//----------------------------------------------------------------------------
void CollisionsBoundTree::Response (CRecord& record0, int t0,
    CRecord& record1, int t1, Intersector<float,Vector3f>*)
{
    CollisionsBoundTree* app = (CollisionsBoundTree*)TheApplication;

    // Mesh0 triangles that are intersecting change from blue to cyan.
    TriMesh* mesh = record0.GetMesh();
    VertexBufferAccessor vba(mesh);
    const int* indices = (int*)mesh->GetIndexBuffer()->GetData();
    int i0 = indices[3*t0];
    int i1 = indices[3*t0 + 1];
    int i2 = indices[3*t0 + 2];
    vba.TCoord<Float2>(0, i0) = app->mCyanUV;
    vba.TCoord<Float2>(0, i1) = app->mCyanUV;
    vba.TCoord<Float2>(0, i2) = app->mCyanUV;
    app->mRenderer->Update(mesh->GetVertexBuffer());

    // Mesh1 triangles that are intersecting change from red to yellow.
    mesh = record1.GetMesh();
    vba.ApplyTo(mesh);
    indices = (int*)mesh->GetIndexBuffer()->GetData();
    i0 = indices[3*t1];
    i1 = indices[3*t1 + 1];
    i2 = indices[3*t1 + 2];
    vba.TCoord<Float2>(0 ,i0) = app->mYellowUV;
    vba.TCoord<Float2>(0, i1) = app->mYellowUV;
    vba.TCoord<Float2>(0, i2) = app->mYellowUV;
    app->mRenderer->Update(mesh->GetVertexBuffer());

    // NOTE: See the comments in Wm5CollisionGroup.h about information that
    // is available from the Intersector<float,Vector3f> object.
}
//----------------------------------------------------------------------------
void ReflectionsAndShadows::CopyNormalToTCoord1 (Object* object)
{
    TriMesh* mesh = DynamicCast<TriMesh>(object);
    if (mesh)
    {
        VertexBufferAccessor vba(mesh);
        for (int i = 0; i < vba.GetNumVertices(); ++i)
        {
            vba.TCoord<Vector3f>(1, i) = vba.Normal<Vector3f>(i);
        }
        mRenderer->Update(mesh->GetVertexBuffer());
    }

    Node* node = DynamicCast<Node>(object);
    if (node)
    {
        for (int i = 0; i < node->GetNumChildren(); ++i)
        {
            Spatial* child = node->GetChild(i);
            if (child)
            {
                CopyNormalToTCoord1(child);
            }
        }
    }
}
//----------------------------------------------------------------------------
void GelatinCube::PhysicsTick ()
{
    mModule->Update((float)GetTimeInSeconds());

    // Update spline surface.  Remember that the spline maintains its own
    // copy of the control points, so this update is necessary.
    int numSlices = mModule->GetNumSlices() - 2;
    int numRows = mModule->GetNumRows() - 2;
    int numCols = mModule->GetNumCols() - 2;

    for (int s = 0; s < numSlices; ++s)
    {
        for (int r = 0; r < numRows; ++r)
        {
            for (int c = 0; c < numCols; ++c)
            {
                mSpline->SetControlPoint(c, r, s,
                    mModule->Position(s + 1, r + 1, c + 1));
            }
        }
    }

    mBox->UpdateSurface();

    for (int i = 0; i < mBox->GetNumChildren(); ++i)
    {
        TriMesh* mesh = StaticCast<TriMesh>(mBox->GetChild(i));
        mRenderer->Update(mesh->GetVertexBuffer());
    }
}
//----------------------------------------------------------------------------
void IntersectingBoxes::ModifyMesh (int i)
{
    Vector3f center(
        0.5f*(mBoxes[i].Min[0] + mBoxes[i].Max[0]),
        0.5f*(mBoxes[i].Min[1] + mBoxes[i].Max[1]),
        0.5f*(mBoxes[i].Min[2] + mBoxes[i].Max[2]));

    float xExtent = 0.5f*(mBoxes[i].Max[0] - mBoxes[i].Min[0]);
    float yExtent = 0.5f*(mBoxes[i].Max[1] - mBoxes[i].Min[1]);
    float zExtent = 0.5f*(mBoxes[i].Max[2] - mBoxes[i].Min[2]);

    Vector3f xTerm = xExtent*Vector3f::UNIT_X;
    Vector3f yTerm = yExtent*Vector3f::UNIT_Y;
    Vector3f zTerm = zExtent*Vector3f::UNIT_Z;

    TriMesh* mesh = StaticCast<TriMesh>(mScene->GetChild(i));
    VertexBufferAccessor vba(mesh);

    vba.Position<Vector3f>(0) = center - xTerm - yTerm - zTerm;
    vba.Position<Vector3f>(1) = center + xTerm - yTerm - zTerm;
    vba.Position<Vector3f>(2) = center + xTerm + yTerm - zTerm;
    vba.Position<Vector3f>(3) = center - xTerm + yTerm - zTerm;
    vba.Position<Vector3f>(4) = center - xTerm - yTerm + zTerm;
    vba.Position<Vector3f>(5) = center + xTerm - yTerm + zTerm;
    vba.Position<Vector3f>(6) = center + xTerm + yTerm + zTerm;
    vba.Position<Vector3f>(7) = center - xTerm + yTerm + zTerm;

    mesh->UpdateModelSpace(Visual::GU_NORMALS);
    mRenderer->Update(mesh->GetVertexBuffer());
}
//----------------------------------------------------------------------------
RawTerrainPage::RawTerrainPage (VertexFormat* vformat, int size,
						  float* heights, const Float2& origin, float spacing)
						  :
