//---------------------------------------------------------------------------- void FreeFormDeformation::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Load the small brain data set. It has positions (x,y,z) and texture // coordinates (u,v). std::string path = Environment::GetPathR("SmallBrainPT2.wmvf"); Visual::PrimitiveType type; VertexFormat* vformat; VertexBuffer* vbuffer; IndexBuffer* ibuffer; Visual::LoadWMVF(path, type, vformat, vbuffer, ibuffer); path = Environment::GetPathR("Quartz.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); mMesh = new0 TriMesh(vformat, vbuffer, ibuffer); mMesh->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); mTrnNode->AttachChild(mMesh); CreateBSplineVolume(); CreatePolylines(); CreateControlBoxes(); }
//---------------------------------------------------------------------------- TriMesh* PolyhedronDistance::CreatePlane () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); float size = 16.0f; vba.Position<Float3>(0) = Float3(-size, -size, -0.1f); vba.Position<Float3>(1) = Float3(+size, -size, -0.1f); vba.Position<Float3>(2) = Float3(+size, +size, -0.1f); vba.Position<Float3>(3) = Float3(-size, +size, -0.1f); vba.Color<Float3>(0, 0) = Float3(0.0f, 0.50f, 0.00f); vba.Color<Float3>(0, 1) = Float3(0.0f, 0.25f, 0.00f); vba.Color<Float3>(0, 2) = Float3(0.0f, 0.75f, 0.00f); vba.Color<Float3>(0, 3) = Float3(0.0f, 1.00f, 0.00f); 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; TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); return mesh; }
//---------------------------------------------------------------------------- void BouncingBall::CreateFloor () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); const float xExtent = 8.0f; const float yExtent = 16.0f; const float zValue = 0.0f; vba.Position<Float3>(0) = Float3(-xExtent, -yExtent, zValue); vba.Position<Float3>(1) = Float3(+xExtent, -yExtent, zValue); vba.Position<Float3>(2) = Float3(+xExtent, +yExtent, zValue); vba.Position<Float3>(3) = Float3(-xExtent, +yExtent, zValue); 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(1.0f, 1.0f); vba.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; mFloor = new0 TriMesh(vformat, vbuffer, ibuffer); std::string path = Environment::GetPathR("Floor.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); mFloor->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT)); }
//---------------------------------------------------------------------------- void BouncingSpheres::CreateBackWall () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); Float3 backWallColor(209.0f/255.0f, 204.0f/255.0f, 180.0f/255.0f); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(1.0f, 1.0f, 1.0f); vba.Position<Float3>(1) = Float3(1.0f, 20.0f, 1.0f); vba.Position<Float3>(2) = Float3(1.0f, 20.0f, 17.0f); vba.Position<Float3>(3) = Float3(1.0f, 1.0f, 17.0f); vba.Color<Float3>(0, 0) = backWallColor; vba.Color<Float3>(0, 1) = backWallColor; vba.Color<Float3>(0, 2) = backWallColor; vba.Color<Float3>(0, 3) = backWallColor; 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; mBackWall = new0 TriMesh(vformat, vbuffer, ibuffer); mBackWall->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); }
//---------------------------------------------------------------------------- Node* ExtremalQuery::CreateVisualConvexPolyhedron () { const Vector3f* vertices = mConvexPolyhedron->GetVertices(); int numTriangles = mConvexPolyhedron->GetNumTriangles(); int numIndices = 3*numTriangles; const int* polyIndices = mConvexPolyhedron->GetIndices(); // Visualize the convex polyhedron as a collection of face-colored // triangles. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numIndices, vstride); VertexBufferAccessor vba(vformat, vbuffer); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); int i; for (i = 0; i < numIndices; ++i) { vba.Position<Vector3f>(i) = vertices[polyIndices[i]]; indices[i] = i; } TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); // Use randomly generated vertex colors. for (i = 0; i < numTriangles; ++i) { Float3 color; for (int j = 0; j < 3; ++j) { color[j] = Mathf::UnitRandom(); } vba.Color<Float3>(0, 3*i ) = color; vba.Color<Float3>(0, 3*i+1) = color; vba.Color<Float3>(0, 3*i+2) = color; } mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); Node* root = new0 Node(); root->AttachChild(mesh); return root; }
//---------------------------------------------------------------------------- void IntersectTriangleCylinder::CreateScene () { mScene = new0 Node(); mCullState = new0 CullState(); mCullState->Enabled = false; mRenderer->SetOverrideCullState(mCullState); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(3, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Vector3f>(0) = (const Vector3f&)mTriangleMVertex0; vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Vector3f>(1) = (const Vector3f&)mTriangleMVertex1; vba.Color<Float3>(0, 1) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Vector3f>(2) = (const Vector3f&)mTriangleMVertex2; vba.Color<Float3>(0, 2) = Float3(0.0f, 0.0f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(3, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; mTMesh = new0 TriMesh(vformat, vbuffer, ibuffer); mTMesh->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mTMesh->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f)); mCMesh = StandardMesh(vformat).Cylinder(8, 16, mCylinderRadius, mCylinderHeight, false); vba.ApplyTo(mCMesh); for (int i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = Float3(1.0f, 0.0f, 0.0f); } mCMesh->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mScene->AttachChild(mTMesh); mScene->AttachChild(mCMesh); }
//---------------------------------------------------------------------------- TriMesh* RoughPlaneSolidBox::CreateRamp () { float x = 8.0f; float y = 8.0f; float z = y*Mathf::Tan((float)mModule.Angle); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(6, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(-x, 0.0f, 0.0f); vba.Position<Float3>(1) = Float3(+x, 0.0f, 0.0f); vba.Position<Float3>(2) = Float3(-x, y, 0.0f); vba.Position<Float3>(3) = Float3(+x, y, 0.0f); vba.Position<Float3>(4) = Float3(-x, y, z); vba.Position<Float3>(5) = Float3(+x, y, z); vba.TCoord<Float2>(0, 0) = Float2(0.25f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(0.75f, 0.0f); vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f); vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f); vba.TCoord<Float2>(0, 4) = Float2(0.25f, 1.0f); vba.TCoord<Float2>(0, 5) = Float2(0.75f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(18, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[ 0] = 0; indices[ 1] = 1; indices[ 2] = 4; indices[ 3] = 1; indices[ 4] = 5; indices[ 5] = 4; indices[ 6] = 0; indices[ 7] = 4; indices[ 8] = 2; indices[ 9] = 1; indices[10] = 3; indices[11] = 5; indices[12] = 3; indices[13] = 2; indices[14] = 4; indices[15] = 3; indices[16] = 4; indices[17] = 5; TriMesh* ramp = new0 TriMesh(vformat, vbuffer, ibuffer); std::string path = Environment::GetPathR("Metal.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); ramp->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT)); return ramp; }
//---------------------------------------------------------------------------- TriMesh* PolyhedronDistance::CreateTetra (float size, bool isBlack) { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Vector3f>(0) = -(size/3.0f)*Vector3f(1.0f, 1.0f, 1.0f); vba.Position<Vector3f>(1) = Vector3f(size, 0.0f, 0.0f); vba.Position<Vector3f>(2) = Vector3f(0.0f, size, 0.0f); vba.Position<Vector3f>(3) = Vector3f(0.0f, 0.0f, size); if (isBlack) { // Black tetrahedra for the small ones used as points. Float3 black(0.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 0) = black; vba.Color<Float3>(0, 1) = black; vba.Color<Float3>(0, 2) = black; vba.Color<Float3>(0, 3) = black; } else { // Colorful colors for the tetrahedra under study. vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f); vba.Color<Float3>(0, 1) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(1.0f, 1.0f, 1.0f); } IndexBuffer* ibuffer = new0 IndexBuffer(12, 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] = 0; indices[ 7] = 1; indices[ 8] = 3; indices[ 9] = 1; indices[10] = 2; indices[11] = 3; TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); return mesh; }
//---------------------------------------------------------------------------- TriMesh* Delaunay3D::CreateTetra (int index) const { const Vector3f* dvertices = mDelaunay->GetVertices(); const int* dindices = mDelaunay->GetIndices(); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Vector3f>(0) = dvertices[dindices[4*index ]]; vba.Position<Vector3f>(1) = dvertices[dindices[4*index + 1]]; vba.Position<Vector3f>(2) = dvertices[dindices[4*index + 2]]; vba.Position<Vector3f>(3) = dvertices[dindices[4*index + 3]]; Float4 lightGray(0.75f, 0.75f, 0.75f, 1.0f); vba.Color<Float4>(0, 0) = lightGray; vba.Color<Float4>(0, 1) = lightGray; vba.Color<Float4>(0, 2) = lightGray; vba.Color<Float4>(0, 3) = lightGray; IndexBuffer* ibuffer = new0 IndexBuffer(12, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[ 0] = 0; indices[ 1] = 1; indices[ 2] = 2; indices[ 3] = 0; indices[ 4] = 3; indices[ 5] = 1; indices[ 6] = 0; indices[ 7] = 2; indices[ 8] = 3; indices[ 9] = 3; indices[10] = 2; indices[11] = 1; TriMesh* tetra = new0 TriMesh(vformat, vbuffer, ibuffer); VisualEffectInstance* instance = VertexColor4Effect::CreateUniqueInstance(); instance->GetEffect()->GetAlphaState(0, 0)->BlendEnabled = true; instance->GetEffect()->GetWireState(0, 0)->Enabled = true; tetra->SetEffectInstance(instance); return tetra; }
bool LoadMultipleTriMeshes(const char* fn,TriMesh& tri) { ifstream in; in.open(fn); if(!in) { cout<<"Couldn't open tri file "<<fn<<endl; return false; } vector<TriMesh> models; do { models.push_back(TriMesh()); in >> models[models.size()-1]; } while(in); if(in.eof()) { tri.Merge(models); return true; } else { cout<<"Error while loading tri file "<<fn<<endl; return false; } return true; }
//---------------------------------------------------------------------------- void GlossMaps::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); // Create vertex and index buffers to be shared by two meshes. VertexFormat* vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); Float3 yVector(0.0f, 1.0f, 0.0f); vba.Position<Float3>(0) = Float3(-0.5f, 0.0f, -0.5f); vba.Position<Float3>(1) = Float3(-0.5f, 0.0f, 0.5f); vba.Position<Float3>(2) = Float3( 0.5f, 0.0f, 0.5f); vba.Position<Float3>(3) = Float3( 0.5f, 0.0f, -0.5f); vba.Normal<Float3>(0) = yVector; vba.Normal<Float3>(1) = yVector; vba.Normal<Float3>(2) = yVector; vba.Normal<Float3>(3) = yVector; vba.TCoord<Float2>(0, 0) = Float2(1.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 1.0f); vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 0.0f); IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // The light and material are used by both the gloss and non-gloss // objects. Light* light = new0 Light(Light::LT_DIRECTIONAL); light->Ambient = Float4(0.1f, 0.1f, 0.1f, 1.0f); light->Diffuse = Float4(0.6f, 0.6f, 0.6f, 1.0f); light->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f); light->DVector = AVector(0.0f, -1.0f, 0.0f); Material* material = new0 Material(); material->Ambient = Float4(0.2f, 0.2f, 0.2f, 1.0f); material->Diffuse = Float4(0.7f, 0.7f, 0.7f, 1.0f); material->Specular = Float4(1.0f, 1.0f, 1.0f, 25.0f); // Create a non-gloss-mapped square. TriMesh* squareNoGloss = new0 TriMesh(vformat, vbuffer, ibuffer); squareNoGloss->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, -0.25f*Mathf::PI)); squareNoGloss->LocalTransform.SetTranslate(APoint(1.0f, -1.0f, 0.0f)); squareNoGloss->SetEffectInstance( LightDirPerVerEffect::CreateUniqueInstance(light, material)); mTrnNode->AttachChild(squareNoGloss); // Create a gloss-mapped square. TriMesh* squareGloss = new0 TriMesh(vformat, vbuffer, ibuffer); squareGloss->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, -0.25f*Mathf::PI)); squareGloss->LocalTransform.SetTranslate(APoint(-1.0f, -1.0f, 0.0f)); mTrnNode->AttachChild(squareGloss); std::string effectFile = Environment::GetPathR("GlossMap.wmfx"); GlossMapEffect* effect = new0 GlossMapEffect(effectFile); std::string baseName = Environment::GetPathR("Magic.wmtf"); Texture2D* baseTexture = Texture2D::LoadWMTF(baseName); squareGloss->SetEffectInstance(effect->CreateInstance(baseTexture, light, material)); }
//---------------------------------------------------------------------------- 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); } } } }
//---------------------------------------------------------------------------- TriMesh* Castle::LoadMeshPNT2 (const std::string& name) { // Get the vertex format. VertexFormat* vformat = VertexFormat::Create(4, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 1); int vstride = vformat->GetStride(); // Get the positions. std::string filename = Environment::GetPathR(name); std::ifstream inFile(filename.c_str()); int numPositions; Float3* positions; GetFloat3(inFile, numPositions, positions); // Get the normals. int numNormals; Float3* normals; GetFloat3(inFile, numNormals, normals); // Get the texture coordinates for unit 0. int numTCoords0; Float2* tcoords0; GetFloat2(inFile, numTCoords0, tcoords0); // Get the texture coordinates for unit 1. int numTCoords1; Float2* tcoords1; GetFloat2(inFile, numTCoords1, tcoords1); // Get the vertices and indices. int numTriangles; inFile >> numTriangles; VertexPNT2* vertices = new1<VertexPNT2>(3*numTriangles); std::vector<VertexPNT2> PNT2Array; std::map<VertexPNT2,int> PNT2Map; std::vector<int> indices; for (int t = 0; t < numTriangles; ++t) { for (int j = 0, k = 3*t; j < 3; ++j, ++k) { VertexPNT2& vertex = vertices[k]; inFile >> vertex.PIndex; inFile >> vertex.NIndex; inFile >> vertex.T0Index; inFile >> vertex.T1Index; std::map<VertexPNT2,int>::iterator miter = PNT2Map.find(vertex); int index; if (miter != PNT2Map.end()) { // Second or later time the vertex is encountered. index = miter->second; } else { // First time the vertex is encountered. index = (int)PNT2Array.size(); PNT2Map.insert(std::make_pair(vertex, index)); PNT2Array.push_back(vertex); } indices.push_back(index); } } inFile.close(); // Build the mesh. int numVertices = (int)PNT2Array.size(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba(vformat, vbuffer); for (int i = 0; i < numVertices; ++i) { VertexPNT2& vertex = PNT2Array[i]; vba.Position<Float3>(i) = positions[vertex.PIndex]; vba.Normal<Float3>(i) = normals[vertex.NIndex]; vba.TCoord<Float2>(0, i) = tcoords0[vertex.T0Index]; vba.TCoord<Float2>(1, i) = tcoords1[vertex.T1Index]; } int numIndices = (int)indices.size(); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); memcpy(ibuffer->GetData(), &indices[0], numIndices*sizeof(int)); delete1(vertices); delete1(tcoords1); delete1(tcoords0); delete1(normals); delete1(positions); return new0 TriMesh(vformat, vbuffer, ibuffer); }
//---------------------------------------------------------------------------- void VolumeTextures::CreateScene () { mScene = new0 Node(); mAlphaState = new0 AlphaState(); mAlphaState->BlendEnabled = true; mRenderer->SetOverrideAlphaState(mAlphaState); mCullState = new0 CullState(); mCullState->Enabled = false; mRenderer->SetOverrideCullState(mCullState); // Create the grid of square meshes. const int numSlices = 64; const int numSamples = 32; // The vertex format that is shared by all square meshes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // The index buffer that is shared by all square meshes. int numIndices = 6*(numSamples-1)*(numSamples-1); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); for (int i1 = 0; i1 < numSamples - 1; ++i1) { for (int i0 = 0; i0 < numSamples - 1; ++i0) { int v0 = i0 + numSamples * i1; int v1 = v0 + 1; int v2 = v1 + numSamples; int v3 = v0 + numSamples; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v0; *indices++ = v2; *indices++ = v3; } } // Create the volume texture. Three Gaussian distributions are used for // the RGB color channels. The alpha channel is constant. const int bound = 64; Texture3D* texture = new0 Texture3D(Texture::TF_A8R8G8B8, bound, bound, bound, 1); unsigned char* data = (unsigned char*)texture->GetData(0); const float mult = 1.0f/(bound - 1.0f); const float rParam = 0.01f; const float gParam = 0.01f; const float bParam = 0.01f; const float extreme = 8.0f; APoint rCenter( 0.5f*extreme, 0.0f, 0.0f); APoint gCenter(-0.5f*extreme, -0.5f*extreme, 0.0f); APoint bCenter(-0.5f*extreme, +0.5f*extreme, 0.0f); unsigned char commonAlpha = 12; APoint point; for (int z = 0; z < bound; ++z) { point[2] = -extreme + 2.0f*extreme*mult*z; for (int y = 0; y < bound; ++y) { point[1] = -extreme + 2.0f*extreme*mult*y; for (int x = 0; x < bound; ++x) { point[0] = -extreme + 2.0f*extreme*mult*x; AVector diff = point - rCenter; float sqrLength = diff.SquaredLength(); float rGauss = 1.0f - rParam*sqrLength; if (rGauss < 0.0f) { rGauss = 0.0f; } diff = point - gCenter; sqrLength = diff.SquaredLength(); float gGauss = 1.0f - gParam*sqrLength; if (gGauss < 0.0f) { gGauss = 0.0f; } diff = point - bCenter; sqrLength = diff.SquaredLength(); float bGauss = 1.0f - bParam*sqrLength; if (bGauss < 0.0f) { bGauss = 0.0f; } *data++ = (unsigned char)(255.0f*bGauss); *data++ = (unsigned char)(255.0f*gGauss); *data++ = (unsigned char)(255.0f*rGauss); *data++ = commonAlpha; } } } // The volume texture effect that is shared by all square meshes. std::string effectFile = Environment::GetPathR("VolumeTextures.wmfx"); VolumeTextureEffect* effect = new0 VolumeTextureEffect(effectFile); VisualEffectInstance* instance = effect->CreateInstance(texture); // The grid of squares. const int numVertices = numSamples*numSamples; float inv = 1.0f/(numSamples - 1.0f); VertexBufferAccessor vba; for (int slice = 0; slice < numSlices; ++slice) { VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); vba.ApplyTo(vformat, vbuffer); float w = slice/(numSlices - 1.0f); float z = 2.0f*w - 1.0f; for (int i1 = 0, i = 0; i1 < numSamples; ++i1) { float v = i1*inv; float y = 2.0f*v - 1.0f; for (int i0 = 0; i0 < numSamples; ++i0, ++i) { float u = i0*inv; float x = 2.0f*u - 1.0f; vba.Position<Float3>(i) = Float3(x, y, z); vba.TCoord<Float3>(0, i) = Float3(u, v, w); } } TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(instance); mScene->AttachChild(mesh); } }
//---------------------------------------------------------------------------- TriMesh* SkinnedBiped::GetMesh (const std::string& name, Node* biped) { // Load the triangle indices and material. std::string filename = name + ".triangle.raw"; std::string path = Environment::GetPathR(filename); FileIO inFile(path, FileIO::FM_DEFAULT_READ); int numTriangles; inFile.Read(sizeof(int), &numTriangles); int numIndices = 3*numTriangles; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); inFile.Read(sizeof(int), numIndices, indices); Material* material = new0 Material(); Float4 emissive, ambient, diffuse, specular; inFile.Read(sizeof(float), 3, &material->Emissive); material->Emissive[3] = 1.0f; inFile.Read(sizeof(float), 3, &material->Ambient); material->Ambient[3] = 1.0f; inFile.Read(sizeof(float), 3, &material->Diffuse); material->Diffuse[3] = 1.0f; inFile.Read(sizeof(float), 3, &material->Specular); material->Specular[3] = 0.0f; inFile.Close(); // Load the skin controller. filename = name + ".skin.raw"; path = Environment::GetPathR(filename); inFile.Open(path, FileIO::FM_DEFAULT_READ); int repeat; float minTime, maxTime, phase, frequency; inFile.Read(sizeof(float), &repeat); inFile.Read(sizeof(float), &minTime); inFile.Read(sizeof(float), &maxTime); inFile.Read(sizeof(float), &phase); inFile.Read(sizeof(float), &frequency); int numVertices, numBones; inFile.Read(sizeof(int), &numVertices); inFile.Read(sizeof(int), &numBones); SkinController* ctrl = new0 SkinController(numVertices, numBones); ctrl->Repeat = (Controller::RepeatType)repeat; ctrl->MinTime = (double)minTime; ctrl->MaxTime = (double)maxTime; ctrl->Phase = (double)phase; ctrl->Frequency = (double)frequency; Node** bones = ctrl->GetBones(); int i; for (i = 0; i < numBones; ++i) { int length; inFile.Read(sizeof(int), &length); char* boneName = new1<char>(length + 1); inFile.Read(sizeof(char), length, boneName); boneName[length] = 0; bones[i] = (Node*)biped->GetObjectByName(boneName); assertion(bones[i] != 0, "Failed to find bone.\n"); delete1(boneName); } float** weights = ctrl->GetWeights(); APoint** offsets = ctrl->GetOffsets(); for (int j = 0; j < numVertices; ++j) { for (i = 0; i < numBones; ++i) { inFile.Read(sizeof(float), &weights[j][i]); inFile.Read(sizeof(float), 3, &offsets[j][i]); } } inFile.Close(); int vstride = mVFormat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); // Set positions and normals to zero for now. The controller update // will set the initial values. memset(vbuffer->GetData(), 0, numVertices*vstride); TriMesh* mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer); mesh->SetName(name); mesh->AttachController(ctrl); mesh->SetEffectInstance(LightDirPerVerEffect::CreateUniqueInstance( mLight, material)); return mesh; }
//---------------------------------------------------------------------------- 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 ConvexHull3D::CreateHull () { int numVertices = mLimitedQuantity; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba(vformat, vbuffer); int i; for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mVertices[i]; vba.Color<Float3>(0, i) = mColors[i]; } RegenerateHull(); int numTriangles = 0; TriMesh* mesh = 0; switch (mHull->GetDimension()) { case 0: sprintf(mFooter, "point: v = %d, t = %d", numVertices, numTriangles); return; case 1: sprintf(mFooter, "linear: v = %d, t = %d", numVertices, numTriangles); return; case 2: { numTriangles = mHull->GetNumSimplices() - 2; const int* hullIndices = mHull->GetIndices(); IndexBuffer* ibuffer = new0 IndexBuffer(3*numTriangles, sizeof(int)); int* indices = (int*)ibuffer->GetData(); for (int t = 0, i0 = 1, i1 = 2; t < numTriangles; ++t, ++i0, ++i1) { *indices++ = hullIndices[0]; *indices++ = hullIndices[i0]; *indices++ = hullIndices[i1]; } mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); sprintf(mFooter, "planar: v = %d, t = %d", numVertices, numTriangles); break; } case 3: numTriangles = mHull->GetNumSimplices(); const int* hullIndices = mHull->GetIndices(); IndexBuffer* ibuffer = new0 IndexBuffer(3*numTriangles, sizeof(int)); int* indices = (int*)ibuffer->GetData(); memcpy(indices, hullIndices, 3*numTriangles*sizeof(int)); mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); sprintf(mFooter, "spatial: v = %d, t = %d", numVertices, numTriangles); break; } // Translate to center of mass. Vector3f center = mVertices[0]; for (i = 1; i < mLimitedQuantity; ++i) { center += mVertices[i]; } center /= (float)mLimitedQuantity; mesh->LocalTransform.SetTranslate(-center); mTrnNode->SetChild(0, mesh); for (i = 2; i < mLimitedQuantity + 2; ++i) { mTrnNode->SetChild(i, CreateSphere()); } TriMesh* sphere = StaticCast<TriMesh>(mTrnNode->GetChild(1)); sphere->LocalTransform.SetTranslate( mVertices[mLimitedQuantity - 1] - center); // Update the scene, center-and-fit to frustum. mScene->Update(); mTrnNode->LocalTransform.SetTranslate(-mScene->WorldBound.GetCenter()); APoint camPosition = APoint::ORIGIN - 2.5f*mScene->WorldBound.GetRadius()*mCamera->GetDVector(); mCamera->SetPosition(camPosition); mCuller.ComputeVisibleSet(mScene); }
//---------------------------------------------------------------------------- void IntersectConvexPolyhedra::ComputeIntersection () { // Transform the model-space vertices to world space. VertexBufferAccessor vba(mMeshPoly0); int i; for (i = 0; i < vba.GetNumVertices(); ++i) { APoint modPos = vba.Position<Float3>(i); APoint locPos = mMeshPoly0->LocalTransform*modPos; mWorldPoly0.Point(i) = Vector3f(locPos[0], locPos[1], locPos[2]); } mWorldPoly0.UpdatePlanes(); vba.ApplyTo(mMeshPoly1); for (i = 0; i < vba.GetNumVertices(); ++i) { APoint modPos = vba.Position<Float3>(i); APoint locPos = mMeshPoly1->LocalTransform*modPos; mWorldPoly1.Point(i) = Vector3f(locPos[0], locPos[1], locPos[2]); } mWorldPoly1.UpdatePlanes(); // Compute the intersection (if any) in world space. bool hasIntersection = mWorldPoly0.FindIntersection(mWorldPoly1, mIntersection); if (hasIntersection) { // Build the corresponding mesh. int numVertices = mIntersection.GetNumVertices(); int numTriangles = mIntersection.GetNumTriangles(); int numIndices = 3*numTriangles; VertexFormat* vformat = mMeshPoly0->GetVertexFormat(); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); Float3 green(0.0f, 1.0f, 0.0f); vba.ApplyTo(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mIntersection.Point(i); vba.Color<Float3>(0, i) = green; } int* indices = (int*)ibuffer->GetData(); for (i = 0; i < numTriangles; ++i) { const MTTriangle& triangle = mIntersection.GetTriangle(i); for (int j = 0; j < 3; ++j) { indices[3*i + j] = mIntersection.GetVLabel(triangle.GetVertex(j)); } } mMeshIntersection = new0 TriMesh(vformat, vbuffer, ibuffer); mMeshIntersection->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mScene->SetChild(0, mMeshIntersection); mMeshIntersection->Culling = Spatial::CULL_DYNAMIC; } else { mMeshIntersection->Culling = Spatial::CULL_ALWAYS; } }
//---------------------------------------------------------------------------- void BillboardNodes::CreateScene () { mScene = new0 Node(); mCullState = new0 CullState(); mRenderer->SetOverrideCullState(mCullState); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // All triangle meshes have this common vertex format. Use StandardMesh // to create these meshes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); StandardMesh stdMesh(vformat); // Create the ground. It covers a square with vertices (1,1,0), (1,-1,0), // (-1,1,0), and (-1,-1,0). Multiply the texture coordinates by a factor // to enhance the wrap-around. mGround = stdMesh.Rectangle(2, 2, 16.0f, 16.0f); VertexBufferAccessor vba(mGround); int i; for (i = 0; i < vba.GetNumVertices(); ++i) { Float2& tcoord = vba.TCoord<Float2>(0, i); tcoord[0] *= 128.0f; tcoord[1] *= 128.0f; } // Create a texture effect for the ground. std::string path = Environment::GetPathR("Horizontal.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = Texture2DEffect::CreateUniqueInstance( texture, Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT); mGround->SetEffectInstance(instance); mScene->AttachChild(mGround); // Create a rectangle mesh. The mesh is in the xy-plane. Do not apply // local transformations to the mesh. Use the billboard node transforms // to control the mesh location and orientation. mRectangle = stdMesh.Rectangle(2, 2, 0.125f, 0.25f); // Create a texture effect for the rectangle and for the torus. Texture2DEffect* geomEffect = new0 Texture2DEffect(Shader::SF_LINEAR); path = Environment::GetPathR("RedSky.wmtf"); texture = Texture2D::LoadWMTF(path); mRectangle->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes a rectangle to always be facing // the camera. This is the type of billboard for an avatar. mBillboard0 = new0 BillboardNode(mCamera); mBillboard0->AttachChild(mRectangle); mScene->AttachChild(mBillboard0); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard0->LocalTransform.SetTranslate(APoint(-0.25f, 0.0f, 0.25f)); mBillboard0->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); // Create a torus mesh. Do not apply local transformations to the mesh. // Use the billboard node transforms to control the mesh location and // orientation. mTorus = StandardMesh(vformat, false).Torus(16, 16, 1.0f, 0.25f); mTorus->LocalTransform.SetUniformScale(0.1f); // Create a texture effect for the torus. It uses the RedSky image that // the rectangle uses. mTorus->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes an object to always be oriented // the same way relative to the camera. mBillboard1 = new0 BillboardNode(mCamera); mBillboard1->AttachChild(mTorus); mScene->AttachChild(mBillboard1); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard1->LocalTransform.SetTranslate(APoint(0.25f, 0.0f, 0.25f)); mBillboard1->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); #ifdef DEMONSTRATE_VIEWPORT_BOUNDING_RECTANGLE // The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z') // in [-1,1]^2 x [0,1]. mSSCamera = new0 Camera(false); mSSCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mSSCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // Create a semitransparent screen rectangle. VertexFormat* ssVFormat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); int ssVStride = ssVFormat->GetStride(); VertexBuffer* ssVBuffer = new0 VertexBuffer(4, ssVStride); VertexBufferAccessor ssVba(ssVFormat, ssVBuffer); Float4 ssColor(0.0f, 0.0f, 1.0f, 0.25f); ssVba.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.0f); ssVba.Position<Float3>(1) = Float3(1.0f, 0.0f, 0.0f); ssVba.Position<Float3>(2) = Float3(1.0f, 1.0f, 0.0f); ssVba.Position<Float3>(3) = Float3(0.0f, 1.0f, 0.0f); ssVba.Color<Float4>(0, 0) = ssColor; ssVba.Color<Float4>(0, 1) = ssColor; ssVba.Color<Float4>(0, 2) = ssColor; ssVba.Color<Float4>(0, 3) = ssColor; IndexBuffer* ssIBuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ssIBuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; mSSRectangle = new0 TriMesh(ssVFormat, ssVBuffer, ssIBuffer); mSSRectangle->Update(); // Create a vertex color effect for the screen rectangle. VertexColor4Effect* ssEffect = new0 VertexColor4Effect(); mSSRectangle->SetEffectInstance(ssEffect->CreateInstance()); // Alpha blending must be enabled to obtain the semitransparency. ssEffect->GetAlphaState(0, 0)->BlendEnabled = true; #endif }
//---------------------------------------------------------------------------- void Skinning::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); // The skinned object is a cylinder. const int radialSamples = 10; const int axisSamples = 7; const float radius = 10.0f; const float height = 80.0f; const float invRS = 1.0f/(float)radialSamples; const float invASm1 = 1.0f/(float)(axisSamples - 1); const float halfHeight = 0.5f*height; const APoint center(0.0f, 0.0f, 100.0f); const AVector u(0.0f,0.0f,-1.0f); const AVector v(0.0f,1.0f,0.0f); const AVector axis(1.0f,0.0f,0.0f); // Generate geometry. VertexFormat* vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT4, 0); int vstride = vformat->GetStride(); const int numVertices = axisSamples*(radialSamples + 1); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba(vformat, vbuffer); // Generate points on the unit circle to be used in computing the mesh // points on a cylinder slice. int r, a, aStart, i; float* sn = new1<float>(radialSamples + 1); float* cs = 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); } sn[radialSamples] = sn[0]; cs[radialSamples] = cs[0]; // Generate the cylinder itself. for (a = 0, i = 0; a < axisSamples; ++a, ++i) { float axisFraction = a*invASm1; // in [0,1] float z = -halfHeight + height*axisFraction; // Compute center of slice. APoint sliceCenter = center + z*axis; // Compute slice vertices with duplication at end point. Float3 color(axisFraction, 1.0f - axisFraction, 0.3f); Float4 tcoord; int save = i; for (r = 0; r < radialSamples; ++r, ++i) { AVector normal = cs[r]*u + sn[r]*v; vba.Position<Float3>(i) = sliceCenter + radius*normal; vba.Color<Float3>(0,i) = color; vba.TCoord<Float4>(0, i) = ComputeWeights(a); } vba.Position<Float3>(i) = vba.Position<Float3>(save); vba.Color<Float3>(0, i) = color; vba.TCoord<Float4>(0, i) = ComputeWeights(a); } // Generate connectivity. int numTriangles = 2*(axisSamples - 1)*radialSamples; int numIndices = 3*numTriangles; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); 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) { indices[0] = i0++; indices[1] = i1; indices[2] = i2; indices[3] = i1++; indices[4] = i3++; indices[5] = i2++; } } delete1(cs); delete1(sn); TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mTrnNode->AttachChild(mesh); std::string effectFile = Environment::GetPathR("Skinning.wmfx"); SkinningEffect* effect = new0 SkinningEffect(effectFile); ShaderFloat* skinningMatrix[4] = { new0 ShaderFloat(4), new0 ShaderFloat(4), new0 ShaderFloat(4), new0 ShaderFloat(4) }; for (i = 0; i < 4; ++i) { mSkinningMatrix[i] = skinningMatrix[i]->GetData(); } mesh->SetEffectInstance(effect->CreateInstance(skinningMatrix)); }
//---------------------------------------------------------------------------- void ScreenPolygons::CreateScene () { // The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z') // in [-1,1]^2 x [0,1]. mScreenCamera = new0 Camera(false); mScreenCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mScreenCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // Load the biped just for some model to display. #ifdef WM5_LITTLE_ENDIAN std::string path = Environment::GetPathR("SkinnedBipedPN.wmof"); #else std::string path = Environment::GetPathR("SkinnedBipedPN.be.wmof"); #endif InStream source; source.Load(path); mScene = DynamicCast<Node>(source.GetObjectAt(0)); assertion(mScene != 0, "Error in biped stream.\n"); // The background is a textured screen polygon (z = 1). VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Float3>(1) = Float3(1.0f, 0.0f, 1.0f); vba.Position<Float3>(2) = Float3(1.0f, 1.0f, 1.0f); vba.Position<Float3>(3) = Float3(0.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(1.0f, 1.0f); vba.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; mBackPoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("RedSky.wmtf"); Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR); Texture2D* texture = Texture2D::LoadWMTF(path); mBackPoly->SetEffectInstance(effect->CreateInstance(texture)); // The middle polygon, which may be translated via '+' or '-'. vbuffer = new0 VertexBuffer(4, vstride); vba.ApplyTo(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.3f, 0.0f); vba.Position<Float3>(1) = Float3(1.0f, 0.3f, 0.0f); vba.Position<Float3>(2) = Float3(1.0f, 0.7f, 0.0f); vba.Position<Float3>(3) = Float3(0.0f, 0.7f, 0.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.3f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.3f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 0.7f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 0.7f); mMidPoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("BallTexture.wmtf"); texture = Texture2D::LoadWMTF(path); mMidPoly->SetEffectInstance(effect->CreateInstance(texture)); mLinearZ = 1.0f; mDepthZ = 1.0f; mMidPoly->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, mLinearZ)); // A portion of the foreground is a textured screen polygon (z = 0). vbuffer = new0 VertexBuffer(5, vstride); vba.ApplyTo(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.0f); vba.Position<Float3>(1) = Float3(0.5f, 0.0f, 0.0f); vba.Position<Float3>(2) = Float3(0.75f, 0.5f, 0.0f); vba.Position<Float3>(3) = Float3(0.5f, 0.75f, 0.0f); vba.Position<Float3>(4) = Float3(0.0f, 0.5f, 0.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(0.67f, 0.0f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 0.67f); vba.TCoord<Float2>(0, 3) = Float2(0.67f, 1.0f); vba.TCoord<Float2>(0, 4) = Float2(0.0f, 0.67f); ibuffer = new0 IndexBuffer(9, sizeof(int)); indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; indices[6] = 0; indices[7] = 3; indices[8] = 4; mForePoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("Flower.wmtf"); Texture2DEffect* foreEffect = new0 Texture2DEffect(Shader::SF_LINEAR); texture = Texture2D::LoadWMTF(path); mForePoly->SetEffectInstance(foreEffect->CreateInstance(texture)); // Make the foreground semitransparent. foreEffect->GetAlphaState(0, 0)->BlendEnabled = true; }
//---------------------------------------------------------------------------- void ClodMeshes::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Load the face model. #ifdef WM5_LITTLE_ENDIAN std::string path = Environment::GetPathR("FacePN.wmof"); #else std::string path = Environment::GetPathR("FacePN.be.wmof"); #endif InStream inStream; inStream.Load(path); TriMeshPtr mesh = StaticCast<TriMesh>(inStream.GetObjectAt(0)); VertexBufferAccessor vba0(mesh); // Remove the normals and add texture coordinates. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(vba0.GetNumVertices(), vstride); VertexBufferAccessor vba1(vformat, vbuffer); float xmin = Mathf::MAX_REAL, xmax = -Mathf::MAX_REAL; float ymin = Mathf::MAX_REAL, ymax = -Mathf::MAX_REAL; int i; for (i = 0; i < vba0.GetNumVertices(); ++i) { Float3 position = vba0.Position<Float3>(i); vba1.Position<Float3>(i) = position; float x = position[0]; float y = position[2]; vba1.TCoord<Float2>(0, i) = Float2(x, y); if (x < xmin) { xmin = x; } if (x > xmax) { xmax = x; } if (y < ymin) { ymin = y; } if (y > ymax) { ymax = y; } } float xmult = 1.0f/(xmax - xmin); float ymult = 1.0f/(ymax - ymin); for (i = 0; i < vba1.GetNumVertices(); ++i) { Float2 tcoord = vba1.TCoord<Float2>(0, i); vba1.TCoord<Float2>(0,i) = Float2( (tcoord[0] - xmin)*xmult, (tcoord[1] - ymin)*ymult); } mesh->SetVertexFormat(vformat); mesh->SetVertexBuffer(vbuffer); // Create a texture for the face. Use the generated texture coordinates. Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR); path = Environment::GetPathR("Magician.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); #ifdef USE_CLOD_MESH // Create the collapse records to be shared by two CLOD meshes. int numRecords = 0; CollapseRecord* records = 0; CreateClodMesh ccm(mesh, numRecords, records); CollapseRecordArray* recordArray = new0 CollapseRecordArray(numRecords, records); mClod[0] = new0 ClodMesh(mesh, recordArray); mClod[0]->LocalTransform = mesh->LocalTransform; mClod[0]->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() - 150.0f*AVector::UNIT_X); mClod[0]->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(mClod[0]); mClod[1] = new0 ClodMesh(mesh, recordArray); mClod[1]->LocalTransform = mesh->LocalTransform; mClod[1]->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() + 150.0f*AVector::UNIT_X - 100.0f*AVector::UNIT_Y); mClod[1]->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(mClod[1]); mActive = mClod[0]; #else IndexBuffer* ibuffer = mesh->GetIndexBuffer(); TriMesh* face = new0 TriMesh(vformat, vbuffer,ibuffer); face->LocalTransform = mesh->LocalTransform; face->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() - 150.0f*AVector::UNIT_X); face->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(face); face = new0 TriMesh(vformat, vbuffer, ibuffer); face->LocalTransform = mesh->LocalTransform; face->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() + 150.0f*AVector::UNIT_X); face->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(face); #endif }
//---------------------------------------------------------------------------- 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); }
//---------------------------------------------------------------------------- RigidTetra::RigidTetra (float size, float mass, const Vector3f& position, const Vector3f& linearMomentum, const Vector3f& angularMomentum) : Moved(false) { Moved = false; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Vector3f>(0) = -(size/3.0f)*Vector3f(1.0f, 1.0f, 1.0f); vba.Position<Vector3f>(1) = Vector3f(size, 0.0f, 0.0f); vba.Position<Vector3f>(2) = Vector3f(0.0f, size, 0.0f); vba.Position<Vector3f>(3) = Vector3f(0.0f, 0.0f, size); vba.Color<Float3>(0, 0) = Float3(1.0f, 1.0f, 1.0f); vba.Color<Float3>(0, 1) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(0.0f, 0.0f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(12, 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] = 0; indices[ 7] = 1; indices[ 8] = 3; indices[ 9] = 1; indices[10] = 2; indices[11] = 3; mMesh = new0 TriMesh(vformat, vbuffer, ibuffer); mMesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); // Compute the inertia tensor. Matrix3f inertia; int j; for (int i = 0; i < 3; ++i) { inertia[i][i] = 0.0f; for (j = 0; j < 3; ++j) { if (i != j) { inertia[i][j] = 0.0f; for (int k = 0; k < 4; ++k) { Vector3f pos = vba.Position<Vector3f>(k); inertia[i][i] += 0.25f*mass*pos[j]*pos[j]; inertia[i][j] -= 0.25f*mass*pos[i]*pos[j]; } } } } // Compute the radius of a sphere bounding the tetrahedron. Vector3f centroid = (size/6.0f)*Vector3f(1.0f, 1.0f, 1.0f); mRadius = 0.0f; for (j = 0; j < 4; ++j) { vba.Position<Vector3f>(j) -= centroid; float temp = (vba.Position<Vector3f>(j) - centroid).Length(); if (temp > mRadius) { mRadius = temp; } } SetMass(mass); SetBodyInertia(inertia); SetPosition(position); SetQOrientation(Quaternionf::IDENTITY); SetLinearMomentum(linearMomentum); SetAngularMomentum(angularMomentum); }
//---------------------------------------------------------------------------- void MaterialTextures::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Create a square object. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, 0.0f); vba.Position<Float3>(1) = Float3(-1.0f, 1.0f, 0.0f); vba.Position<Float3>(2) = Float3( 1.0f, 1.0f, 0.0f); vba.Position<Float3>(3) = Float3( 1.0f, -1.0f, 0.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(1.0f, 1.0f); vba.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] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // Create a square with a door texture. TriMesh* door = new0 TriMesh(vformat, vbuffer, ibuffer); std::string path = Environment::GetPathR("Door.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); door->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); mTrnNode->AttachChild(door); // Material-texture effect shared by two objects. The material is // semitransparent, so alpha blending must be enabled. MaterialTextureEffect* effect = new0 MaterialTextureEffect(Shader::SF_LINEAR); effect->GetAlphaState(0, 0)->BlendEnabled = true; // Create a square with a material-texture effect. The texture is combined // with the material to produce a semitransparenteffect on the sand. You // should be able to see the door through it. TriMesh* sand = new0 TriMesh(vformat, vbuffer, ibuffer); sand->LocalTransform.SetTranslate(APoint(0.25f, 0.25f, -0.25f)); mTrnNode->AttachChild(sand); mMaterial = new0 Material(); mMaterial->Diffuse = Float4(1.0f, 0.0f, 0.0f, 0.5f); path = Environment::GetPathR("Sand.wmtf"); texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = effect->CreateInstance(mMaterial, texture); sand->SetEffectInstance(instance); // The material alpha is adjustable during run time, so we must enable // the corresponding shader constant to automatically update. instance->GetVertexConstant(0, "MaterialDiffuse")->EnableUpdater(); // Create another square with a material-texture effect. TriMesh* water = new0 TriMesh(vformat, vbuffer, ibuffer); water->LocalTransform.SetTranslate(APoint(0.5f, 0.5f, -0.5f)); mTrnNode->AttachChild(water); Material* material = new0 Material(); material->Diffuse = Float4(0.0f, 0.0f, 1.0f, 0.5f); path = Environment::GetPathR("Water.wmtf"); texture = Texture2D::LoadWMTF(path); water->SetEffectInstance(effect->CreateInstance(material, texture)); }
//---------------------------------------------------------------------------- void Terrains::CreateScene () { // Create the root of the scene. mScene = new0 Node(); // Load and initialize the sky dome. It follows the camera. std::string skyMeshName = Environment::GetPathR("SkyDomePNT2.wmvf"); Visual::PrimitiveType type; VertexFormat* vformat; VertexBuffer* vbuffer; IndexBuffer* ibuffer; Visual::LoadWMVF(skyMeshName, type, vformat, vbuffer, ibuffer); mSkyDome = new0 TriMesh(vformat, vbuffer, ibuffer); mScene->AttachChild(mSkyDome); APoint skyPosition = mCamera->GetPosition(); skyPosition[2] = 0.0f; mSkyDome->LocalTransform.SetTranslate(skyPosition); mSkyDome->LocalTransform.SetUniformScale(mCamera->GetDMax()); Texture2DEffect* skyEffect = new0 Texture2DEffect( Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT); std::string skyTextureName = Environment::GetPathR("SkyDome.wmtf"); Texture2D* skyTexture = Texture2D::LoadWMTF(skyTextureName); skyTexture->GenerateMipmaps(); mSkyDome->SetEffectInstance(skyEffect->CreateInstance(skyTexture)); // Load the height field and create the terrain. vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 1); // For lower-resolution terrain, change the paths to Height64/Color64 or // Height32/Color32. std::string heightName = ThePath + "Data/Height128/height"; std::string colorName = ThePath + "Data/Color128/color"; mTerrain = new0 Terrain(heightName, vformat, mCamera); mScene->AttachChild(mTerrain); // The effect that is shared across all pages. std::string effectFile = Environment::GetPathR("BaseMulDetailFogExpSqr.wmfx"); TerrainEffect* terrainEffect = new0 TerrainEffect(effectFile); std::string detailName = Environment::GetPathR("Detail.wmtf"); Texture2D* detailTexture = Texture2D::LoadWMTF(detailName); detailTexture->GenerateMipmaps(); ShaderFloat* fogColorDensity = new0 ShaderFloat(1); (*fogColorDensity)[0] = 0.5686f; (*fogColorDensity)[1] = 0.7255f; (*fogColorDensity)[2] = 0.8353f; (*fogColorDensity)[3] = 0.0015f; // Attach an effect to each page. Preload all resources to video memory. // This will avoid frame rate stalls when new terrain pages are // encountered as the camera moves. const int numRows = mTerrain->GetRowQuantity(); const int numCols = mTerrain->GetColQuantity(); for (int r = 0; r < numRows; ++r) { for (int c = 0; c < numCols; ++c) { TerrainPage* page = mTerrain->GetPage(r, c); char suffix[32]; sprintf(suffix, ".%d.%d.wmtf", r, c); std::string colorTextureName = colorName + std::string(suffix); Texture2D* colorTexture = Texture2D::LoadWMTF(colorTextureName); colorTexture->GenerateMipmaps(); VisualEffectInstance* instance = terrainEffect->CreateInstance( colorTexture, detailTexture, fogColorDensity); page->SetEffectInstance(instance); mRenderer->Bind(page->GetVertexBuffer()); mRenderer->Bind(page->GetVertexFormat()); mRenderer->Bind(page->GetIndexBuffer()); mRenderer->Bind(colorTexture); } } }
//---------------------------------------------------------------------------- void IntersectConvexPolyhedra::CreateScene () { mScene = new0 Node(); mMotionObject = mScene; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Attach a dummy intersection mesh. If the intersection is nonempty, // the Culling flag will be modified to CULL_DYNAMIC. The intersection // is drawn as a solid. mMeshIntersection = StandardMesh(vformat).Tetrahedron(); VertexBufferAccessor vba(mMeshIntersection); Float3 green(0.0f, 1.0f, 0.0f); int i, j; for (i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = green; } mMeshIntersection->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mMeshIntersection->Culling = Spatial::CULL_ALWAYS; mScene->AttachChild(mMeshIntersection); // The first polyhedron is an ellipsoid. ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 1.0f, 1.0f, 2.0f, 2.0f, 4.0f, 4.0f, 3, mWorldPoly0); // Build the corresponding mesh. int numVertices = mWorldPoly0.GetNumVertices(); int numTriangles = mWorldPoly0.GetNumTriangles(); int numIndices = 3*numTriangles; VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); Float3 red(1.0f, 0.0f, 0.0f); vba.ApplyTo(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mWorldPoly0.Point(i); vba.Color<Float3>(0,i) = red; } int* indices = (int*)ibuffer->GetData(); for (i = 0; i < numTriangles; ++i) { const MTTriangle& triangle = mWorldPoly0.GetTriangle(i); for (j = 0; j < 3; ++j) { indices[3*i + j] = mWorldPoly0.GetVLabel(triangle.GetVertex(j)); } } mMeshPoly0 = new0 TriMesh(vformat, vbuffer, ibuffer); VisualEffectInstance* instance = VertexColor3Effect::CreateUniqueInstance(); instance->GetEffect()->GetWireState(0, 0)->Enabled = true; mMeshPoly0->SetEffectInstance(instance); mMeshPoly0->LocalTransform.SetTranslate(APoint(0.0f, 2.0f, 0.0f)); mScene->AttachChild(mMeshPoly0); // The second polyhedron is egg shaped. ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 2.0f, 2.0f, 4.0f, 4.0f, 5.0f, 3.0f, 4, mWorldPoly1); // Build the corresponding mesh. numVertices = mWorldPoly1.GetNumVertices(); numTriangles = mWorldPoly1.GetNumTriangles(); numIndices = 3*numTriangles; vbuffer = new0 VertexBuffer(numVertices, vstride); ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); Float3 blue(0.0f, 0.0f, 1.0f); vba.ApplyTo(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mWorldPoly1.Point(i); vba.Color<Float3>(0, i) = blue; } indices = (int*)ibuffer->GetData(); for (i = 0; i < numTriangles; ++i) { const MTTriangle& triangle = mWorldPoly1.GetTriangle(i); for (j = 0; j < 3; ++j) { indices[3*i + j] = mWorldPoly1.GetVLabel(triangle.GetVertex(j)); } } mMeshPoly1 = new0 TriMesh(vformat, vbuffer, ibuffer); instance = VertexColor3Effect::CreateUniqueInstance(); instance->GetEffect()->GetWireState(0, 0)->Enabled = true; mMeshPoly1->SetEffectInstance(instance); mMeshPoly1->LocalTransform.SetTranslate(APoint(0.0f, -2.0f, 0.0f)); mScene->AttachChild(mMeshPoly1); ComputeIntersection(); }
//---------------------------------------------------------------------------- void WrigglingSnake::CreateSnakeHead () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Create the snake head as a paraboloid that is attached to the last // ring of vertices on the snake body. These vertices are generated // for t = 1. int numSliceSamples = mSnakeBody->GetNumSliceSamples(); mSlice = new1<Vector3f>(numSliceSamples + 1); // Number of rays (determined by slice samples of tube surface). int numRays = numSliceSamples - 1; // Number of shells less one (your choice, specified in application // constructor). int numShellsM1 = mNumShells - 1; // Generate vertices (positions to be filled in by UpdateSnakeHead). int numVertices = 1 + numRays*numShellsM1; VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba(vformat, vbuffer); Float3 darkGreen(0.0f, 0.25f, 0.0f); for (int i = 0; i < numVertices; ++i) { vba.Color<Float3>(0, i) = darkGreen; } // Generate triangles. int numTriangles = numRays*(2*numShellsM1 - 1); int numIndices = 3*numTriangles; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); for (int r0 = numRays - 1, r1 = 0, t = 0; r1 < numRays; r0 = r1++) { *indices++ = 0; *indices++ = 1 + numShellsM1*r0; *indices++ = 1 + numShellsM1*r1; ++t; for (int s = 1; s < numShellsM1; ++s) { int i00 = s + numShellsM1*r0; int i01 = s + numShellsM1*r1; int i10 = i00 + 1; int i11 = i01 + 1; *indices++ = i00; *indices++ = i10; *indices++ = i11; *indices++ = i00; *indices++ = i11; *indices++ = i01; t += 2; } } mSnakeHead = new0 TriMesh(vformat, vbuffer, ibuffer); mSnakeHead->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); mSnakeRoot->AttachChild(mSnakeHead); UpdateSnake(); }
//---------------------------------------------------------------------------- void ReflectionsAndShadows::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); }
//---------------------------------------------------------------------------- void PolygonOffsets::CreateScene () { mScene = new0 Node(); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Vertices to be shared by rectangles 1 and 3. VertexBuffer* vbuffer0 = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer0); vba.Position<Float3>(0) = Float3(-1.0f, 0.0f, -1.0f); vba.Position<Float3>(1) = Float3(-1.0f, 0.0f, +1.0f); vba.Position<Float3>(2) = Float3(+1.0f, 0.0f, +1.0f); vba.Position<Float3>(3) = Float3(+1.0f, 0.0f, -1.0f); vba.Color<Float3>(0, 0) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 1) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(1.0f, 0.0f, 0.0f); // Vertices to be shared by rectangles 2 and 4. VertexBuffer* vbuffer1 = new0 VertexBuffer(4, vstride); vba.ApplyTo(vformat, vbuffer1); vba.Position<Float3>(0) = Float3(-1.0f, 0.0f, -1.0f); vba.Position<Float3>(1) = Float3(-1.0f, 0.0f, +1.0f); vba.Position<Float3>(2) = Float3(+1.0f, 0.0f, +1.0f); vba.Position<Float3>(3) = Float3(+1.0f, 0.0f, -1.0f); vba.Color<Float3>(0, 0) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 1) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(0.0f, 1.0f, 0.0f); // Indices to be shared by all rectangles. IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // Effect to be shared by the first three rectangles. VertexColor3Effect* effect = new0 VertexColor3Effect(); // rectangle 1 TriMesh* mesh = new0 TriMesh(vformat, vbuffer0, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(+2.0f, -4.0f, 0.0f)); mScene->AttachChild(mesh); // rectangle 2 mesh = new0 TriMesh(vformat, vbuffer1, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(+2.0f, -4.0f, 0.0f)); mesh->LocalTransform.SetUniformScale(0.5f); mScene->AttachChild(mesh); // rectangle 3 mesh = new0 TriMesh(vformat, vbuffer0, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(-2.0f, -4.0f, 0.0f)); mScene->AttachChild(mesh); // rectangle 4 mesh = new0 TriMesh(vformat, vbuffer1, ibuffer); mesh->LocalTransform.SetTranslate(APoint(-2.0f, -4.0f, 0.0f)); mesh->LocalTransform.SetUniformScale(0.5f); mScene->AttachChild(mesh); // Set up the polygon offset for rectangle 4. effect = new0 VertexColor3Effect(); OffsetState* ostate = effect->GetOffsetState(0, 0); ostate->FillEnabled = true; ostate->Scale = -1.0f; ostate->Bias = -2.0f; mesh->SetEffectInstance(effect->CreateInstance()); }