Beispiel #1
0
//----------------------------------------------------------------------------
void Fluids3D::CreateScene ()
{
    // Get fluid solver parameters.
    const int bound0M1 = mSmoke->GetIMax();
    const int bound1M1 = mSmoke->GetJMax();
    const int bound2M1 = mSmoke->GetKMax();
    const int bound0 = bound0M1 + 1;
    const int bound1 = bound1M1 + 1;
    const int bound2 = bound2M1 + 1;
    const int quantity = bound0*bound1*bound2;
    const float* x = mSmoke->GetX();
    const float* y = mSmoke->GetY();
    const float* z = mSmoke->GetZ();

#ifdef USE_PARTICLES
    // Create the vertex format.
    VertexFormat* vformat = VertexFormat::Create(3,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0);
#else
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0);
#endif

    // Create the vertex buffer for the cube.
#ifdef USE_PARTICLES
    const int numVertices = 4*quantity;
#else
    const int numVertices = quantity;
#endif

    int vstride = vformat->GetStride();
    VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride);

    int i0, i1, i2, index;

#ifdef USE_PARTICLES
    const float delta = mSmoke->GetDx();
    Float4* posSize = new1<Float4>(quantity);
    for (i2 = 0, index = 0; i2 < bound2; ++i2)
    {
        for (i1 = 0; i1 < bound1; ++i1)
        {
            for (i0 = 0; i0 < bound0; ++i0, ++index)
            {
                posSize[index] = Float4(x[i0], y[i1], z[i2], delta);
            }
        }
    }

    mCube = new0 Particles(vformat, vbuffer, 4, posSize, 1.0f);
    UpdateVertexBuffer();

    IndexBuffer* ibuffer = mCube->GetIndexBuffer();
#else
    VertexBufferAccessor vba(vformat, vbuffer);
    for (i2 = 0, index = 0; i2 < bound2; ++i2)
    {
        for (i1 = 0; i1 < bound1; ++i1)
        {
            for (i0 = 0; i0 < bound0; ++i0, ++index)
            {
                vba.Position<Float3>(index) = Float3(x[i0], y[i1], z[i2]);
            }
        }
    }

    // Create the index buffer for the cube.
    const int numIndices =
        6*bound0M1*bound1M1*bound2 +
        6*bound0M1*bound1*bound2M1 +
        6*bound0*bound1M1*bound2M1;

    IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int));
    int* indices = (int*)ibuffer->GetData();

    const int bound01 = bound0*bound1;
    int j0, j1, j2, j3;
    for (i2 = 0; i2 < bound2; ++i2)
    {
        for (i1 = 0; i1 < bound1M1; ++i1)
        {
            for (i0 = 0; i0 < bound0M1; ++i0)
            {
                j0 = i0 + bound0*(i1 + bound1*i2);
                j1 = j0 + 1;
                j2 = j1 + bound0;
                j3 = j2 - 1;
                *indices++ = j0;
                *indices++ = j1;
                *indices++ = j2;
                *indices++ = j0;
                *indices++ = j2;
                *indices++ = j3;
            }
        }
    }

    for (i1 = 0; i1 < bound1; ++i1)
    {
        for (i2 = 0; i2 < bound2M1; ++i2)
        {
            for (i0 = 0; i0 < bound0M1; ++i0)
            {
                j0 = i0 + bound0*(i1 + bound1*i2);
                j1 = j0 + 1;
                j2 = j1 + bound01;
                j3 = j2 - 1;
                *indices++ = j0;
                *indices++ = j1;
                *indices++ = j2;
                *indices++ = j0;
                *indices++ = j2;
                *indices++ = j3;
            }
        }
    }

    for (i0 = 0; i0 < bound0; ++i0)
    {
        for (i1 = 0; i1 < bound1M1; ++i1)
        {
            for (i2 = 0; i2 < bound2M1; ++i2)
            {
                j0 = i0 + bound0*(i1 + bound1*i2);
                j1 = j0 + bound0;
                j2 = j1 + bound01;
                j3 = j2 - bound0;
                *indices++ = j0;
                *indices++ = j1;
                *indices++ = j2;
                *indices++ = j0;
                *indices++ = j2;
                *indices++ = j3;
            }
        }
    }

    mCube = new0 TriMesh(vformat, vbuffer, ibuffer);
    UpdateVertexBuffer();
#endif

    mNumIndices = ibuffer->GetNumElements();
    mIndices = new1<int>(mNumIndices);
    memcpy(mIndices, ibuffer->GetData(), mNumIndices*sizeof(int));

    // Create the cube effect.
#ifdef USE_PARTICLES
    std::string path = Environment::GetPathR("Disk.wmtf");
    Texture2D* texture = Texture2D::LoadWMTF(path);
    VisualEffectInstance* instance =
        VertexColor4TextureEffect::CreateUniqueInstance(texture,
        Shader::SF_NEAREST, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE);