mSize(size),
mSizeM1(size - 1),
mHeights(heights),
mOrigin(origin),
mSpacing(spacing)
{
	// size = 2^p + 1, p <= 7
	assertion(size ==  3 || size ==  5 || size ==   9 || size == 17
		|| size == 33 || size == 65 || size == 129, "Invalid page size\n");

	mInvSpacing = 1.0f/mSpacing;

	// 创建地形页网格
	float ext = mSpacing*mSizeM1;
	TriMesh* mesh = StandardMesh(vformat).Rectangle(mSize, mSize, ext, ext);
	mVFormat = vformat;
	mVBuffer = mesh->GetVertexBuffer();
	mIBuffer = mesh->GetIndexBuffer();
	delete0(mesh);

	// 修改地形顶点数据
	VertexBufferAccessor vba(mVFormat, mVBuffer);
	int numVertices = mVBuffer->GetNumElements();
	for (int i = 0; i < numVertices; ++i)
	{
		int x = i % mSize;
		int y = i / mSize;
		vba.Position<Float3>(i) = Float3(GetX(x), GetY(y), GetHeight(i));
		vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, 1.0f);
	}

	UpdateModelSpace(Renderable::GU_NORMALS);

	mUV01 = Float4(8.0f, 8.0f, 8.0f, 8.0f);
	mUV23 = Float4(8.0f, 8.0f, 8.0f, 8.0f);
	mUV4 = Float4(8.0f, 8.0f, 8.0f, 8.0f);

	mUV01Float = new0 ShaderFloat(1);
	mUV23Float = new0 ShaderFloat(1);
	mUV4Float = new0 ShaderFloat(1);

	SetUV0(Float2(mUV01[0], mUV01[1]));
	SetUV1(Float2(mUV01[2], mUV01[3]));
	SetUV2(Float2(mUV23[0], mUV23[1]));
	SetUV3(Float2(mUV23[2], mUV23[3]));
	SetUV4(Float2(mUV4[0], mUV4[1]));

	mTextureAlpha = new0 Texture2D(Texture::TF_A8R8G8B8, mSize, mSize, 1);
	mTextureDefault = DynamicCast<Texture2D>(ResourceManager::GetSingleton()
		.BlockLoad("Data/Images/Terrain/NiTu.dds"));
	assertion(mTextureDefault!=0, "Load texture %s failed.",
		"Data/Images/Terrain/NiTu.dds");
}
//----------------------------------------------------------------------------
RevolutionSurface::RevolutionSurface (Curve2f* curve, float xCenter,
    TopologyType topology, int numCurveSamples, int numRadialSamples,
    bool sampleByArcLength, bool outsideView, VertexFormat* vformat)
    :
    mCurve(curve),
    mXCenter(xCenter),
    mTopology(topology),
    mNumCurveSamples(numCurveSamples),
    mNumRadialSamples(numRadialSamples),
    mSin(0),
    mCos(0),
    mSamples(0),
    mSampleByArcLength(sampleByArcLength)
{
    ComputeSampleData();

    // The topology of the meshes is all that matters.  The vertices will be
    // modified later based on the curve of revolution.
    StandardMesh stdmesh(vformat, !outsideView);
    TriMesh* mesh = 0;
    switch (mTopology)
    {
    case REV_DISK_TOPOLOGY:
        mesh = stdmesh.Disk(mNumCurveSamples, mNumRadialSamples, 1.0f);
        break;
    case REV_CYLINDER_TOPOLOGY:
        mesh = stdmesh.Cylinder(mNumCurveSamples, mNumRadialSamples, 1.0f,
            1.0f, true);
        break;
    case REV_SPHERE_TOPOLOGY:
        mesh = stdmesh.Sphere(mNumCurveSamples, mNumRadialSamples, 1.0f);
        break;
    case REV_TORUS_TOPOLOGY:
        mesh = stdmesh.Torus(mNumCurveSamples, mNumRadialSamples, 1.0f,
            0.25f);
        break;
    default:
        assertion(false, "Unexpected condition\n");
        break;
    }
    assertion(mesh != 0, "Failed to construct mesh\n");

    mVFormat = vformat;
    mVBuffer = mesh->GetVertexBuffer();

    // Generate the actual surface by replacing the vertex values.  NOTE:
    // Setting mIBuffer to zero acts as a flag that tells UpdateSurface
    // *not* to call Renderer::UpdateVertexBuffer(mVBuffer).  Only when the
    // application has constructed a RevolutionSurface wlil the update occur.
    mIBuffer = 0;
    UpdateSurface();

    mIBuffer = mesh->GetIndexBuffer();
    delete0(mesh);
}
//----------------------------------------------------------------------------
RawTerrainPage::RawTerrainPage (VertexFormat* vformat, int size,
	float* heights, const Float2& origin, float spacing)
	:
