// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2005.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

#include "Portals.h"

WM3_WINDOW_APPLICATION(Portals);

//----------------------------------------------------------------------------
Portals::Portals ()
    :
    WindowApplication3("Portals",0,0,640,480,ColorRGB(0.9f,0.9f,0.9f))
{
}
//----------------------------------------------------------------------------
bool Portals::OnInitialize ()
{
    if ( !WindowApplication3::OnInitialize() )
        return false;

    // set up camera
    m_spkCamera->SetFrustum(-0.055f,0.055f,-0.04125f,0.04125f,0.1f,100.0f);
    Vector3f kCLoc(0.0f,0.0f,1.0f);
    Vector3f kCDir(0.0f,1.0f,0.0f);
    Vector3f kCUp(0.0f,0.0f,1.0f);
    Vector3f kCRight = kCDir.Cross(kCUp);
    m_spkCamera->SetFrame(kCLoc,kCDir,kCUp,kCRight);

    // set up scene
    m_spkScene = new Node;
    m_spkWireframe = new WireframeState;
    m_spkScene->SetGlobalState(m_spkWireframe);

    if ( !InitializeTextures() )
        return true;

    ConvexRegionManager* pkCRM = CreateBspTree();
    pkCRM->AttachOutside(CreateOutside());
    m_spkScene->AttachChild(pkCRM);

    // initial update of objects
    m_spkScene->UpdateGS();
    m_spkScene->UpdateRS();

#if 1
    InitializeCameraMotion(0.001f,0.001f);
#else
    // Enable this to see the problem with eyepoint outside the environment,
    // but the near plane inside.  The initial configuration has the eyepoint
    // outside, but the near plane partially inside the environment.  Press
    // the UP-ARROW key a couple of times and see the inside pop into view.
    kCLoc = Vector3f(-0.74392152f,-5.0354514f,1.0f);
    kCDir = Vector3f(-0.65598810f,0.75463903f,0.0f);
    kCUp = Vector3f(0.0f,0.0f,1.0f);
    kCRight = kCDir.Cross(kCUp);
    m_spkCamera->SetFrame(kCLoc,kCDir,kCUp,kCRight);
    m_fTrnSpeed = 0.0001f;
    InitializeCameraMotion(0.0001f,0.001f);
#endif

    return true;
}
//----------------------------------------------------------------------------
void Portals::OnTerminate ()
{
    m_spkScene = 0;
    m_spkWireframe = 0;
    m_spkCeiling = 0;
    m_spkFloor = 0;
    m_spkWall1 = 0;
    m_spkWall2 = 0;
    m_spkAgate = 0;
    m_spkBark = 0;
    m_spkSky = 0;
    m_spkWater = 0;
    WindowApplication3::OnTerminate();
}
//----------------------------------------------------------------------------
void Portals::OnIdle ()
{
    MeasureTime();

    MoveCamera();

    m_pkRenderer->ClearBuffers();
    if ( m_pkRenderer->BeginScene() )
    {
        m_pkRenderer->DrawScene(m_spkScene);
        DrawFrameRate(8,GetHeight()-8,ColorRGBA::WHITE);
        m_pkRenderer->EndScene();
    }
    m_pkRenderer->DisplayBackBuffer();

    UpdateFrameCount();
}
//----------------------------------------------------------------------------
bool Portals::OnKeyDown (unsigned char ucKey, int iX, int iY)
{
    if ( WindowApplication3::OnKeyDown(ucKey,iX,iY) )
        return true;

    switch ( ucKey )
    {
    case 'w':
    case 'W':
        m_spkWireframe->Enabled = !m_spkWireframe->Enabled;
        return true;

    case 's':
    case 'S':
        TestStream();
        return true;
    }

    return false;
}
//----------------------------------------------------------------------------
void Portals::CreateCenterCube (ImagePtr& rspkFloor,
    ImagePtr& rspkCeiling, ImagePtr& rspkWall, ImagePtr& rspkPicture0,
    ImagePtr& rspkPicture1, ImagePtr& rspkPicture2, ImagePtr& rspkPicture3,
    Node*& rpkCube, Portal**& rapkPortal)
{
    rpkCube = new Node(7);

    // walls
    Vector3f* akVertex = new Vector3f[24];
    akVertex[ 0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[ 1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[ 2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[ 3] = Vector3f(-1.0f,+1.0f,0.0f);
    akVertex[ 4] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[ 5] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[ 6] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[ 7] = Vector3f(-1.0f,+1.0f,2.0f);
    akVertex[ 8] = Vector3f(+0.5f,-1.0f,0.0f);
    akVertex[ 9] = Vector3f(+0.5f,-1.0f,1.5f);
    akVertex[10] = Vector3f(-0.5f,-1.0f,1.5f);
    akVertex[11] = Vector3f(-0.5f,-1.0f,0.0f);
    akVertex[12] = Vector3f(-0.5f,+1.0f,0.0f);
    akVertex[13] = Vector3f(-0.5f,+1.0f,1.5f);
    akVertex[14] = Vector3f(+0.5f,+1.0f,1.5f);
    akVertex[15] = Vector3f(+0.5f,+1.0f,0.0f);
    akVertex[16] = Vector3f(+1.0f,+0.5f,0.0f);
    akVertex[17] = Vector3f(+1.0f,+0.5f,1.5f);
    akVertex[18] = Vector3f(+1.0f,-0.5f,1.5f);
    akVertex[19] = Vector3f(+1.0f,-0.5f,0.0f);
    akVertex[20] = Vector3f(-1.0f,-0.5f,0.0f);
    akVertex[21] = Vector3f(-1.0f,-0.5f,1.5f);
    akVertex[22] = Vector3f(-1.0f,+0.5f,1.5f);
    akVertex[23] = Vector3f(-1.0f,+0.5f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(24,akVertex);

    Vector2f* akUV = new Vector2f[24];
    akUV[ 0] = Vector2f(0.00f,0.00f);
    akUV[ 1] = Vector2f(1.00f,0.00f);
    akUV[ 2] = Vector2f(0.00f,0.00f);
    akUV[ 3] = Vector2f(1.00f,0.00f);
    akUV[ 4] = Vector2f(0.00f,1.00f);
    akUV[ 5] = Vector2f(1.00f,1.00f);
    akUV[ 6] = Vector2f(0.00f,1.00f);
    akUV[ 7] = Vector2f(1.00f,1.00f);
    akUV[ 8] = Vector2f(0.75f,0.00f);
    akUV[ 9] = Vector2f(0.75f,0.75f);
    akUV[10] = Vector2f(0.25f,0.75f);
    akUV[11] = Vector2f(0.25f,0.00f);
    akUV[12] = Vector2f(0.75f,0.00f);
    akUV[13] = Vector2f(0.75f,0.75f);
    akUV[14] = Vector2f(0.25f,0.75f);
    akUV[15] = Vector2f(0.25f,0.00f);
    akUV[16] = Vector2f(0.25f,0.00f);
    akUV[17] = Vector2f(0.25f,0.75f);
    akUV[18] = Vector2f(0.75f,0.75f);
    akUV[19] = Vector2f(0.75f,0.00f);
    akUV[20] = Vector2f(0.25f,0.00f);
    akUV[21] = Vector2f(0.25f,0.75f);
    akUV[22] = Vector2f(0.75f,0.75f);
    akUV[23] = Vector2f(0.75f,0.00f);
    Vector2fArray* pkUVs = new Vector2fArray(24,akUV);

    int* aiIndex = new int[72];
    aiIndex[ 0] =  1;  aiIndex[ 1] =  8;  aiIndex[ 2] =  9;
    aiIndex[ 3] =  1;  aiIndex[ 4] =  9;  aiIndex[ 5] =  5;
    aiIndex[ 6] =  5;  aiIndex[ 7] =  9;  aiIndex[ 8] =  4;
    aiIndex[ 9] =  9;  aiIndex[10] = 10;  aiIndex[11] =  4;
    aiIndex[12] = 10;  aiIndex[13] =  0;  aiIndex[14] =  4;
    aiIndex[15] = 11;  aiIndex[16] =  0;  aiIndex[17] = 10;
    aiIndex[18] =  3;  aiIndex[19] = 12;  aiIndex[20] = 13;
    aiIndex[21] =  3;  aiIndex[22] = 13;  aiIndex[23] =  7;
    aiIndex[24] =  7;  aiIndex[25] = 13;  aiIndex[26] =  6;
    aiIndex[27] = 13;  aiIndex[28] = 14;  aiIndex[29] =  6;
    aiIndex[30] = 14;  aiIndex[31] =  2;  aiIndex[32] =  6;
    aiIndex[33] = 15;  aiIndex[34] =  2;  aiIndex[35] = 14;
    aiIndex[36] =  2;  aiIndex[37] = 16;  aiIndex[38] = 17;
    aiIndex[39] =  2;  aiIndex[40] = 17;  aiIndex[41] =  6;
    aiIndex[42] =  6;  aiIndex[43] = 17;  aiIndex[44] =  5;
    aiIndex[45] = 17;  aiIndex[46] = 18;  aiIndex[47] =  5;
    aiIndex[48] = 18;  aiIndex[49] =  1;  aiIndex[50] =  5;
    aiIndex[51] = 19;  aiIndex[52] =  1;  aiIndex[53] = 18;
    aiIndex[54] =  0;  aiIndex[55] = 20;  aiIndex[56] = 21;
    aiIndex[57] =  0;  aiIndex[58] = 21;  aiIndex[59] =  4;
    aiIndex[60] =  4;  aiIndex[61] = 21;  aiIndex[62] =  7;
    aiIndex[63] = 21;  aiIndex[64] = 22;  aiIndex[65] =  7;
    aiIndex[66] = 22;  aiIndex[67] =  3;  aiIndex[68] =  7;
    aiIndex[69] = 23;  aiIndex[70] =  3;  aiIndex[71] = 22;
    IntArray* pkIndices = new IntArray(72,aiIndex);

    TriMesh* pkMesh = new TriMesh(pkVertices,pkIndices,false);
    Texture* pkTexture = new Texture(rspkWall);
    TextureEffect* pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // portals
    rapkPortal = new Portal*[4];

    Vector3f* akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[11];
    akModelVertex[1] = akVertex[10];
    akModelVertex[2] = akVertex[ 9];
    akModelVertex[3] = akVertex[ 8];
    rapkPortal[0] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[15];
    akModelVertex[1] = akVertex[14];
    akModelVertex[2] = akVertex[13];
    akModelVertex[3] = akVertex[12];
    rapkPortal[1] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[19];
    akModelVertex[1] = akVertex[18];
    akModelVertex[2] = akVertex[17];
    akModelVertex[3] = akVertex[16];
    rapkPortal[2] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[23];
    akModelVertex[1] = akVertex[22];
    akModelVertex[2] = akVertex[21];
    akModelVertex[3] = akVertex[20];
    rapkPortal[3] = new Portal(4,akModelVertex,0,true);

    // floor
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,0.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkFloor);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // ceiling
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,2.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 2;  aiIndex[2] = 1;
    aiIndex[3] = 0;  aiIndex[4] = 3;  aiIndex[5] = 2;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkCeiling);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // object 0
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-0.875f,-0.625f,0.75f);
    akVertex[1] = Vector3f(-0.875f,-0.625f,1.10f);
    akVertex[2] = Vector3f(-0.625f,-0.875f,1.10f);
    akVertex[3] = Vector3f(-0.625f,-0.875f,0.75f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(1.0f,0.0f);
    akUV[1] = Vector2f(1.0f,1.0f);
    akUV[2] = Vector2f(0.0f,1.0f);
    akUV[3] = Vector2f(0.0f,0.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkPicture0);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // object 1
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(+0.875f,+0.625f,0.75f);
    akVertex[1] = Vector3f(+0.875f,+0.625f,1.10f);
    akVertex[2] = Vector3f(+0.625f,+0.875f,1.10f);
    akVertex[3] = Vector3f(+0.625f,+0.875f,0.75f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(1.0f,0.0f);
    akUV[1] = Vector2f(1.0f,1.0f);
    akUV[2] = Vector2f(0.0f,1.0f);
    akUV[3] = Vector2f(0.0f,0.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkPicture1);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // object 2
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-0.625f,+0.875f,0.75f);
    akVertex[1] = Vector3f(-0.625f,+0.875f,1.10f);
    akVertex[2] = Vector3f(-0.875f,+0.625f,1.10f);
    akVertex[3] = Vector3f(-0.875f,+0.625f,0.75f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(1.0f,0.0f);
    akUV[1] = Vector2f(1.0f,1.0f);
    akUV[2] = Vector2f(0.0f,1.0f);
    akUV[3] = Vector2f(0.0f,0.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkPicture2);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // object 3
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(+0.625f,-0.875f,0.75f);
    akVertex[1] = Vector3f(+0.625f,-0.875f,1.10f);
    akVertex[2] = Vector3f(+0.875f,-0.625f,1.10f);
    akVertex[3] = Vector3f(+0.875f,-0.625f,0.75f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(1.0f,0.0f);
    akUV[1] = Vector2f(1.0f,1.0f);
    akUV[2] = Vector2f(0.0f,1.0f);
    akUV[3] = Vector2f(0.0f,0.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkPicture3);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);
}
//----------------------------------------------------------------------------
void Portals::CreateAxisConnector (ImagePtr& rspkFloor,
    ImagePtr& rspkCeiling, ImagePtr& rspkWall, Node*& rpkCube,
    Portal**& rapkPortal)
{
    rpkCube = new Node(3);

    // walls
    Vector3f* akVertex = new Vector3f[16];
    akVertex[ 0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[ 1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[ 2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[ 3] = Vector3f(-1.0f,+1.0f,0.0f);
    akVertex[ 4] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[ 5] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[ 6] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[ 7] = Vector3f(-1.0f,+1.0f,2.0f);
    akVertex[ 8] = Vector3f(+0.5f,-1.0f,0.0f);
    akVertex[ 9] = Vector3f(+0.5f,-1.0f,1.5f);
    akVertex[10] = Vector3f(-0.5f,-1.0f,1.5f);
    akVertex[11] = Vector3f(-0.5f,-1.0f,0.0f);
    akVertex[12] = Vector3f(-0.5f,+1.0f,0.0f);
    akVertex[13] = Vector3f(-0.5f,+1.0f,1.5f);
    akVertex[14] = Vector3f(+0.5f,+1.0f,1.5f);
    akVertex[15] = Vector3f(+0.5f,+1.0f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(16,akVertex);

    Vector2f* akUV = new Vector2f[16];
    akUV[ 0] = Vector2f(0.00f,0.00f);
    akUV[ 1] = Vector2f(1.00f,0.00f);
    akUV[ 2] = Vector2f(0.00f,0.00f);
    akUV[ 3] = Vector2f(1.00f,0.00f);
    akUV[ 4] = Vector2f(0.00f,1.00f);
    akUV[ 5] = Vector2f(1.00f,1.00f);
    akUV[ 6] = Vector2f(0.00f,1.00f);
    akUV[ 7] = Vector2f(1.00f,1.00f);
    akUV[ 8] = Vector2f(0.75f,0.00f);
    akUV[ 9] = Vector2f(0.75f,0.75f);
    akUV[10] = Vector2f(0.25f,0.75f);
    akUV[11] = Vector2f(0.25f,0.00f);
    akUV[12] = Vector2f(0.75f,0.00f);
    akUV[13] = Vector2f(0.75f,0.75f);
    akUV[14] = Vector2f(0.25f,0.75f);
    akUV[15] = Vector2f(0.25f,0.00f);
    Vector2fArray* pkUVs = new Vector2fArray(16,akUV);

    int* aiIndex = new int[48];
    aiIndex[ 0] =  1;  aiIndex[ 1] =  8;  aiIndex[ 2] =  9;
    aiIndex[ 3] =  1;  aiIndex[ 4] =  9;  aiIndex[ 5] =  5;
    aiIndex[ 6] =  5;  aiIndex[ 7] =  9;  aiIndex[ 8] =  4;
    aiIndex[ 9] =  9;  aiIndex[10] = 10;  aiIndex[11] =  4;
    aiIndex[12] = 10;  aiIndex[13] =  0;  aiIndex[14] =  4;
    aiIndex[15] = 11;  aiIndex[16] =  0;  aiIndex[17] = 10;
    aiIndex[18] =  3;  aiIndex[19] = 12;  aiIndex[20] = 13;
    aiIndex[21] =  3;  aiIndex[22] = 13;  aiIndex[23] =  7;
    aiIndex[24] =  7;  aiIndex[25] = 13;  aiIndex[26] =  6;
    aiIndex[27] = 13;  aiIndex[28] = 14;  aiIndex[29] =  6;
    aiIndex[30] = 14;  aiIndex[31] =  2;  aiIndex[32] =  6;
    aiIndex[33] = 15;  aiIndex[34] =  2;  aiIndex[35] = 14;
    aiIndex[36] =  0;  aiIndex[37] =  7;  aiIndex[38] =  4;
    aiIndex[39] =  0;  aiIndex[40] =  3;  aiIndex[41] =  7;
    aiIndex[42] =  2;  aiIndex[43] =  5;  aiIndex[44] =  6;
    aiIndex[45] =  2;  aiIndex[46] =  1;  aiIndex[47] =  5;
    IntArray* pkIndices = new IntArray(48,aiIndex);

    TriMesh* pkMesh = new TriMesh(pkVertices,pkIndices,false);
    Texture* pkTexture = new Texture(rspkWall);
    TextureEffect* pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // portals
    rapkPortal = new Portal*[2];

    Vector3f* akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[11];
    akModelVertex[1] = akVertex[10];
    akModelVertex[2] = akVertex[ 9];
    akModelVertex[3] = akVertex[ 8];
    rapkPortal[0] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[15];
    akModelVertex[1] = akVertex[14];
    akModelVertex[2] = akVertex[13];
    akModelVertex[3] = akVertex[12];
    rapkPortal[1] = new Portal(4,akModelVertex,0,true);

    // floor
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,0.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkFloor);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // ceiling
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,2.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 2;  aiIndex[2] = 1;
    aiIndex[3] = 0;  aiIndex[4] = 3;  aiIndex[5] = 2;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkCeiling);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);
}
//----------------------------------------------------------------------------
void Portals::CreateEndCube (ImagePtr& rspkFloor, ImagePtr& rspkCeiling,
    ImagePtr& rspkWall, Node*& rpkCube, Portal**& rapkPortal)
{
    rpkCube = new Node(3);

    // walls
    Vector3f* akVertex = new Vector3f[20];
    akVertex[ 0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[ 1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[ 2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[ 3] = Vector3f(-1.0f,+1.0f,0.0f);
    akVertex[ 4] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[ 5] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[ 6] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[ 7] = Vector3f(-1.0f,+1.0f,2.0f);
    akVertex[ 8] = Vector3f(+0.5f,-1.0f,0.0f);
    akVertex[ 9] = Vector3f(+0.5f,-1.0f,1.5f);
    akVertex[10] = Vector3f(-0.5f,-1.0f,1.5f);
    akVertex[11] = Vector3f(-0.5f,-1.0f,0.0f);
    akVertex[12] = Vector3f(-0.5f,+1.0f,0.0f);
    akVertex[13] = Vector3f(-0.5f,+1.0f,1.5f);
    akVertex[14] = Vector3f(+0.5f,+1.0f,1.5f);
    akVertex[15] = Vector3f(+0.5f,+1.0f,0.0f);
    akVertex[16] = Vector3f(+1.0f,+0.5f,0.0f);
    akVertex[17] = Vector3f(+1.0f,+0.5f,1.5f);
    akVertex[18] = Vector3f(+1.0f,-0.5f,1.5f);
    akVertex[19] = Vector3f(+1.0f,-0.5f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(20,akVertex);

    Vector2f* akUV = new Vector2f[20];
    akUV[ 0] = Vector2f(0.00f,0.00f);
    akUV[ 1] = Vector2f(1.00f,0.00f);
    akUV[ 2] = Vector2f(0.00f,0.00f);
    akUV[ 3] = Vector2f(1.00f,0.00f);
    akUV[ 4] = Vector2f(0.00f,1.00f);
    akUV[ 5] = Vector2f(1.00f,1.00f);
    akUV[ 6] = Vector2f(0.00f,1.00f);
    akUV[ 7] = Vector2f(1.00f,1.00f);
    akUV[ 8] = Vector2f(0.75f,0.00f);
    akUV[ 9] = Vector2f(0.75f,0.75f);
    akUV[10] = Vector2f(0.25f,0.75f);
    akUV[11] = Vector2f(0.25f,0.00f);
    akUV[12] = Vector2f(0.75f,0.00f);
    akUV[13] = Vector2f(0.75f,0.75f);
    akUV[14] = Vector2f(0.25f,0.75f);
    akUV[15] = Vector2f(0.25f,0.00f);
    akUV[16] = Vector2f(0.25f,0.00f);
    akUV[17] = Vector2f(0.25f,0.75f);
    akUV[18] = Vector2f(0.75f,0.75f);
    akUV[19] = Vector2f(0.75f,0.00f);
    Vector2fArray* pkUVs = new Vector2fArray(20,akUV);

    int* aiIndex = new int[60];
    aiIndex[ 0] =  1;  aiIndex[ 1] =  8;  aiIndex[ 2] =  9;
    aiIndex[ 3] =  1;  aiIndex[ 4] =  9;  aiIndex[ 5] =  5;
    aiIndex[ 6] =  5;  aiIndex[ 7] =  9;  aiIndex[ 8] =  4;
    aiIndex[ 9] =  9;  aiIndex[10] = 10;  aiIndex[11] =  4;
    aiIndex[12] = 10;  aiIndex[13] =  0;  aiIndex[14] =  4;
    aiIndex[15] = 11;  aiIndex[16] =  0;  aiIndex[17] = 10;
    aiIndex[18] =  3;  aiIndex[19] = 12;  aiIndex[20] = 13;
    aiIndex[21] =  3;  aiIndex[22] = 13;  aiIndex[23] =  7;
    aiIndex[24] =  7;  aiIndex[25] = 13;  aiIndex[26] =  6;
    aiIndex[27] = 13;  aiIndex[28] = 14;  aiIndex[29] =  6;
    aiIndex[30] = 14;  aiIndex[31] =  2;  aiIndex[32] =  6;
    aiIndex[33] = 15;  aiIndex[34] =  2;  aiIndex[35] = 14;
    aiIndex[36] =  2;  aiIndex[37] = 16;  aiIndex[38] = 17;
    aiIndex[39] =  2;  aiIndex[40] = 17;  aiIndex[41] =  6;
    aiIndex[42] =  6;  aiIndex[43] = 17;  aiIndex[44] =  5;
    aiIndex[45] = 17;  aiIndex[46] = 18;  aiIndex[47] =  5;
    aiIndex[48] = 18;  aiIndex[49] =  1;  aiIndex[50] =  5;
    aiIndex[51] = 19;  aiIndex[52] =  1;  aiIndex[53] = 18;
    aiIndex[54] =  0;  aiIndex[55] =  7;  aiIndex[56] =  4;
    aiIndex[57] =  0;  aiIndex[58] =  3;  aiIndex[59] =  7;
    IntArray* pkIndices = new IntArray(60,aiIndex);

    TriMesh* pkMesh = new TriMesh(pkVertices,pkIndices,false);
    Texture* pkTexture = new Texture(rspkWall);
    TextureEffect* pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // portals
    rapkPortal = new Portal*[3];

    Vector3f* akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[11];
    akModelVertex[1] = akVertex[10];
    akModelVertex[2] = akVertex[ 9];
    akModelVertex[3] = akVertex[ 8];
    rapkPortal[0] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[15];
    akModelVertex[1] = akVertex[14];
    akModelVertex[2] = akVertex[13];
    akModelVertex[3] = akVertex[12];
    rapkPortal[1] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[19];
    akModelVertex[1] = akVertex[18];
    akModelVertex[2] = akVertex[17];
    akModelVertex[3] = akVertex[16];
    rapkPortal[2] = new Portal(4,akModelVertex,0,true);

    // floor
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,0.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkFloor);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // ceiling
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,2.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(4,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 2;  aiIndex[2] = 1;
    aiIndex[3] = 0;  aiIndex[4] = 3;  aiIndex[5] = 2;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkCeiling);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);
}
//----------------------------------------------------------------------------
void Portals::CreateDiagonalConnector (ImagePtr& rspkFloor,
    ImagePtr& rspkCeiling, ImagePtr& rspkWall, Node*& rpkCube,
    Portal**& rapkPortal)
{
    rpkCube = new Node(3);

    // walls
    Vector3f* akVertex = new Vector3f[16];
    akVertex[ 0] = Vector3f(3.0f,1.0f,0.0f);
    akVertex[ 1] = Vector3f(5.0f,1.0f,0.0f);
    akVertex[ 2] = Vector3f(1.0f,5.0f,0.0f);
    akVertex[ 3] = Vector3f(1.0f,3.0f,0.0f);
    akVertex[ 4] = Vector3f(3.0f,1.0f,2.0f);
    akVertex[ 5] = Vector3f(5.0f,1.0f,2.0f);
    akVertex[ 6] = Vector3f(1.0f,5.0f,2.0f);
    akVertex[ 7] = Vector3f(1.0f,3.0f,2.0f);
    akVertex[ 8] = Vector3f(4.5f,1.0f,0.0f);
    akVertex[ 9] = Vector3f(4.5f,1.0f,1.5f);
    akVertex[10] = Vector3f(3.5f,1.0f,1.5f);
    akVertex[11] = Vector3f(3.5f,1.0f,0.0f);
    akVertex[12] = Vector3f(1.0f,3.5f,0.0f);
    akVertex[13] = Vector3f(1.0f,3.5f,1.5f);
    akVertex[14] = Vector3f(1.0f,4.5f,1.5f);
    akVertex[15] = Vector3f(1.0f,4.5f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(16,akVertex);

    Vector2f* akUV = new Vector2f[16];
    akUV[ 0] = Vector2f(0.00f,0.00f);
    akUV[ 1] = Vector2f(1.00f,0.00f);
    akUV[ 2] = Vector2f(0.00f,0.00f);
    akUV[ 3] = Vector2f(1.00f,0.00f);
    akUV[ 4] = Vector2f(0.00f,1.00f);
    akUV[ 5] = Vector2f(1.00f,1.00f);
    akUV[ 6] = Vector2f(0.00f,1.00f);
    akUV[ 7] = Vector2f(1.00f,1.00f);
    akUV[ 8] = Vector2f(0.75f,0.00f);
    akUV[ 9] = Vector2f(0.75f,0.75f);
    akUV[10] = Vector2f(0.25f,0.75f);
    akUV[11] = Vector2f(0.25f,0.00f);
    akUV[12] = Vector2f(0.75f,0.00f);
    akUV[13] = Vector2f(0.75f,0.75f);
    akUV[14] = Vector2f(0.25f,0.75f);
    akUV[15] = Vector2f(0.25f,0.00f);
    Vector2fArray* pkUVs = new Vector2fArray(16,akUV);

    int* aiIndex = new int[48];
    aiIndex[ 0] =  1;  aiIndex[ 1] =  8;  aiIndex[ 2] =  9;
    aiIndex[ 3] =  1;  aiIndex[ 4] =  9;  aiIndex[ 5] =  5;
    aiIndex[ 6] =  5;  aiIndex[ 7] =  9;  aiIndex[ 8] =  4;
    aiIndex[ 9] =  9;  aiIndex[10] = 10;  aiIndex[11] =  4;
    aiIndex[12] = 10;  aiIndex[13] =  0;  aiIndex[14] =  4;
    aiIndex[15] = 11;  aiIndex[16] =  0;  aiIndex[17] = 10;
    aiIndex[18] =  3;  aiIndex[19] = 12;  aiIndex[20] = 13;
    aiIndex[21] =  3;  aiIndex[22] = 13;  aiIndex[23] =  7;
    aiIndex[24] =  7;  aiIndex[25] = 13;  aiIndex[26] =  6;
    aiIndex[27] = 13;  aiIndex[28] = 14;  aiIndex[29] =  6;
    aiIndex[30] = 14;  aiIndex[31] =  2;  aiIndex[32] =  6;
    aiIndex[33] = 15;  aiIndex[34] =  2;  aiIndex[35] = 14;
    aiIndex[36] =  0;  aiIndex[37] =  7;  aiIndex[38] =  4;
    aiIndex[39] =  0;  aiIndex[40] =  3;  aiIndex[41] =  7;
    aiIndex[42] =  2;  aiIndex[43] =  5;  aiIndex[44] =  6;
    aiIndex[45] =  2;  aiIndex[46] =  1;  aiIndex[47] =  5;
    IntArray* pkIndices = new IntArray(48,aiIndex);

    TriMesh* pkMesh = new TriMesh(pkVertices,pkIndices,false);
    Texture* pkTexture = new Texture(rspkWall);
    TextureEffect* pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // portals
    rapkPortal = new Portal*[2];

    Vector3f* akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[11];
    akModelVertex[1] = akVertex[10];
    akModelVertex[2] = akVertex[ 9];
    akModelVertex[3] = akVertex[ 8];
    rapkPortal[0] = new Portal(4,akModelVertex,0,true);

    akModelVertex = new Vector3f[4];
    akModelVertex[0] = akVertex[15];
    akModelVertex[1] = akVertex[14];
    akModelVertex[2] = akVertex[13];
    akModelVertex[3] = akVertex[12];
    rapkPortal[1] = new Portal(4,akModelVertex,0,true);

    // floor
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(3.0f,1.0f,0.0f);
    akVertex[1] = Vector3f(5.0f,1.0f,0.0f);
    akVertex[2] = Vector3f(1.0f,5.0f,0.0f);
    akVertex[3] = Vector3f(1.0f,3.0f,0.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(16,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkFloor);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);

    // ceiling
    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(3.0f,1.0f,2.0f);
    akVertex[1] = Vector3f(5.0f,1.0f,2.0f);
    akVertex[2] = Vector3f(1.0f,5.0f,2.0f);
    akVertex[3] = Vector3f(1.0f,3.0f,2.0f);
    pkVertices = new Vector3fArray(4,akVertex);

    akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    pkUVs = new Vector2fArray(16,akUV);

    aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 2;  aiIndex[2] = 1;
    aiIndex[3] = 0;  aiIndex[4] = 3;  aiIndex[5] = 2;
    pkIndices = new IntArray(6,aiIndex);

    pkMesh = new TriMesh(pkVertices,pkIndices,false);
    pkTexture = new Texture(rspkCeiling);
    pkEffect = new TextureEffect(pkTexture,pkUVs);
    pkMesh->SetEffect(pkEffect);
    rpkCube->AttachChild(pkMesh);
}
//----------------------------------------------------------------------------
TriMesh* Portals::CreateOutside ()
{
    const int iVertexQuantity = 40;
    Vector3f* akVertex = new Vector3f[iVertexQuantity];
    akVertex[0] = Vector3f(-1.0f,-1.0f,2.0f);
    akVertex[1] = Vector3f(+1.0f,-1.0f,2.0f);
    akVertex[2] = Vector3f(+1.0f,+1.0f,2.0f);
    akVertex[3] = Vector3f(-1.0f,+1.0f,2.0f);
    akVertex[4] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[5] = Vector3f(+1.0f,-1.0f,0.0f);
    akVertex[6] = Vector3f(+1.0f,+1.0f,0.0f);
    akVertex[7] = Vector3f(-1.0f,+1.0f,0.0f);

    Vector3f kTrn(4.0f,0.0f,0.0f);
    int i, j;
    for (i = 0, j = 8; i < 8; i++, j++)
        akVertex[j] = akVertex[i] + kTrn;

    kTrn = Vector3f(0.0f,4.0f,0.0f);
    for (i = 0, j = 16; i < 8; i++, j++)
        akVertex[j] = akVertex[i] + kTrn;

    kTrn = Vector3f(-4.0f,0.0f,0.0f);
    for (i = 0, j = 24; i < 8; i++, j++)
        akVertex[j] = akVertex[i] + kTrn;

    kTrn = Vector3f(0.0f,-4.0f,0.0f);
    for (i = 0, j = 32; i < 8; i++, j++)
        akVertex[j] = akVertex[i] + kTrn;

    Vector3fArray* pkVertices = new Vector3fArray(iVertexQuantity,akVertex);

    ColorRGB* akColor = new ColorRGB[iVertexQuantity];
    for (i = 0; i < iVertexQuantity; i++)
    {
        akColor[i].R() = Mathf::UnitRandom();
        akColor[i].G() = Mathf::UnitRandom();
        akColor[i].B() = Mathf::UnitRandom();
    }
    ColorRGBArray* pkColors = new ColorRGBArray(iVertexQuantity,akColor);

    const int iTriangleQuantity = 92;
    int* aiIndex = new int[3*iTriangleQuantity];
    aiIndex[ 0] =  0;  aiIndex[ 1] =  1;  aiIndex[ 2] =  2;
    aiIndex[ 3] =  0;  aiIndex[ 4] =  2;  aiIndex[ 5] =  3;
    aiIndex[ 6] =  1;  aiIndex[ 7] = 11;  aiIndex[ 8] =  2;
    aiIndex[ 9] =  1;  aiIndex[10] =  8;  aiIndex[11] = 11;
    aiIndex[12] =  8;  aiIndex[13] = 10;  aiIndex[14] = 11;
    aiIndex[15] =  8;  aiIndex[16] =  9;  aiIndex[17] = 10;
    aiIndex[18] = 25;  aiIndex[19] =  0;  aiIndex[20] =  3;
    aiIndex[21] = 25;  aiIndex[22] =  3;  aiIndex[23] = 26;
    aiIndex[24] = 24;  aiIndex[25] = 25;  aiIndex[26] = 26;
    aiIndex[27] = 24;  aiIndex[28] = 26;  aiIndex[29] = 27;
    aiIndex[30] =  3;  aiIndex[31] =  2;  aiIndex[32] = 17;
    aiIndex[33] =  3;  aiIndex[34] = 17;  aiIndex[35] = 16;
    aiIndex[36] = 16;  aiIndex[37] = 17;  aiIndex[38] = 18;
    aiIndex[39] = 16;  aiIndex[40] = 18;  aiIndex[41] = 19;
    aiIndex[42] = 35;  aiIndex[43] =  1;  aiIndex[44] =  0;
    aiIndex[45] = 35;  aiIndex[46] = 34;  aiIndex[47] =  1;
    aiIndex[48] = 32;  aiIndex[49] = 34;  aiIndex[50] = 35;
    aiIndex[51] = 32;  aiIndex[52] = 33;  aiIndex[53] = 34;
    aiIndex[54] = 27;  aiIndex[55] = 16;  aiIndex[56] = 19;
    aiIndex[57] = 27;  aiIndex[58] = 26;  aiIndex[59] = 16;
    aiIndex[60] = 17;  aiIndex[61] = 11;  aiIndex[62] = 18;
    aiIndex[63] = 18;  aiIndex[64] = 11;  aiIndex[65] = 10;
    aiIndex[66] = 24;  aiIndex[67] = 32;  aiIndex[68] = 25;
    aiIndex[69] = 25;  aiIndex[70] = 32;  aiIndex[71] = 35;
    aiIndex[72] = 34;  aiIndex[73] =  9;  aiIndex[74] =  8;
    aiIndex[75] = 34;  aiIndex[76] = 33;  aiIndex[77] =  9;

    for (i = 0, j = 78; i < 26; i++)
    {
        aiIndex[j++] = 4 + aiIndex[3*i];
        aiIndex[j++] = 4 + aiIndex[3*i+2];
        aiIndex[j++] = 4 + aiIndex[3*i+1];
    }

    aiIndex[156] =  6;  aiIndex[157] =  2;  aiIndex[158] = 11;
    aiIndex[159] =  6;  aiIndex[160] = 11;  aiIndex[161] = 15;
    aiIndex[162] = 21;  aiIndex[163] = 17;  aiIndex[164] =  2;
    aiIndex[165] = 21;  aiIndex[166] =  2;  aiIndex[167] =  6;
    aiIndex[168] = 15;  aiIndex[169] = 11;  aiIndex[170] = 17;
    aiIndex[171] = 15;  aiIndex[172] = 17;  aiIndex[173] = 21;
    aiIndex[174] = 12;  aiIndex[175] =  8;  aiIndex[176] =  1;
    aiIndex[177] = 12;  aiIndex[178] =  1;  aiIndex[179] =  5;
    aiIndex[180] =  5;  aiIndex[181] =  1;  aiIndex[182] = 34;
    aiIndex[183] =  5;  aiIndex[184] = 34;  aiIndex[185] = 38;
    aiIndex[186] = 38;  aiIndex[187] = 34;  aiIndex[188] =  8;
    aiIndex[189] = 38;  aiIndex[190] =  8;  aiIndex[191] = 12;
    aiIndex[192] =  4;  aiIndex[193] =  0;  aiIndex[194] = 25;
    aiIndex[195] =  4;  aiIndex[196] = 25;  aiIndex[197] = 29;
    aiIndex[198] = 39;  aiIndex[199] = 35;  aiIndex[200] =  0;
    aiIndex[201] = 39;  aiIndex[202] =  0;  aiIndex[203] =  4;
    aiIndex[204] = 29;  aiIndex[205] = 25;  aiIndex[206] = 35;
    aiIndex[207] = 29;  aiIndex[208] = 35;  aiIndex[209] = 39;
    aiIndex[210] =  7;  aiIndex[211] =  3;  aiIndex[212] = 16;
    aiIndex[213] =  7;  aiIndex[214] = 16;  aiIndex[215] = 20;
    aiIndex[216] = 30;  aiIndex[217] = 26;  aiIndex[218] =  3;
    aiIndex[219] = 30;  aiIndex[220] =  3;  aiIndex[221] =  7;
    aiIndex[222] = 20;  aiIndex[223] = 16;  aiIndex[224] = 26;
    aiIndex[225] = 20;  aiIndex[226] = 26;  aiIndex[227] = 30;
    aiIndex[228] = 14;  aiIndex[229] = 10;  aiIndex[230] =  9;
    aiIndex[231] = 14;  aiIndex[232] =  9;  aiIndex[233] = 13;
    aiIndex[234] = 22;  aiIndex[235] = 18;  aiIndex[236] = 10;
    aiIndex[237] = 22;  aiIndex[238] = 10;  aiIndex[239] = 14;
    aiIndex[240] = 23;  aiIndex[241] = 19;  aiIndex[242] = 18;
    aiIndex[243] = 23;  aiIndex[244] = 18;  aiIndex[245] = 22;
    aiIndex[246] = 31;  aiIndex[247] = 27;  aiIndex[248] = 19;
    aiIndex[249] = 31;  aiIndex[250] = 19;  aiIndex[251] = 23;
    aiIndex[252] = 28;  aiIndex[253] = 24;  aiIndex[254] = 27;
    aiIndex[255] = 28;  aiIndex[256] = 27;  aiIndex[257] = 31;
    aiIndex[258] = 36;  aiIndex[259] = 32;  aiIndex[260] = 24;
    aiIndex[261] = 36;  aiIndex[262] = 24;  aiIndex[263] = 28;
    aiIndex[264] = 37;  aiIndex[265] = 33;  aiIndex[266] = 32;
    aiIndex[267] = 37;  aiIndex[268] = 32;  aiIndex[269] = 36;
    aiIndex[270] = 13;  aiIndex[271] =  9;  aiIndex[272] = 33;
    aiIndex[273] = 13;  aiIndex[274] = 33;  aiIndex[275] = 37;
    IntArray* pkIndices = new IntArray(3*iTriangleQuantity,aiIndex);

    TriMesh* pkMesh = new TriMesh(pkVertices,pkIndices,false);
    VertexColorEffect* pkEffect = new VertexColorEffect(pkColors);
    pkMesh->SetEffect(pkEffect);

    return pkMesh;
}
//----------------------------------------------------------------------------
ConvexRegionManager* Portals::CreateBspTree ()
{
    // construction of tree in BspTree.txt.
    ConvexRegionManager* pkC = new ConvexRegionManager;
    pkC->SetName("CRM");
    pkC->ModelPlane().Normal = Vector3f(0.0f,0.0f,-1.0f);
    pkC->ModelPlane().Constant = 0.0f;

    BspNode* pkR = new BspNode;
    pkR->SetName("R");
    pkR->ModelPlane().Normal = Vector3f(0.0f,0.0f,1.0f);
    pkR->ModelPlane().Constant = 2.0f;

    BspNode* pkRR = new BspNode;
    pkRR->SetName("RR");
    pkRR->ModelPlane().Normal = Vector3f(1.0f,0.0f,0.0f);
    pkRR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRL = new BspNode;
    pkRRL->SetName("RRL");
    pkRRL->ModelPlane().Normal = Vector3f(0.0f,1.0f,0.0f);
    pkRRL->ModelPlane().Constant = 1.0f;

    BspNode* pkRRLL = new BspNode;
    pkRRLL->SetName("RRLL");
    pkRRLL->ModelPlane().Normal = Vector3f(1.0f,1.0f,0.0f);
    pkRRLL->ModelPlane().Constant = 4.0f;

    BspNode* pkRRLLL = new BspNode;
    pkRRLLL->SetName("RRLLL");
    pkRRLLL->ModelPlane().Normal = Vector3f(1.0f,1.0f,0.0f);
    pkRRLLL->ModelPlane().Constant = 6.0f;

    BspNode* pkRRLR = new BspNode;
    pkRRLR->SetName("RRLR");
    pkRRLR->ModelPlane().Normal = Vector3f(0.0f,-1.0f,0.0f);
    pkRRLR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRLRL = new BspNode;
    pkRRLRL->SetName("RRLRL");
    pkRRLRL->ModelPlane().Normal = Vector3f(1.0f,-1.0f,0.0f);
    pkRRLRL->ModelPlane().Constant = 4.0f;

    BspNode* pkRRLRLL = new BspNode;
    pkRRLRLL->SetName("RRLRLL");
    pkRRLRLL->ModelPlane().Normal = Vector3f(1.0f,-1.0f,0.0f);
    pkRRLRLL->ModelPlane().Constant = 6.0f;

    BspNode* pkRRLRR = new BspNode;
    pkRRLRR->SetName("RRLRR");
    pkRRLRR->ModelPlane().Normal = Vector3f(1.0f,0.0f,0.0f);
    pkRRLRR->ModelPlane().Constant = 3.0f;

    BspNode* pkRRLRRL = new BspNode;
    pkRRLRRL->SetName("RRLRRL");
    pkRRLRRL->ModelPlane().Normal = Vector3f(1.0f,0.0f,0.0f);
    pkRRLRRL->ModelPlane().Constant = 5.0f;

    BspNode* pkRRR = new BspNode;
    pkRRR->SetName("RRR");
    pkRRR->ModelPlane().Normal = Vector3f(-1.0f,0.0f,0.0f);
    pkRRR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRRL = new BspNode;
    pkRRRL->SetName("RRRL");
    pkRRRL->ModelPlane().Normal = Vector3f(0.0f,1.0f,0.0f);
    pkRRRL->ModelPlane().Constant = 1.0f;

    BspNode* pkRRRLL = new BspNode;
    pkRRRLL->SetName("RRRLL");
    pkRRRLL->ModelPlane().Normal = Vector3f(-1.0f,1.0f,0.0f);
    pkRRRLL->ModelPlane().Constant = 4.0f;

    BspNode* pkRRRLLL = new BspNode;
    pkRRRLLL->SetName("RRRLLL");
    pkRRRLLL->ModelPlane().Normal = Vector3f(-1.0f,1.0f,0.0f);
    pkRRRLLL->ModelPlane().Constant = 6.0f;

    BspNode* pkRRRLR = new BspNode;
    pkRRRLR->SetName("RRRLR");
    pkRRRLR->ModelPlane().Normal = Vector3f(0.0f,-1.0f,0.0f);
    pkRRRLR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRRLRL = new BspNode;
    pkRRRLRL->SetName("RRRLRL");
    pkRRRLRL->ModelPlane().Normal = Vector3f(-1.0f,-1.0f,0.0f);
    pkRRRLRL->ModelPlane().Constant = 4.0f;

    BspNode* pkRRRLRLL = new BspNode;
    pkRRRLRLL->SetName("RRRLRLL");
    pkRRRLRLL->ModelPlane().Normal = Vector3f(-1.0f,-1.0f,0.0f);
    pkRRRLRLL->ModelPlane().Constant = 6.0f;

    BspNode* pkRRRLRR = new BspNode;
    pkRRRLRR->SetName("RRRLRR");
    pkRRRLRR->ModelPlane().Normal = Vector3f(-1.0f,0.0f,0.0f);
    pkRRRLRR->ModelPlane().Constant = 3.0f;

    BspNode* pkRRRLRRL = new BspNode;
    pkRRRLRRL->SetName("RRRLRRL");
    pkRRRLRRL->ModelPlane().Normal = Vector3f(-1.0f,0.0f,0.0f);
    pkRRRLRRL->ModelPlane().Constant = 5.0f;

    BspNode* pkRRRR = new BspNode;
    pkRRRR->SetName("RRRR");
    pkRRRR->ModelPlane().Normal = Vector3f(0.0f,1.0f,0.0f);
    pkRRRR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRRRL = new BspNode;
    pkRRRRL->SetName("RRRRL");
    pkRRRRL->ModelPlane().Normal = Vector3f(0.0f,1.0f,0.0f);
    pkRRRRL->ModelPlane().Constant = 3.0f;

    BspNode* pkRRRRLL = new BspNode;
    pkRRRRLL->SetName("RRRRLL");
    pkRRRRLL->ModelPlane().Normal = Vector3f(0.0f,1.0f,0.0f);
    pkRRRRLL->ModelPlane().Constant = 5.0f;

    BspNode* pkRRRRR = new BspNode;
    pkRRRRR->SetName("RRRRR");
    pkRRRRR->ModelPlane().Normal = Vector3f(0.0f,-1.0f,0.0f);
    pkRRRRR->ModelPlane().Constant = 1.0f;

    BspNode* pkRRRRRL = new BspNode;
    pkRRRRRL->SetName("RRRRRL");
    pkRRRRRL->ModelPlane().Normal = Vector3f(0.0f,-1.0f,0.0f);
    pkRRRRRL->ModelPlane().Constant = 3.0f;

    BspNode* pkRRRRRLL = new BspNode;
    pkRRRRRLL->SetName("RRRRRLL");
    pkRRRRRLL->ModelPlane().Normal = Vector3f(0.0f,-1.0f,0.0f);
    pkRRRRRLL->ModelPlane().Constant = 5.0f;

    // create regions and portals
    Node* pkNode;
    Portal** apkPortal;

    CreateCenterCube(m_spkFloor,m_spkWall1,m_spkWall1,m_spkWater,m_spkAgate,
        m_spkBark,m_spkSky,pkNode,apkPortal);
    ConvexRegion* pkC00 = new ConvexRegion(4,apkPortal);
    pkC00->SetName("C00");
    pkC00->AttachChild(pkNode);

    CreateAxisConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,apkPortal);
    ConvexRegion* pkC02 = new ConvexRegion(2,apkPortal);
    pkC02->SetName("C02");
    pkC02->AttachChild(pkNode);
    pkC02->Local.SetTranslate(Vector3f(0.0f,2.0f,0.0f));

    CreateAxisConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,apkPortal);
    ConvexRegion* pkC0m2 = new ConvexRegion(2,apkPortal);
    pkC0m2->SetName("C0m2");
    pkC0m2->AttachChild(pkNode);
    pkC0m2->Local.SetTranslate(Vector3f(0.0f,-2.0f,0.0f));

    CreateAxisConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,apkPortal);
    ConvexRegion* pkC20 = new ConvexRegion(2,apkPortal);
    pkC20->SetName("C20");
    pkC20->AttachChild(pkNode);
    pkC20->Local.SetTranslate(Vector3f(2.0f,0.0f,0.0f));
    pkC20->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::HALF_PI));

    CreateAxisConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,apkPortal);
    ConvexRegion* pkCm20 = new ConvexRegion(2,apkPortal);
    pkCm20->SetName("Cm20");
    pkCm20->AttachChild(pkNode);
    pkCm20->Local.SetTranslate(Vector3f(-2.0f,0.0f,0.0f));
    pkCm20->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::HALF_PI));

    CreateEndCube(m_spkFloor,m_spkCeiling,m_spkWall1,pkNode,apkPortal);
    ConvexRegion* pkC04 = new ConvexRegion(3,apkPortal);
    pkC04->SetName("C04");
    pkC04->AttachChild(pkNode);
    pkC04->Local.SetTranslate(Vector3f(0.0f,4.0f,0.0f));
    pkC04->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        -Mathf::HALF_PI));

    CreateEndCube(m_spkFloor,m_spkCeiling,m_spkWall1,pkNode,apkPortal);
    ConvexRegion* pkC0m4 = new ConvexRegion(3,apkPortal);
    pkC0m4->SetName("C0m4");
    pkC0m4->AttachChild(pkNode);
    pkC0m4->Local.SetTranslate(Vector3f(0.0f,-4.0f,0.0f));
    pkC0m4->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::HALF_PI));

    CreateEndCube(m_spkFloor,m_spkCeiling,m_spkWall1,pkNode,apkPortal);
    ConvexRegion* pkC40 = new ConvexRegion(3,apkPortal);
    pkC40->SetName("C40");
    pkC40->AttachChild(pkNode);
    pkC40->Local.SetTranslate(Vector3f(4.0f,0.0f,0.0f));
    pkC40->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::PI));

    CreateEndCube(m_spkFloor,m_spkCeiling,m_spkWall1,pkNode,apkPortal);
    ConvexRegion* pkCm40 = new ConvexRegion(3,apkPortal);
    pkCm40->SetName("Cm40");
    pkCm40->AttachChild(pkNode);
    pkCm40->Local.SetTranslate(Vector3f(-4.0f,0.0f,0.0f));

    CreateDiagonalConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,
        apkPortal);
    ConvexRegion* pkDPP = new ConvexRegion(2,apkPortal);
    pkDPP->SetName("DPP");
    pkDPP->AttachChild(pkNode);

    CreateDiagonalConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,
        apkPortal);
    ConvexRegion* pkDMP = new ConvexRegion(2,apkPortal);
    pkDMP->SetName("DMP");
    pkDMP->AttachChild(pkNode);
    pkDMP->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::HALF_PI));

    CreateDiagonalConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,
        apkPortal);
    ConvexRegion* pkDMM = new ConvexRegion(2,apkPortal);
    pkDMM->SetName("DMM");
    pkDMM->AttachChild(pkNode);
    pkDMM->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        Mathf::PI));

    CreateDiagonalConnector(m_spkFloor,m_spkCeiling,m_spkWall2,pkNode,
        apkPortal);
    ConvexRegion* pkDPM = new ConvexRegion(2,apkPortal);
    pkDPM->SetName("DPM");
    pkDPM->AttachChild(pkNode);
    pkDPM->Local.SetRotate(Matrix3f().FromAxisAngle(Vector3f::UNIT_Z,
        -Mathf::HALF_PI));

    // create adjacency graph
    pkC00->GetPortal(0)->AdjacentRegion() = pkC0m2;
    pkC00->GetPortal(1)->AdjacentRegion() = pkC02;
    pkC00->GetPortal(2)->AdjacentRegion() = pkC20;
    pkC00->GetPortal(3)->AdjacentRegion() = pkCm20;
    pkC02->GetPortal(0)->AdjacentRegion() = pkC00;
    pkC02->GetPortal(1)->AdjacentRegion() = pkC04;
    pkC0m2->GetPortal(0)->AdjacentRegion() = pkC0m4;
    pkC0m2->GetPortal(1)->AdjacentRegion() = pkC00;
    pkC20->GetPortal(0)->AdjacentRegion() = pkC40;
    pkC20->GetPortal(1)->AdjacentRegion() = pkC00;
    pkCm20->GetPortal(0)->AdjacentRegion() = pkC00;
    pkCm20->GetPortal(1)->AdjacentRegion() = pkCm40;
    pkC04->GetPortal(0)->AdjacentRegion() = pkDMP;
    pkC04->GetPortal(1)->AdjacentRegion() = pkDPP;
    pkC04->GetPortal(2)->AdjacentRegion() = pkC02;
    pkC0m4->GetPortal(0)->AdjacentRegion() = pkDPM;
    pkC0m4->GetPortal(1)->AdjacentRegion() = pkDMM;
    pkC0m4->GetPortal(2)->AdjacentRegion() = pkC0m2;
    pkC40->GetPortal(0)->AdjacentRegion() = pkDPP;
    pkC40->GetPortal(1)->AdjacentRegion() = pkDPM;
    pkC40->GetPortal(2)->AdjacentRegion() = pkC20;
    pkCm40->GetPortal(0)->AdjacentRegion() = pkDMM;
    pkCm40->GetPortal(1)->AdjacentRegion() = pkDMP;
    pkCm40->GetPortal(2)->AdjacentRegion() = pkCm20;
    pkDPP->GetPortal(0)->AdjacentRegion() = pkC40;
    pkDPP->GetPortal(1)->AdjacentRegion() = pkC04;
    pkDMP->GetPortal(0)->AdjacentRegion() = pkC04;
    pkDMP->GetPortal(1)->AdjacentRegion() = pkCm40;
    pkDMM->GetPortal(0)->AdjacentRegion() = pkCm40;
    pkDMM->GetPortal(1)->AdjacentRegion() = pkC0m4;
    pkDPM->GetPortal(0)->AdjacentRegion() = pkC0m4;
    pkDPM->GetPortal(1)->AdjacentRegion() = pkC40;

    // depth-first attachment
    pkC->AttachPositiveChild(0);
    pkC->AttachNegativeChild(pkR);
        pkR->AttachPositiveChild(0);
        pkR->AttachNegativeChild(pkRR);
            pkRR->AttachPositiveChild(pkRRL);
                pkRRL->AttachPositiveChild(pkRRLL);
                    pkRRLL->AttachPositiveChild(pkRRLLL);
                        pkRRLLL->AttachPositiveChild(0);
                        pkRRLLL->AttachNegativeChild(pkDPP);
                    pkRRLL->AttachNegativeChild(0);
                pkRRL->AttachNegativeChild(pkRRLR);
                    pkRRLR->AttachPositiveChild(pkRRLRL);
                        pkRRLRL->AttachPositiveChild(pkRRLRLL);
                            pkRRLRLL->AttachPositiveChild(0);
                            pkRRLRLL->AttachNegativeChild(pkDPM);
                        pkRRLRL->AttachNegativeChild(0);
                    pkRRLR->AttachNegativeChild(pkRRLRR);
                        pkRRLRR->AttachPositiveChild(pkRRLRRL);
                            pkRRLRRL->AttachPositiveChild(0);
                            pkRRLRRL->AttachNegativeChild(pkC40);
                        pkRRLRR->AttachNegativeChild(pkC20);
            pkRR->AttachNegativeChild(pkRRR);
                pkRRR->AttachPositiveChild(pkRRRL);
                    pkRRRL->AttachPositiveChild(pkRRRLL);
                        pkRRRLL->AttachPositiveChild(pkRRRLLL);
                            pkRRRLLL->AttachPositiveChild(0);
                            pkRRRLLL->AttachNegativeChild(pkDMP);
                        pkRRRLL->AttachNegativeChild(0);
                    pkRRRL->AttachNegativeChild(pkRRRLR);
                        pkRRRLR->AttachPositiveChild(pkRRRLRL);
                            pkRRRLRL->AttachPositiveChild(pkRRRLRLL);
                                pkRRRLRLL->AttachPositiveChild(0);
                                pkRRRLRLL->AttachNegativeChild(pkDMM);
                            pkRRRLRL->AttachNegativeChild(0);
                        pkRRRLR->AttachNegativeChild(pkRRRLRR);
                            pkRRRLRR->AttachPositiveChild(pkRRRLRRL);
                                pkRRRLRRL->AttachPositiveChild(0);
                                pkRRRLRRL->AttachNegativeChild(pkCm40);
                            pkRRRLRR->AttachNegativeChild(pkCm20);
                pkRRR->AttachNegativeChild(pkRRRR);
                    pkRRRR->AttachPositiveChild(pkRRRRL);
                        pkRRRRL->AttachPositiveChild(pkRRRRLL);
                            pkRRRRLL->AttachPositiveChild(0);
                            pkRRRRLL->AttachNegativeChild(pkC04);
                        pkRRRRL->AttachNegativeChild(pkC02);
                    pkRRRR->AttachNegativeChild(pkRRRRR);
                        pkRRRRR->AttachPositiveChild(pkRRRRRL);
                            pkRRRRRL->AttachPositiveChild(pkRRRRRLL);
                                pkRRRRRLL->AttachPositiveChild(0);
                                pkRRRRRLL->AttachNegativeChild(pkC0m4);
                            pkRRRRRL->AttachNegativeChild(pkC0m2);
                        pkRRRRR->AttachNegativeChild(pkC00);
    return pkC;
}
//----------------------------------------------------------------------------
bool Portals::InitializeTextures ()
{
    m_spkCeiling = Image::Load(
        System::GetPath("../../Data/Wmif/","Ceiling.wmif"));
    if ( !m_spkCeiling )
        return false;

    m_spkFloor = Image::Load(
        System::GetPath("../../Data/Wmif/","Floor.wmif"));
    if ( !m_spkFloor )
        return false;

    m_spkWall1 = Image::Load(
        System::GetPath("../../Data/Wmif/","Wall1.wmif"));
    if ( !m_spkWall1 )
        return false;

    m_spkWall2 = Image::Load(
        System::GetPath("../../Data/Wmif/","Wall2.wmif"));
    if ( !m_spkWall2 )
        return false;

    m_spkAgate = Image::Load(
        System::GetPath("../../Data/Wmif/","Agate.wmif"));
    if ( !m_spkAgate )
        return false;

    m_spkBark = Image::Load(
        System::GetPath("../../Data/Wmif/","Bark.wmif"));
    if ( !m_spkBark )
        return false;

    m_spkSky = Image::Load(
        System::GetPath("../../Data/Wmif/","Sky.wmif"));
    if ( !m_spkSky )
        return false;

    m_spkWater = Image::Load(
        System::GetPath("../../Data/Wmif/","Water.wmif"));
    if ( !m_spkWater )
        return false;

    return true;
}
//----------------------------------------------------------------------------
void Portals::TestStream ()
{
    Stream kOStream;
    kOStream.Insert(m_spkScene);
    kOStream.Save("Portals.wmof");

    Stream kIStream;
    kIStream.Load("Portals.wmof");
    NodePtr spkScene = (Node*)kIStream.GetObjectAt(0);
}
//----------------------------------------------------------------------------