#else
    VertexColor4Effect* effect = new0 VertexColor4Effect();
    VisualEffectInstance* instance = effect->CreateInstance();
#endif

    const VisualPass* pass = instance->GetPass(0);
    AlphaState* astate = pass->GetAlphaState();
    astate->BlendEnabled = true;

    CullState* cstate = pass->GetCullState();
    cstate->Enabled = false;

    DepthState* dstate = pass->GetDepthState();
    dstate->Enabled = false;
    dstate->Writable = false;

    mCube->SetEffectInstance(instance);

    mScene = new0 Node();
    mScene->AttachChild(mCube);
}
//----------------------------------------------------------------------------
void FreeFormDeformation::CreatePolylines ()
{
    // Generate the polylines that connect adjacent control points.
    mPolysegmentRoot = new0 Node();
    mTrnNode->AttachChild(mPolysegmentRoot);

    VertexColor3Effect* effect = new0 VertexColor3Effect();
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBufferAccessor vba;
    VertexBuffer* vbuffer;
    Polysegment* segment;

    int i0, i1, i2;
    for (i0 = 0; i0 < mQuantity; ++i0)
    {
        for (i1 = 0; i1 < mQuantity; ++i1)
        {
            for (i2 = 0; i2 < mQuantity-1; ++i2)
            {
                vbuffer = new0 VertexBuffer(2, vstride);
                vba.ApplyTo(vformat, vbuffer);
                vba.Position<Vector3f>(0) =
                    mVolume->GetControlPoint(i0, i1, i2);
                vba.Position<Vector3f>(1) =
                    mVolume->GetControlPoint(i0, i1, i2+1);
                vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 0.75f);
                vba.Color<Float3>(0, 1) = Float3(0.0f, 0.0f, 0.75f);
                segment = new0 Polysegment(vformat, vbuffer, true);
                segment->SetEffectInstance(effect->CreateInstance());
                mPolysegmentRoot->AttachChild(segment);
            }
        }

        for (i2 = 0; i2 < mQuantity; ++i2)
        {
            for (i1 = 0; i1 < mQuantity-1; ++i1)
            {
                vbuffer = new0 VertexBuffer(2, vstride);
                vba.ApplyTo(vformat, vbuffer);
                vba.Position<Vector3f>(0) =
                    mVolume->GetControlPoint(i0, i1, i2);
                vba.Position<Vector3f>(1) =
                    mVolume->GetControlPoint(i0, i1+1, i2);
                vba.Color<Float3>(0, 0) = Float3(0.0f, 0.75f, 0.0f);
                vba.Color<Float3>(0, 1) = Float3(0.0f, 0.75f, 0.0f);
                segment = new0 Polysegment(vformat, vbuffer, true);
                segment->SetEffectInstance(effect->CreateInstance());
                mPolysegmentRoot->AttachChild(segment);
            }
        }
    }

    for (i0 = 0; i0 < mQuantity-1; ++i0)
    {
        for (i1 = 0; i1 < mQuantity; ++i1)
        {
            for (i2 = 0; i2 < mQuantity; ++i2)
            {
                vbuffer = new0 VertexBuffer(2, vstride);
                vba.ApplyTo(vformat, vbuffer);
                vba.Position<Vector3f>(0) =
                    mVolume->GetControlPoint(i0, i1, i2);
                vba.Position<Vector3f>(1) =
                    mVolume->GetControlPoint(i0+1, i1, i2);
                vba.Color<Float3>(0,0) = Float3(0.75f, 0.0f, 0.0f);
                vba.Color<Float3>(0,1) = Float3(0.75f, 0.0f, 0.0f);
                segment = new0 Polysegment(vformat, vbuffer, true);
                segment->SetEffectInstance(effect->CreateInstance());
                mPolysegmentRoot->AttachChild(segment);
            }
        }
    }
}
//----------------------------------------------------------------------------
void FreeFormDeformation::CreateControlBoxes ()
{
    // Generate small boxes to represent the control points.
    mControlRoot = new0 Node();
    mTrnNode->AttachChild(mControlRoot);

    // Create a single box to be shared by each control point box.
    const float halfWidth = 0.02f;
    VertexFormat* vformat = VertexFormat::Create(1,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(8, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    vba.Position<Vector3f>(0) = Vector3f(-halfWidth, -halfWidth, -halfWidth);
    vba.Position<Vector3f>(1) = Vector3f(+halfWidth, -halfWidth, -halfWidth);
    vba.Position<Vector3f>(2) = Vector3f(+halfWidth, +halfWidth, -halfWidth);
    vba.Position<Vector3f>(3) = Vector3f(-halfWidth, +halfWidth, -halfWidth);
    vba.Position<Vector3f>(4) = Vector3f(-halfWidth, -halfWidth, +halfWidth);
    vba.Position<Vector3f>(5) = Vector3f(+halfWidth, -halfWidth, +halfWidth);
    vba.Position<Vector3f>(6) = Vector3f(+halfWidth, +halfWidth, +halfWidth);
    vba.Position<Vector3f>(7) = Vector3f(-halfWidth, +halfWidth, +halfWidth);

    IndexBuffer* ibuffer = new0 IndexBuffer(36, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[ 0] = 0;  indices[ 1] = 2;  indices[ 2] = 1;
    indices[ 3] = 0;  indices[ 4] = 3;  indices[ 5] = 2;
    indices[ 6] = 4;  indices[ 7] = 5;  indices[ 8] = 6;
    indices[ 9] = 4;  indices[10] = 6;  indices[11] = 7;
    indices[12] = 0;  indices[13] = 5;  indices[14] = 4;
    indices[15] = 0;  indices[16] = 1;  indices[17] = 5;
    indices[18] = 3;  indices[19] = 7;  indices[20] = 6;
    indices[21] = 3;  indices[22] = 6;  indices[23] = 2;
    indices[24] = 1;  indices[25] = 2;  indices[26] = 6;
    indices[27] = 1;  indices[28] = 6;  indices[29] = 5;
    indices[30] = 0;  indices[31] = 4;  indices[32] = 7;
    indices[33] = 0;  indices[34] = 7;  indices[35] = 3;

    // Create the materials and light to be attached to each box.
    Material* materialActive = new0 Material();
    materialActive->Emissive = Float4(0.0f, 0.0f, 0.0f, 1.0f);
    materialActive->Ambient = Float4(1.0f, 0.0f, 0.0f, 1.0f);
    materialActive->Diffuse = Float4(1.0f, 0.0f, 0.0f, 1.0f);
    materialActive->Specular = Float4(0.0f, 0.0f, 0.0f, 1.0f);

    Material* materialInactive = new0 Material();
    materialInactive->Emissive = Float4(0.0f, 0.0f, 0.0f, 1.0f);
    materialInactive->Ambient = Float4(0.75f, 0.75f, 0.75f, 1.0f);
    materialInactive->Diffuse = Float4(0.75f, 0.75f, 0.75f, 1.0f);
    materialInactive->Specular = Float4(0.0f, 0.0f, 0.0f, 1.0f);

    Light* light = new0 Light(Light::LT_AMBIENT);
    light->Ambient = Float4(1.0f, 1.0f, 1.0f, 1.0f);
    light->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f);
    light->Specular = Float4(0.0f, 0.0f, 0.0f, 1.0f);

    LightAmbEffect* effect = new0 LightAmbEffect();
    mControlActive = effect->CreateInstance(light, materialActive);
    mControlInactive = effect->CreateInstance(light, materialInactive);

    for (int i0 = 0; i0 < mQuantity; ++i0)
    {
        for (int i1 = 0; i1 < mQuantity; ++i1)
        {
            for (int i2 = 0; i2 < mQuantity; ++i2)
            {
                TriMesh* box = new0 TriMesh(vformat, vbuffer, ibuffer);
                Vector3f ctrl = mVolume->GetControlPoint(i0, i1, i2);
                box->LocalTransform.SetTranslate(ctrl);

                // Encode the indices in the name for later use.  This will
                // allow fast lookup of volume control points.
                char name[32];
                sprintf(name, "%d %d %d", i0, i1, i2);
                box->SetName(name);

                box->SetEffectInstance(mControlInactive);

                mControlRoot->AttachChild(box);
            }
        }
    }
}
Beispiel #4
0
//----------------------------------------------------------------------------
void PlanarShadows::CreatePlanes ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
    int vstride = vformat->GetStride();

    // Create the floor mesh.
    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor floor(vformat, vbuffer);

    float xValue = 128.0f;
    float yValue = 256.0f;
    float zValue = 0.0f;
    floor.Position<Float3>(0) = Float3(-xValue, -yValue, zValue);
    floor.Position<Float3>(1) = Float3(+xValue, -yValue, zValue);
    floor.Position<Float3>(2) = Float3(+xValue, +yValue, zValue);
    floor.Position<Float3>(3) = Float3(-xValue, +yValue, zValue);
    floor.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    floor.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    floor.TCoord<Float2>(0, 2) = Float2(1.0f, 1.0f);
    floor.TCoord<Float2>(0, 3) = Float2(0.0f, 1.0f);

    IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
    indices[3] = 0;  indices[4] = 2;  indices[5] = 3;

    mPlane0 = new0 TriMesh(vformat, vbuffer, ibuffer);

    Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR_LINEAR,
        Shader::SC_REPEAT, Shader::SC_REPEAT);
    std::string path = Environment::GetPathR("Sand.wmtf");
    Texture2D* texture = Texture2D::LoadWMTF(path);
    mPlane0->SetEffectInstance(effect->CreateInstance(texture));

    mScene->AttachChild(mPlane0);

    // Create the wall mesh.
    vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor wall(vformat, vbuffer);

    xValue = -128.0f;
    yValue = 256.0f;
    zValue = 128.0f;
    wall.Position<Float3>(0) = Float3(xValue, -yValue, 0.0f);
    wall.Position<Float3>(1) = Float3(xValue, +yValue, 0.0f);
    wall.Position<Float3>(2) = Float3(xValue, +yValue, zValue);
    wall.Position<Float3>(3) = Float3(xValue, -yValue, zValue);
    wall.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    wall.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    wall.TCoord<Float2>(0, 2) = Float2(1.0f, 1.0f);
    wall.TCoord<Float2>(0, 3) = Float2(0.0f, 1.0f);

    mPlane1 = new0 TriMesh(vformat, vbuffer, ibuffer);

    path = Environment::GetPathR("Stone.wmtf");
    texture = Texture2D::LoadWMTF(path);
    mPlane1->SetEffectInstance(effect->CreateInstance(texture));

    mScene->AttachChild(mPlane1);
}
//----------------------------------------------------------------------------
PX2::Node *GeoObjFactory::CreateScaleCtrl_O()
{
	// node
	PX2::Node *node = new0 Node;
	node->LocalTransform.SetUniformScale(2.0f);
	node->SetName("Scale");

	VertexFormat *vf = PX2_GR.GetVertexFormat(GraphicsRoot::VFT_PC);
	StandardMesh stdMesh(vf);
	VertexBuffer *vBufferTemp = 0;
	VertexBufferAccessor vbaTemp;

	// x
	PX2::Node *nodeX = new0 Node;
	nodeX->SetName("Scale_X");

	VertexBuffer *vBufferX = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaX(vf, vBufferX);

	vbaX.Position<Float3>(0) = Float3(0.25f, 0.0f, 0.0f);
	vbaX.Position<Float3>(1) = Float3(1.125f, 0.0f, 0.0f);
	vbaX.Color<Float4>(0, 0) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaX.Color<Float4>(0, 1) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaX.Position<Float3>(2) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaX.Color<Float4>(0, 2) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaX.Color<Float4>(0, 3) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	vbaX.Position<Float3>(4) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(5) = Float3(0.5f, 0.0f, 0.5f);
	vbaX.Color<Float4>(0, 4) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaX.Color<Float4>(0, 5) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	Polysegment *polysegmentX = new0 PX2::Polysegment(vf, vBufferX,
		false);
	polysegmentX->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeX->AttachChild(polysegmentX);

	TriMesh *meshX = stdMesh.Box(0.06f, 0.06f, 0.06f);
	meshX->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshX->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshX->LocalTransform.SetTranslate(APoint(1.125f, 0.0f, 0.0f));
	vBufferTemp = meshX->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	}
	nodeX->AttachChild(meshX);

	// y
	PX2::Node *nodeY = new0 PX2::Node;
	nodeX->SetName("Scale_Y");

	VertexBuffer *vBufferY = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaY(vf, vBufferY);

	vbaY.Position<Float3>(0) = Float3(0.0f, 0.25f, 0.0f);
	vbaY.Position<Float3>(1) = Float3(0.0f, 1.125f, 0.0f);
	vbaY.Color<Float4>(0, 0) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaY.Color<Float4>(0, 1) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	vbaY.Position<Float3>(2) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaY.Color<Float4>(0, 2) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaY.Color<Float4>(0, 3) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaY.Position<Float3>(4) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaY.Color<Float4>(0, 4) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaY.Color<Float4>(0, 5) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	Polysegment *polysegmentY = new0 PX2::Polysegment(vf, vBufferY,
		false);
	polysegmentY->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeY->AttachChild(polysegmentY);

	TriMesh *meshY = stdMesh.Box(0.06f, 0.06f, 0.06f);
	meshY->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshY->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshY->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f));
	vBufferTemp = meshY->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	}
	nodeY->AttachChild(meshY);

	// z
	PX2::Node *nodeZ = new0 PX2::Node();
	nodeX->SetName("Scale_Z");

	VertexBuffer *vBufferZ = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaZ(vf, vBufferZ);

	vbaZ.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.25f);
	vbaZ.Position<Float3>(1) = Float3(0.0f, 0.0f, 1.125f);
	vbaZ.Color<Float4>(0, 0) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaZ.Color<Float4>(0, 1) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	vbaZ.Position<Float3>(2) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(3) = Float3(0.5f, 0.0f, 0.5f);
	vbaZ.Color<Float4>(0, 2) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaZ.Color<Float4>(0, 3) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaZ.Position<Float3>(4) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaZ.Color<Float4>(0, 4) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaZ.Color<Float4>(0, 5) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	Polysegment *polysegmentZ = new0 PX2::Polysegment(vf, vBufferZ,
		false);
	polysegmentZ->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeZ->AttachChild(polysegmentZ);

	TriMesh *meshZ = stdMesh.Box(0.06f, 0.06f, 0.06f);
	meshZ->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshZ->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshZ->LocalTransform.SetTranslate(APoint(.0f, 0.0f, 1.125f));
	vBufferTemp = meshZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	}
	nodeZ->AttachChild(meshZ);

	// XYZ
	node->AttachChild(nodeX);
	node->AttachChild(nodeY);
	node->AttachChild(nodeZ);

	return node;
}
//----------------------------------------------------------------------------
PX2::Node *GeoObjFactory::CreateTranslateCtrl_O()
{
	// node
	PX2::Node *node = new0 Node;
	node->LocalTransform.SetUniformScale(2.0f);
	node->SetName("Translate");

	VertexFormat *vf = PX2_GR.GetVertexFormat(GraphicsRoot::VFT_PC);
	StandardMesh stdMesh(vf);
	VertexBuffer *vBufferTemp = 0;
	VertexBufferAccessor vbaTemp;

	// x
	PX2::Node *nodeX = new0 Node;
	nodeX->SetName("Translate_X");

	VertexBuffer *vBufferX = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaX(vf, vBufferX);

	vbaX.Position<Float3>(0) = Float3(0.25f, 0.0f, 0.0f);
	vbaX.Position<Float3>(1) = Float3(1.125f, 0.0f, 0.0f);
	vbaX.Color<Float4>(0, 0) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaX.Color<Float4>(0, 1) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaX.Position<Float3>(2) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaX.Color<Float4>(0, 2) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaX.Color<Float4>(0, 3) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	vbaX.Position<Float3>(4) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(5) = Float3(0.5f, 0.0f, 0.5f);
	vbaX.Color<Float4>(0, 4) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaX.Color<Float4>(0, 5) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	Polysegment *polysegmentX = new0 PX2::Polysegment(vf, vBufferX,
		false);
	polysegmentX->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeX->AttachChild(polysegmentX);

	TriMesh *meshX = stdMesh.Disk(3, 20, 0.1f);
	meshX->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshX->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshX->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_Y,
		-Mathf::HALF_PI));
	meshX->LocalTransform.SetTranslate(APoint(1.125f, 0.0f, 0.0f));
	vBufferTemp = meshX->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	}
	nodeX->AttachChild(meshX);

	TriFan *fanX = stdMesh.Cone(20, 0.1f, 0.45f);
	fanX->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//fanX->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	fanX->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_Y,
		Mathf::HALF_PI));
	fanX->LocalTransform.SetTranslate(APoint(1.125f, 0.0f, 0.0f));
	vBufferTemp = fanX->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	}
	nodeX->AttachChild(fanX);

	// y
	PX2::Node *nodeY = new0 PX2::Node;
	nodeX->SetName("Translate_Y");

	VertexBuffer *vBufferY = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaY(vf, vBufferY);

	vbaY.Position<Float3>(0) = Float3(0.0f, 0.25f, 0.0f);
	vbaY.Position<Float3>(1) = Float3(0.0f, 1.125f, 0.0f);
	vbaY.Color<Float4>(0, 0) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaY.Color<Float4>(0, 1) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	vbaY.Position<Float3>(2) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaY.Color<Float4>(0, 2) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaY.Color<Float4>(0, 3) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaY.Position<Float3>(4) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaY.Color<Float4>(0, 4) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaY.Color<Float4>(0, 5) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	Polysegment *polysegmentY = new0 PX2::Polysegment(vf, vBufferY,
		false);
	polysegmentY->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeY->AttachChild(polysegmentY);

	TriMesh *meshY = stdMesh.Disk(3, 20, 0.1f);
	meshY->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshY->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshY->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_X,
		Mathf::HALF_PI));
	meshY->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f));
	vBufferTemp = meshY->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	}
	nodeY->AttachChild(meshY);

	TriFan *fanY = stdMesh.Cone(20, 0.1f, 0.45f);
	fanY->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//fanY->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	fanY->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_X,
		-Mathf::HALF_PI));
	fanY->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f));
	vBufferTemp = fanY->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	}
	nodeY->AttachChild(fanY);

	// z
	PX2::Node *nodeZ = new0 PX2::Node();
	nodeX->SetName("Translate_Z");

	VertexBuffer *vBufferZ = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaZ(vf, vBufferZ);

	vbaZ.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.25f);
	vbaZ.Position<Float3>(1) = Float3(0.0f, 0.0f, 1.125f);
	vbaZ.Color<Float4>(0, 0) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	vbaZ.Color<Float4>(0, 1) = Float4(0.0f, 0.0f, 1.0f, 1.0f);

	vbaZ.Position<Float3>(2) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(3) = Float3(0.5f, 0.0f, 0.5f);
	vbaZ.Color<Float4>(0, 2) = Float4(1.0f, 0.0f, 0.0f, 1.0f);
	vbaZ.Color<Float4>(0, 3) = Float4(1.0f, 0.0f, 0.0f, 1.0f);

	vbaZ.Position<Float3>(4) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaZ.Color<Float4>(0, 4) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	vbaZ.Color<Float4>(0, 5) = Float4(0.0f, 1.0f, 0.0f, 1.0f);

	Polysegment *polysegmentZ = new0 PX2::Polysegment(vf, vBufferZ,
		false);
	polysegmentZ->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeZ->AttachChild(polysegmentZ);

	TriMesh *meshZ = stdMesh.Disk(3, 20, 0.1f);
	meshZ->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshZ->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshZ->LocalTransform.SetTranslate(APoint(.0f, 0.0f, 1.125f));
	meshZ->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_X,
		Mathf::PI));
	vBufferTemp = meshZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	}
	nodeZ->AttachChild(meshZ);

	TriFan *fanZ = stdMesh.Cone(20, 0.1f, 0.45f);
	fanZ->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//fanZ->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	fanZ->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 1.125f));
	vBufferTemp = fanZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 0.0f, 1.0f, 1.0f);
	}
	nodeZ->AttachChild(fanZ);

	// xy
	PX2::Node *nodeXY = new0 Node;
	nodeXY->SetName("Translate_XY");
	TriMesh *meshXY = stdMesh.Rectangle(2, 2, 0.25f, 0.25f);
	meshXY->LocalTransform.SetTranslate(APoint(0.25f, 0.25f, 0.0f));
	VertexColor4Material *matXY = new0 VertexColor4Material();
	matXY->GetAlphaProperty(0, 0)->BlendEnabled = true;
	matXY->GetCullProperty(0, 0)->Enabled = false;
	meshXY->SetMaterialInstance(matXY->CreateInstance());
	vBufferTemp = meshXY->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 1.0f, 0.0f, 0.0f);
	}
	nodeXY->AttachChild(meshXY);

	// yz
	PX2::Node *nodeYZ = new0 Node;
	nodeYZ->SetName("Translate_YZ");
	TriMesh *meshYZ = stdMesh.Rectangle(2, 2, 0.25f, 0.25f);
	meshYZ->LocalTransform.SetTranslate(APoint(0.25f, 0.25f, 0.0f));
	meshYZ->LocalTransform.SetRotate(Matrix3f().MakeEulerXYZ(0.0f, -Mathf::HALF_PI, 0.0f));
	VertexColor4Material *matYZ = new0 VertexColor4Material();
	matYZ->GetAlphaProperty(0, 0)->BlendEnabled = true;
	matYZ->GetCullProperty(0, 0)->Enabled = false;
	meshYZ->SetMaterialInstance(matYZ->CreateInstance());
	vBufferTemp = meshYZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 1.0f, 0.0f, 0.0f);
	}
	nodeYZ->AttachChild(meshYZ);

	// xz
	PX2::Node *nodeXZ = new0 Node;
	nodeXZ->SetName("Translate_XZ");
	TriMesh *meshXZ = stdMesh.Rectangle(2, 2, 0.25f, 0.25f);
	meshXZ->LocalTransform.SetRotate(Matrix3f().MakeEulerXYZ(Mathf::HALF_PI, 0.0f, 0.0f));
	meshXZ->LocalTransform.SetTranslate(APoint(0.25f, 0.0f, 0.25f));
	VertexColor4Material *matXZ = new0 VertexColor4Material();
	matXZ->GetAlphaProperty(0, 0)->BlendEnabled = true;
	matXZ->GetCullProperty(0, 0)->Enabled = false;
	meshXZ->SetMaterialInstance(matXZ->CreateInstance());
	vBufferTemp = meshXZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(1.0f, 1.0f, 0.0f, 0.0f);
	}
	nodeXZ->AttachChild(meshXZ);

	// XYZ
	node->AttachChild(nodeX);
	node->AttachChild(nodeY);
	node->AttachChild(nodeZ);
	node->AttachChild(nodeXY);
	node->AttachChild(nodeYZ);
	node->AttachChild(nodeXZ);

	return node;
}
//----------------------------------------------------------------------------
PX2::Node *GeoObjFactory::CreateRolateCtrl_P()
{
	int axisSamples = 4;
	int radialSamples = 12;
	float radial = 0.05f;
	float height = radial*4.0f;

	// node
	PX2::Node *node = new0 Node;
	node->LocalTransform.SetUniformScale(2.0f);
	node->SetName("Rolate");

	VertexFormat *vf = PX2_GR.GetVertexFormat(GraphicsRoot::VFT_PC);
	StandardMesh stdMesh(vf);
	VertexBuffer *vBufferTemp = 0;
	VertexBufferAccessor vbaTemp;

	// x
	PX2::Node *nodeX = new0 Node;
	nodeX->SetName("Rolate_X");

	VertexBuffer *vBufferX = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaX(vf, vBufferX);

	vbaX.Position<Float3>(0) = Float3(0.25f, 0.0f, 0.0f);
	vbaX.Position<Float3>(1) = Float3(1.125f, 0.0f, 0.0f);
	vbaX.Color<Float4>(0, 0) = Float4::RED;
	vbaX.Color<Float4>(0, 1) = Float4::RED;

	vbaX.Position<Float3>(2) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaX.Color<Float4>(0, 2) = Float4::GREEN;
	vbaX.Color<Float4>(0, 3) = Float4::GREEN;

	vbaX.Position<Float3>(4) = Float3(0.5f, 0.0f, 0.0f);
	vbaX.Position<Float3>(5) = Float3(0.5f, 0.0f, 0.5f);
	vbaX.Color<Float4>(0, 4) = Float4::RED;
	vbaX.Color<Float4>(0, 5) = Float4::RED;

	Polysegment *polysegmentX = new0 PX2::Polysegment(vf, vBufferX,
		false);
	polysegmentX->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeX->AttachChild(polysegmentX);

	TriMesh *meshX = stdMesh.Cylinder(axisSamples, radialSamples, radial,
		height, false);
	meshX->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	meshX->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_Y,
		Mathf::HALF_PI));
	meshX->LocalTransform.SetTranslate(APoint(1.125f, 0.0f, 0.0f));
	vBufferTemp = meshX->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4::RED;
	}
	nodeX->AttachChild(meshX);

	// y
	PX2::Node *nodeY = new0 PX2::Node;
	nodeX->SetName("Rolate_Y");

	VertexBuffer *vBufferY = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaY(vf, vBufferY);

	vbaY.Position<Float3>(0) = Float3(0.0f, 0.25f, 0.0f);
	vbaY.Position<Float3>(1) = Float3(0.0f, 1.125f, 0.0f);
	vbaY.Color<Float4>(0, 0) = Float4::GREEN;
	vbaY.Color<Float4>(0, 1) = Float4::GREEN;

	vbaY.Position<Float3>(2) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(3) = Float3(0.5f, 0.5f, 0.0f);
	vbaY.Color<Float4>(0, 2) = Float4::GREEN;
	vbaY.Color<Float4>(0, 3) = Float4::GREEN;

	vbaY.Position<Float3>(4) = Float3(0.0f, 0.5f, 0.0f);
	vbaY.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaY.Color<Float4>(0, 4) = Float4::GREEN;
	vbaY.Color<Float4>(0, 5) = Float4::GREEN;

	Polysegment *polysegmentY = new0 PX2::Polysegment(vf, vBufferY,
		false);
	polysegmentY->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeY->AttachChild(polysegmentY);

	TriMesh *meshY = stdMesh.Cylinder(axisSamples, radialSamples, radial,
		height, false);
	meshY->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	meshY->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_X,
		Mathf::HALF_PI));
	meshY->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f));
	vBufferTemp = meshY->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4(0.0f, 1.0f, 0.0f, 1.0f);
	}
	nodeY->AttachChild(meshY);

	// z
	PX2::Node *nodeZ = new0 PX2::Node();
	nodeX->SetName("Rolate_Z");

	VertexBuffer *vBufferZ = new0 VertexBuffer(6, vf->GetStride());
	VertexBufferAccessor vbaZ(vf, vBufferZ);

	vbaZ.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.25f);
	vbaZ.Position<Float3>(1) = Float3(0.0f, 0.0f, 1.125f);
	vbaZ.Color<Float4>(0, 0) = Float4::BLUE;
	vbaZ.Color<Float4>(0, 1) = Float4::BLUE;

	vbaZ.Position<Float3>(2) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(3) = Float3(0.5f, 0.0f, 0.5f);
	vbaZ.Color<Float4>(0, 2) = Float4::BLUE;
	vbaZ.Color<Float4>(0, 3) = Float4::BLUE;

	vbaZ.Position<Float3>(4) = Float3(0.0f, 0.0f, 0.5f);
	vbaZ.Position<Float3>(5) = Float3(0.0f, 0.5f, 0.5f);
	vbaZ.Color<Float4>(0, 4) = Float4::BLUE;
	vbaZ.Color<Float4>(0, 5) = Float4::BLUE;

	Polysegment *polysegmentZ = new0 PX2::Polysegment(vf, vBufferZ,
		false);
	polysegmentZ->SetMaterialInstance(
		VertexColor4Material::CreateUniqueInstance());
	nodeZ->AttachChild(polysegmentZ);

	TriMesh *meshZ = stdMesh.Cylinder(axisSamples, radialSamples, radial,
		height, false);
	meshZ->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	meshZ->LocalTransform.SetTranslate(APoint(.0f, 0.0f, 1.125f));
	vBufferTemp = meshZ->GetVertexBuffer();
	vbaTemp.ApplyTo(vf, vBufferTemp);
	for (int i = 0; i < vBufferTemp->GetNumElements(); i++)
	{
		vbaTemp.Color<Float4>(0, i) = Float4::BLUE;
	}
	nodeZ->AttachChild(meshZ);

	// XYZ
	node->AttachChild(nodeX);
	node->AttachChild(nodeY);
	node->AttachChild(nodeZ);

	return node;
}
//----------------------------------------------------------------------------
void CubeMaps::CreateScene ()
{
    // Create the root of the scene.
    mScene = new0 Node();
    mWireState = new0 WireState();
    mRenderer->SetOverrideWireState(mWireState);

    // Create the walls of the cube room.  Each of the six texture images is
    // RGBA 64-by-64.
    Node* room = new0 Node();
    mScene->AttachChild(room);

    // Index buffer shared by the room walls.
    IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0;  indices[1] = 1;  indices[2] = 3;
    indices[3] = 0;  indices[4] = 3;  indices[5] = 2;

    // The vertex format shared by the room walls.
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
    int vstride = vformat->GetStride();
    VertexBufferAccessor vba;

    // The texture effect shared by the room walls.
    Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR);

    VertexBuffer* vbuffer;
    TriMesh* wall;
    std::string textureName;

    // +x wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(1) = Float3(+1.0f, -1.0f, +1.0f);
    vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, -1.0f);
    vba.Position<Float3>(3) = Float3(+1.0f, +1.0f, +1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("XpFace.wmtf");
    Texture2D* xpTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(xpTexture));

    // -x wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, +1.0f);
    vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(2) = Float3(-1.0f, +1.0f, +1.0f);
    vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, -1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("XmFace.wmtf");
    Texture2D* xmTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(xmTexture));

    // +y wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(+1.0f, +1.0f, +1.0f);
    vba.Position<Float3>(1) = Float3(-1.0f, +1.0f, +1.0f);
    vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, -1.0f);
    vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, -1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("YpFace.wmtf");
    Texture2D* ypTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(ypTexture));

    // -y wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(2) = Float3(+1.0f, -1.0f, +1.0f);
    vba.Position<Float3>(3) = Float3(-1.0f, -1.0f, +1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("YmFace.wmtf");
    Texture2D* ymTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(ymTexture));

    // +z wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, +1.0f);
    vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, +1.0f);
    vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, +1.0f);
    vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, +1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("ZpFace.wmtf");
    Texture2D* zpTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(zpTexture));

    // -z wall
    vbuffer = new0 VertexBuffer(4, vstride);
    vba.ApplyTo(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(1) = Float3(+1.0f, -1.0f, -1.0f);
    vba.Position<Float3>(2) = Float3(-1.0f, +1.0f, -1.0f);
    vba.Position<Float3>(3) = Float3(+1.0f, +1.0f, -1.0f);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    wall = new0 TriMesh(vformat, vbuffer, ibuffer);
    room->AttachChild(wall);
    textureName = Environment::GetPathR("ZmFace.wmtf");
    Texture2D* zmTexture = Texture2D::LoadWMTF(textureName);
    wall->SetEffectInstance(effect->CreateInstance(zmTexture));

    // A sphere to reflect the environment via a cube map.  The colors will
    // be used to modulate the cube map texture.
    vformat = VertexFormat::Create(3,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    vstride = vformat->GetStride();

    mSphere = StandardMesh(vformat).Sphere(64, 64, 0.125f);
    room->AttachChild(mSphere);

    // Generate random vertex colors for the sphere.  The StandardMesh class
    // produces a sphere with duplicated vertices along a longitude line.
    // This allows texture coordinates to be assigned in a manner that treats
    // the sphere as if it were a rectangle mesh.  For vertex colors, we want
    // the duplicated vertices to have the same color, so a hash table is used
    // to look up vertex colors for the duplicates.
    vba.ApplyTo(mSphere);
    std::map<Float3,Float3> dataMap;
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        Float3& position = vba.Position<Float3>(i);
        Float3& color = vba.Color<Float3>(0, i);
        std::map<Float3,Float3>::iterator iter = dataMap.find(position);
        if (iter != dataMap.end())
        {
            color = iter->second;
        }
        else
        {
            color[0] = 0.0f;
            color[1] = Mathf::IntervalRandom(0.5f, 0.75f);
            color[2] = Mathf::IntervalRandom(0.75f, 1.0f);
            dataMap.insert(std::make_pair(position, color));
        }
    }

    // Create the cube map and attach it to the sphere.
    std::string effectFile = Environment::GetPathR("CubeMap.wmfx");
    CubeMapEffect* cubeMapEffect = new0 CubeMapEffect(effectFile);

    ShaderFloat* reflectivity = new0 ShaderFloat(1);
    (*reflectivity)[0] = 0.5f;

    std::string cubeName = Environment::GetPathR("CubeMap.wmtf");
    TextureCube* cubeTexture = TextureCube::LoadWMTF(cubeName);
    cubeTexture->GenerateMipmaps();
    mCubeMapInstance = cubeMapEffect->CreateInstance(cubeTexture,
        reflectivity, false);

    mSphere->SetEffectInstance(mCubeMapInstance);

    // Allow culling to be disabled on the sphere so when you move inside
    // the sphere, you can see the previously hidden facets and verify that
    // the cube image for those facets is correctly oriented.
    mSphereCullState = cubeMapEffect->GetCullState(0, 0);
}