TerrainPage(size, heights, origin, spacing)
{
	float ext = mSpacing*mSizeM1;
	TriMesh* mesh = StandardMesh(vformat).Rectangle(mSize, mSize, ext, ext);
	mVFormat = vformat;
	mVBuffer = mesh->GetVertexBuffer();
	mIBuffer = mesh->GetIndexBuffer();
	delete0(mesh);

	VertexBufferAccessor vba(mVFormat, mVBuffer);
	int numVertices = mVBuffer->GetNumElements();
	for (int i = 0; i < numVertices; ++i)
	{
		int x = i % mSize;
		int y = i / mSize;
		vba.Position<Float3>(i) = Float3(GetX(x), GetY(y), GetHeight(i));
		vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, 1.0f);
		vba.Color<Float3>(0, i) = Float3(0.0f, 0.0f, 0.0f);
	}

	UpdateModelSpace(Renderable::GU_NORMALS);

	mUV01 = Float4(8.0f, 8.0f, 8.0f, 8.0f);
	mUV23 = Float4(8.0f, 8.0f, 8.0f, 8.0f);
	mUV4 = Float4(8.0f, 8.0f, 8.0f, 8.0f);

	mUV01Float = new0 ShaderFloat(1);
	mUV23Float = new0 ShaderFloat(1);
	mUV4Float = new0 ShaderFloat(1);

	SetUV0(Float2(mUV01[0], mUV01[1]));
	SetUV1(Float2(mUV01[2], mUV01[3]));
	SetUV2(Float2(mUV23[0], mUV23[1]));
	SetUV3(Float2(mUV23[2], mUV23[3]));
	SetUV4(Float2(mUV4[0], mUV4[1]));

	mTextureAlpha = new0 Texture2D(Texture::TF_A8R8G8B8, mSize, mSize, 1);
	mTextureDefaultFilename = "Data/engine/grass.png";
}
//----------------------------------------------------------------------------
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::CreateRolateCtrl_O()
{
	// 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");

	TriMesh *meshX = stdMesh.Torus(40, 10, 1.0f, 0.04f);;
	meshX->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshX->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshX->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_Y,
		-Mathf::HALF_PI));
	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("Rolate_Y");

	TriMesh *meshY = stdMesh.Torus(40, 10, 1.0f, 0.04f);;
	meshY->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshY->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	meshY->LocalTransform.SetRotate(HMatrix().MakeRotation(AVector::UNIT_X,
		Mathf::HALF_PI));
	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");

	TriMesh *meshZ = stdMesh.Torus(40, 10, 1.0f, 0.04f);;
	meshZ->SetMaterialInstance(VertexColor4Material::CreateUniqueInstance());
	//meshZ->GetMaterialInstance()->GetPass(0)->GetWireProperty()->Enabled = true;
	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);

	// 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;
}
Example #12
0
//----------------------------------------------------------------------------
TriMesh* StandardMesh::Cylinder (int axisSamples, int radialSamples,
    float radius, float height, bool open)
{
    TriMesh* mesh;
    int unit;
    Float2 tcoord;

    if (open)
    {
        int numVertices = axisSamples*(radialSamples+1);
        int numTriangles = 2*(axisSamples-1)*radialSamples;
        int numIndices = 3*numTriangles;
        int stride = mVFormat->GetStride();

        // Create a vertex buffer.
        VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, stride,
            mUsage);

        VertexBufferAccessor vba(mVFormat, vbuffer);

        // Generate geometry.
        float invRS = 1.0f/(float)radialSamples;
        float invASm1 = 1.0f/(float)(axisSamples-1);
        float halfHeight = 0.5f*height;
        int r, a, aStart, i;

        // Generate points on the unit circle to be used in computing the
        // mesh points on a cylinder slice.
        float* cs = new1<float>(radialSamples + 1);
        float* sn = new1<float>(radialSamples + 1);
        for (r = 0; r < radialSamples; ++r)
        {
            float angle = Mathf::TWO_PI*invRS*r;
            cs[r] = Mathf::Cos(angle);
            sn[r] = Mathf::Sin(angle);
        }
        cs[radialSamples] = cs[0];
        sn[radialSamples] = sn[0];

        // Generate the cylinder itself.
        for (a = 0, i = 0; a < axisSamples; ++a)
        {
            float axisFraction = a*invASm1;  // in [0,1]
            float z = -halfHeight + height*axisFraction;

            // Compute center of slice.
            APoint sliceCenter(0.0f, 0.0f, z);

            // Compute slice vertices with duplication at endpoint.
            int save = i;
            for (r = 0; r < radialSamples; ++r)
            {
                float radialFraction = r*invRS;  // in [0,1)
                AVector normal(cs[r], sn[r], 0.0f);

                vba.Position<Float3>(i) = sliceCenter + radius*normal;

                if (mHasNormals)
                {
                    if (mInside)
                    {
                        vba.Normal<Float3>(i) = -normal;
                    }
                    else
                    {
                        vba.Normal<Float3>(i) = normal;
                    }
                }

                tcoord = Float2(radialFraction, axisFraction);
                for (unit = 0; unit < MAX_UNITS; ++unit)
                {
                    if (mHasTCoords[unit])
                    {
                        vba.TCoord<Float2>(unit, i) = tcoord;
                    }
                }

                ++i;
            }

            vba.Position<Float3>(i) = vba.Position<Float3>(save);

            if (mHasNormals)
            {
                vba.Normal<Float3>(i) = vba.Normal<Float3>(save);
            }

            tcoord = Float2(1.0f, axisFraction);
            for (unit = 0; unit < MAX_UNITS; ++unit)
            {
                if (mHasTCoords[unit])
                {
                    vba.TCoord<Float2>(0, i) = tcoord;
                }
            }

            ++i;
        }
        TransformData(vba);

        // Generate indices.
        IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage);
        int* indices = (int*)ibuffer->GetData();
        for (a = 0, aStart = 0; a < axisSamples-1; ++a)
        {
            int i0 = aStart;
            int i1 = i0 + 1;
            aStart += radialSamples + 1;
            int i2 = aStart;
            int i3 = i2 + 1;
            for (i = 0; i < radialSamples; ++i, indices += 6)
            {
                if (mInside)
                {
                    indices[0] = i0++;
                    indices[1] = i2;
                    indices[2] = i1;
                    indices[3] = i1++;
                    indices[4] = i2++;
                    indices[5] = i3++;
                }
                else // outside view
                {
                    indices[0] = i0++;
                    indices[1] = i1;
                    indices[2] = i2;
                    indices[3] = i1++;
                    indices[4] = i3++;
                    indices[5] = i2++;
                }
            }
        }

        delete1(cs);
        delete1(sn);

        mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer);
    }
    else
    {
        mesh = Sphere(axisSamples, radialSamples, radius);
        VertexBuffer* vbuffer = mesh->GetVertexBuffer();
        int numVertices = vbuffer->GetNumElements();

        VertexBufferAccessor vba(mVFormat, vbuffer);

        // Flatten sphere at poles.
        float hDiv2 = 0.5f*height;
        vba.Position<Float3>(numVertices-2)[2] = -hDiv2;  // south pole
        vba.Position<Float3>(numVertices-1)[2] = +hDiv2;  // north pole

        // Remap z-values to [-h/2,h/2].
        float zFactor = 2.0f/(axisSamples-1);
        float tmp0 = radius*(-1.0f + zFactor);
        float tmp1 = 1.0f/(radius*(+1.0f - zFactor));
        for (int i = 0; i < numVertices-2; ++i)
        {
            Float3& pos = vba.Position<Float3>(i);
            pos[2] = hDiv2*(-1.0f + tmp1*(pos[2] - tmp0));
            float adjust = radius*Mathf::InvSqrt(pos[0]*pos[0] +
                pos[1]*pos[1]);
            pos[0] *= adjust;
            pos[1] *= adjust;
        }
        TransformData(vba);

        if (mHasNormals)
        {
            mesh->UpdateModelSpace(Visual::GU_NORMALS);
        }
    }

    // The duplication of vertices at the seam causes the automatically
    // generated bounding volume to be slightly off center.  Reset the bound
    // to use the true information.
    float maxDist = Mathf::Sqrt(radius*radius + height*height);
    mesh->GetModelBound().SetCenter(APoint::ORIGIN);
    mesh->GetModelBound().SetRadius(maxDist);
    return mesh;
}
//----------------------------------------------------------------------------
void BoxSurface::UpdateSurface ()
{
	int permute[3];
	TriMesh* mesh;
	VertexFormat* vformat;
	VertexBuffer* vbuffer;

	// u faces
	permute[0] = 1;
	permute[1] = 2;
	permute[2] = 0;

	// u = 0
	mesh = StaticCast<TriMesh>(GetChild(0));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumVSamples, vformat, vbuffer, false, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// u = 1
	mesh = StaticCast<TriMesh>(GetChild(1));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumVSamples, vformat, vbuffer, true, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// v faces
	permute[0] = 0;
	permute[1] = 2;
	permute[2] = 1;

	// v = 0
	mesh = StaticCast<TriMesh>(GetChild(2));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumUSamples, vformat, vbuffer, true, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// v = 1
	mesh = StaticCast<TriMesh>(GetChild(3));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumUSamples, vformat, vbuffer, false, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// w faces
	permute[0] = 0;
	permute[1] = 1;
	permute[2] = 2;

	// w = 0
	mesh = StaticCast<TriMesh>(GetChild(4));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumVSamples, mNumUSamples, vformat, vbuffer, false, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// w = 1
	mesh = StaticCast<TriMesh>(GetChild(5));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumVSamples, mNumUSamples, vformat, vbuffer, true, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);
}