//---------------------------------------------------------------------------- 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)); }
//---------------------------------------------------------------------------- TriMesh *ScreenTarget::CreateRectangle (VertexFormat* vformat, float xMin, float xMax, float yMin, float yMax, float zValue) { if (!ValidFormat(vformat)) return 0; Float2 tc0, tc1, tc2, tc3; tc0 = Float2(0.0f, 0.0f); tc1 = Float2(1.0f, 0.0f); tc2 = Float2(1.0f, 1.0f); tc3 = Float2(0.0f, 1.0f); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(xMin, yMin, zValue); vba.Position<Float3>(1) = Float3(xMax, yMin, zValue); vba.Position<Float3>(2) = Float3(xMax, yMax, zValue); vba.Position<Float3>(3) = Float3(xMin, yMax, zValue); vba.TCoord<Float2>(0, 0) = tc0; vba.TCoord<Float2>(0, 1) = tc1; vba.TCoord<Float2>(0, 2) = tc2; vba.TCoord<Float2>(0, 3) = tc3; // 为square创建IndexBuffer 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; return new0 TriMesh(vformat, vbuffer, ibuffer); }
//---------------------------------------------------------------------------- Billboard::Billboard () : mIsDynamic(true), mIsUseTexAsSize(false), mIsDoAlphaDisAfterStop(true), mDoAlphaDisAfterStopSpeed(0.5f), mIsUseTrim(false) { SetTex("Data/engine/default.png"); mAnchorPoint = Float2(0.5f, 0.5f); SetLocal(true); SetDynamic(mIsDynamic); IndexBuffer *iBuffer = new0 IndexBuffer(6, 2, Buffer::BU_STATIC); unsigned short *indices = (unsigned short*)iBuffer->GetData(); unsigned short v0 = 0; unsigned short v1 = 1; unsigned short v2 = 2; unsigned short v3 = 3; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v1; *indices++ = v3; *indices++ = v2; SetIndexBuffer(iBuffer); mEffectableCtrl = new0 BillboardController(); mEffectableCtrl->SetName("BillboardController"); AttachController(mEffectableCtrl); }
//---------------------------------------------------------------------------- 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 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()); }
//---------------------------------------------------------------------------- void Fluids3D::UpdateIndexBuffer () { VertexBufferAccessor vba(mCube); APoint camPos = mCamera->GetPosition(); const int numTriangles = mNumIndices/3; int* currentIndex = mIndices; mTriangles.clear(); for (int t = 0; t < numTriangles; ++t) { Triangle tri; tri.mIndex0 = *currentIndex++; tri.mIndex1 = *currentIndex++; tri.mIndex2 = *currentIndex++; #ifdef USE_PARTICLES float alpha = vba.Color<Float4>(0, tri.mIndex0)[3]; if (alpha == 0.0f) { continue; } #else float alpha0 = vba.Color<Float4>(0, tri.mIndex0)[3]; float alpha1 = vba.Color<Float4>(0, tri.mIndex1)[3]; float alpha2 = vba.Color<Float4>(0, tri.mIndex2)[3]; if (alpha0 == 0.0f && alpha1 == 0.0f && alpha2 == 0.0f) { continue; } #endif Vector3f scaledCenter = vba.Position<Vector3f>(tri.mIndex0) + vba.Position<Vector3f>(tri.mIndex1) + vba.Position<Vector3f>(tri.mIndex2); APoint output = mCube->WorldTransform*APoint(scaledCenter); AVector diff = output - camPos; tri.mNegSqrDistance = -diff.SquaredLength(); mTriangles.insert(tri); } IndexBuffer* ibuffer = mCube->GetIndexBuffer(); int* indices = (int*)ibuffer->GetData(); ibuffer->SetNumElements(3*(int)mTriangles.size()); std::multiset<Triangle>::iterator iter = mTriangles.begin(); std::multiset<Triangle>::iterator end = mTriangles.end(); for (/**/; iter != end; ++iter) { *indices++ = iter->mIndex0; *indices++ = iter->mIndex1; *indices++ = iter->mIndex2; } mRenderer->Update(ibuffer); }
//---------------------------------------------------------------------------- void ClipMesh::Update () { // Transform the model-space vertices to world space. int numVertices = (int)mTorusVerticesMS.size(); int i; for (i = 0; i < numVertices; ++i) { mTorusVerticesWS[i] = mTorus->LocalTransform*mTorusVerticesMS[i]; } // Partition the torus mesh. std::vector<APoint> clipVertices; std::vector<int> negIndices, posIndices; PartitionMesh(mTorusVerticesWS, mTorusIndices, mPlane, clipVertices, negIndices, posIndices); // Replace the torus vertex buffer. numVertices = (int)clipVertices.size(); int stride = mTorus->GetVertexFormat()->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, stride, Buffer::BU_STATIC); mTorus->SetVertexBuffer(vbuffer); VertexBufferAccessor vba(mTorus); Float3 black(0.0f, 0.0f, 0.0f); for (i = 0; i < numVertices; ++i) { // Transform the world-space vertex to model space. vba.Position<Float3>(i) = mTorus->LocalTransform.Inverse()*clipVertices[i]; vba.Color<Float3>(0, i) = black; } // Modify the vertex color based on which mesh the vertices lie. int negQuantity = (int)negIndices.size(); for (i = 0; i < negQuantity; ++i) { vba.Color<Float3>(0, negIndices[i])[2] = 1.0f; } int posQuantity = (int)posIndices.size(); for (i = 0; i < posQuantity; ++i) { vba.Color<Float3>(0, posIndices[i])[0] = 1.0f; } // To display the triangles generated by the split. int numIndices = negQuantity + posQuantity; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); mTorus->SetIndexBuffer(ibuffer); int* indices = (int*)ibuffer->GetData(); memcpy(indices, &negIndices[0], negQuantity*sizeof(int)); memcpy(indices + negQuantity, &posIndices[0], posQuantity*sizeof(int)); }
//---------------------------------------------------------------------------- void ClipMesh::CreateScene () { mScene = new0 Node(); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); // The plane is fixed at z = 0. mPlane.SetNormal(AVector::UNIT_Z); mPlane.SetConstant(0.0f); mMeshPlane = StandardMesh(vformat).Rectangle(32, 32, 16.0f, 16.0f); VisualEffectInstance* instance = VertexColor3Effect::CreateUniqueInstance(); instance->GetEffect()->GetWireState(0,0)->Enabled = true; mMeshPlane->SetEffectInstance(instance); mScene->AttachChild(mMeshPlane); VertexBufferAccessor vba(mMeshPlane); Float3 green(0.0f, 1.0f, 0.0f); int i; for (i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = green; } // Get the positions and indices for a torus. mTorus = StandardMesh(vformat).Torus(64, 64, 4.0f, 1.0f); instance = VertexColor3Effect::CreateUniqueInstance(); mTorusWireState = instance->GetEffect()->GetWireState(0, 0); mTorus->SetEffectInstance(instance); mScene->AttachChild(mTorus); vba.ApplyTo(mTorus); mTorusVerticesMS.resize(vba.GetNumVertices()); mTorusVerticesWS.resize(vba.GetNumVertices()); Float3 black(0.0f, 0.0f, 0.0f); for (i = 0; i < vba.GetNumVertices(); ++i) { mTorusVerticesMS[i] = vba.Position<Float3>(i); mTorusVerticesWS[i] = mTorusVerticesMS[i]; vba.Color<Float3>(0, i) = black; } IndexBuffer* ibuffer = mTorus->GetIndexBuffer(); int numIndices = ibuffer->GetNumElements(); int* indices = (int*)ibuffer->GetData(); mTorusIndices.resize(numIndices); memcpy(&mTorusIndices[0], indices, numIndices*sizeof(int)); Update(); }
//---------------------------------------------------------------------------- TriMesh* ScreenTarget::CreateRectangle (VertexFormat* vformat, int rtWidth, int rtHeight, float xmin, float xmax, float ymin, float ymax, float zValue) { if (ValidFormat(vformat) && ValidSizes(rtWidth, rtHeight)) { Float2 tc0, tc1, tc2, tc3; if (VertexShader::GetProfile() == VertexShader::VP_ARBVP1) { tc0 = Float2(0.0f, 0.0f); tc1 = Float2(1.0f, 0.0f); tc2 = Float2(1.0f, 1.0f); tc3 = Float2(0.0f, 1.0f); } else { float dx = 0.5f*(xmax - xmin)/(float)(rtWidth - 1); float dy = 0.5f*(ymax - ymin)/(float)(rtHeight - 1); xmin -= dx; xmax -= dx; ymin += dy; ymax += dy; tc0 = Float2(0.0f, 1.0f); tc1 = Float2(1.0f, 1.0f); tc2 = Float2(1.0f, 0.0f); tc3 = Float2(0.0f, 0.0f); } int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(xmin, ymin, zValue); vba.Position<Float3>(1) = Float3(xmax, ymin, zValue); vba.Position<Float3>(2) = Float3(xmax, ymax, zValue); vba.Position<Float3>(3) = Float3(xmin, ymax, zValue); vba.TCoord<Float2>(0, 0) = tc0; vba.TCoord<Float2>(0, 1) = tc1; vba.TCoord<Float2>(0, 2) = tc2; vba.TCoord<Float2>(0, 3) = tc3; // 为square创建IndexBuffer 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; return new0 TriMesh(vformat, vbuffer, ibuffer); } return 0; }
//---------------------------------------------------------------------------- TriMesh* StandardMesh::Hexahedron () { float fSqrtThird = Mathf::Sqrt(1.0f/3.0f); int numVertices = 8; int numTriangles = 12; 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. vba.Position<Float3>(0) = Float3(-fSqrtThird, -fSqrtThird, -fSqrtThird); vba.Position<Float3>(1) = Float3( fSqrtThird, -fSqrtThird, -fSqrtThird); vba.Position<Float3>(2) = Float3( fSqrtThird, fSqrtThird, -fSqrtThird); vba.Position<Float3>(3) = Float3(-fSqrtThird, fSqrtThird, -fSqrtThird); vba.Position<Float3>(4) = Float3(-fSqrtThird, -fSqrtThird, fSqrtThird); vba.Position<Float3>(5) = Float3( fSqrtThird, -fSqrtThird, fSqrtThird); vba.Position<Float3>(6) = Float3( fSqrtThird, fSqrtThird, fSqrtThird); vba.Position<Float3>(7) = Float3(-fSqrtThird, fSqrtThird, fSqrtThird); CreatePlatonicNormals(vba); CreatePlatonicUVs(vba); TransformData(vba); // Generate indices. IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage); int* indices = (int*)ibuffer->GetData(); indices[ 0] = 0; indices[ 1] = 3; indices[ 2] = 2; indices[ 3] = 0; indices[ 4] = 2; indices[ 5] = 1; indices[ 6] = 0; indices[ 7] = 1; indices[ 8] = 5; indices[ 9] = 0; indices[10] = 5; indices[11] = 4; indices[12] = 0; indices[13] = 4; indices[14] = 7; indices[15] = 0; indices[16] = 7; indices[17] = 3; indices[18] = 6; indices[19] = 5; indices[20] = 1; indices[21] = 6; indices[22] = 1; indices[23] = 2; indices[24] = 6; indices[25] = 2; indices[26] = 3; indices[27] = 6; indices[28] = 3; indices[29] = 7; indices[30] = 6; indices[31] = 7; indices[32] = 4; indices[33] = 6; indices[34] = 4; indices[35] = 5; if (mInside) { ReverseTriangleOrder(numTriangles,indices); } return new0 TriMesh(mVFormat, vbuffer, ibuffer); }
//---------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- ClodMesh::ClodMesh (TriMesh* mesh, CollapseRecordArray* recordArray) : TriMesh(mesh->GetVertexFormat(), mesh->GetVertexBuffer(), 0), mCurrentRecord(0), mTargetRecord(0), mRecordArray(recordArray) { assertion(recordArray != 0, "Record array is needed for construction.\n"); // 创建一份顶点索引的拷贝 IndexBuffer* ibuffer = mesh->GetIndexBuffer(); int numIndices = ibuffer->GetNumElements(); int elementSize = ibuffer->GetElementSize(); assertion(elementSize == 4, "Invalid indices.\n"); char* srcIndices = ibuffer->GetData(); mIBuffer = new0 IndexBuffer(numIndices, elementSize); char* trgIndices = mIBuffer->GetData(); memcpy(trgIndices, srcIndices, numIndices*elementSize); }
//---------------------------------------------------------------------------- TriMesh* StandardMesh::Tetrahedron () { float fSqrt2Div3 = Mathf::Sqrt(2.0f)/3.0f; float fSqrt6Div3 = Mathf::Sqrt(6.0f)/3.0f; float fOneThird = 1.0f/3.0f; int numVertices = 4; int numTriangles = 4; 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. vba.Position<Float3>(0) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Float3>(1) = Float3(2.0f*fSqrt2Div3, 0.0f, -fOneThird); vba.Position<Float3>(2) = Float3(-fSqrt2Div3, fSqrt6Div3, -fOneThird); vba.Position<Float3>(3) = Float3(-fSqrt2Div3, -fSqrt6Div3, -fOneThird); CreatePlatonicNormals(vba); CreatePlatonicUVs(vba); TransformData(vba); // Generate indices. IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage); 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] = 1; indices[ 9] = 1; indices[10] = 3; indices[11] = 2; if (mInside) { ReverseTriangleOrder(numTriangles,indices); } return new0 TriMesh(mVFormat, vbuffer, ibuffer); }
//---------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- IndexBuffer* Visual::LoadIndexBuffer (FileIO& inFile) { int numElements; inFile.Read(sizeof(int), &numElements); if (numElements > 0) { int elementSize, usage, offset; inFile.Read(sizeof(int), &elementSize); inFile.Read(sizeof(int), &usage); inFile.Read(sizeof(int), &offset); IndexBuffer* ibuffer = new0 IndexBuffer(numElements, elementSize, (Buffer::Usage)usage); ibuffer->SetOffset(offset); inFile.Read(elementSize, ibuffer->GetNumBytes()/elementSize, ibuffer->GetData()); return ibuffer; } return 0; }
//---------------------------------------------------------------------------- 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 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 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(); }
//---------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- TriMesh* StandardMesh::Sphere (int zSamples, int radialSamples, float radius) { int zsm1 = zSamples-1, zsm2 = zSamples-2, zsm3 = zSamples-3; int rsp1 = radialSamples+1; int numVertices = zsm2*rsp1 + 2; int numTriangles = 2*zsm2*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 zFactor = 2.0f/(float)zsm1; int r, z, zStart, i, unit; Float2 tcoord; // Generate points on the unit circle to be used in computing the mesh // points on a cylinder slice. float* sn = new1<float>(rsp1); float* cs = new1<float>(rsp1); 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 (z = 1, i = 0; z < zsm1; ++z) { float zFraction = -1.0f + zFactor*z; // in (-1,1) float zValue = radius*zFraction; // Compute center of slice. APoint sliceCenter(0.0f, 0.0f, zValue); // Compute radius of slice. float sliceRadius = Mathf::Sqrt(Mathf::FAbs( radius*radius - zValue*zValue)); // Compute slice vertices with duplication at endpoint. AVector normal; int save = i; for (r = 0; r < radialSamples; ++r) { float radialFraction = r*invRS; // in [0,1) AVector radial(cs[r], sn[r], 0.0f); vba.Position<Float3>(i) = sliceCenter + sliceRadius*radial; if (mHasNormals) { normal = vba.Position<Float3>(i); normal.Normalize(); if (mInside) { vba.Normal<Float3>(i) = -normal; } else { vba.Normal<Float3>(i) = normal; } } tcoord[0] = radialFraction; tcoord[1] = 0.5f*(zFraction + 1.0f); 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[0] = 1.0f; tcoord[1] = 0.5f*(zFraction + 1.0f); for (unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = tcoord; } } ++i; } // south pole vba.Position<Float3>(i) = Float3(0.0f, 0.0f, -radius); if (mHasNormals) { if (mInside) { vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, 1.0f); } else { vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, -1.0f); } } tcoord = Float2(0.5f, 0.5f); for (unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = tcoord; } } ++i; // north pole vba.Position<Float3>(i) = Float3(0.0f, 0.0f, radius); if (mHasNormals) { if (mInside) { vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, -1.0f); } else { vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, 1.0f); } } tcoord = Float2(0.5f, 1.0f); for (unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = tcoord; } } ++i; TransformData(vba); // Generate indices. IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage); int* indices = (int*)ibuffer->GetData(); for (z = 0, zStart = 0; z < zsm3; ++z) { int i0 = zStart; int i1 = i0 + 1; zStart += rsp1; int i2 = zStart; 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 // inside view { indices[0] = i0++; indices[1] = i1; indices[2] = i2; indices[3] = i1++; indices[4] = i3++; indices[5] = i2++; } } } // south pole triangles int numVerticesM2 = numVertices - 2; for (i = 0; i < radialSamples; ++i, indices += 3) { if (mInside) { indices[0] = i; indices[1] = i + 1; indices[2] = numVerticesM2; } else { indices[0] = i; indices[1] = numVerticesM2; indices[2] = i + 1; } } // north pole triangles int numVerticesM1 = numVertices-1, offset = zsm3*rsp1; for (i = 0; i < radialSamples; ++i, indices += 3) { if (mInside) { indices[0] = i + offset; indices[1] = numVerticesM1; indices[2] = i + 1 + offset; } else { indices[0] = i + offset; indices[1] = i + 1 + offset; indices[2] = numVerticesM1; } } delete1(cs); delete1(sn); // The duplication of vertices at the seam cause the automatically // generated bounding volume to be slightly off center. Reset the bound // to use the true information. TriMesh* mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer); mesh->GetModelBound().SetCenter(APoint::ORIGIN); mesh->GetModelBound().SetRadius(radius); return mesh; }
//---------------------------------------------------------------------------- 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)); }
//---------------------------------------------------------------------------- TriMesh* StandardMesh::Torus (int circleSamples, int radialSamples, float outerRadius, float innerRadius) { int numVertices = (circleSamples+1)*(radialSamples+1); int numTriangles = 2*circleSamples*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 invCS = 1.0f/(float)circleSamples; float invRS = 1.0f/(float)radialSamples; int c, r, i, unit; Float2 tcoord; // Generate the cylinder itself. for (c = 0, i = 0; c < circleSamples; ++c) { // Compute center point on torus circle at specified angle. float circleFraction = c*invCS; // in [0,1) float theta = Mathf::TWO_PI*circleFraction; float cosTheta = Mathf::Cos(theta); float sinTheta = Mathf::Sin(theta); AVector radial(cosTheta, sinTheta, 0.0f); AVector torusMiddle = outerRadius*radial; // Compute slice vertices with duplication at endpoint. int save = i; for (r = 0; r < radialSamples; ++r) { float radialFraction = r*invRS; // in [0,1) float phi = Mathf::TWO_PI*radialFraction; float cosPhi = Mathf::Cos(phi); float sinPhi = Mathf::Sin(phi); AVector normal = cosPhi*radial + sinPhi*AVector::UNIT_Z; vba.Position<Float3>(i) = torusMiddle + innerRadius*normal; if (mHasNormals) { if (mInside) { vba.Normal<Float3>(i) = -normal; } else { vba.Normal<Float3>(i) = normal; } } tcoord = Float2(radialFraction, circleFraction); 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, circleFraction); for (unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = tcoord; } } ++i; } // Duplicate the cylinder ends to form a torus. for (r = 0; r <= radialSamples; ++r, ++i) { vba.Position<Float3>(i) = vba.Position<Float3>(r); if (mHasNormals) { vba.Normal<Float3>(i) = vba.Normal<Float3>(r); } for (unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = Float2(vba.TCoord<Float2>(unit, r)[0], 1.0f); } } } TransformData(vba); // Generate indices. IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage); int* indices = (int*)ibuffer->GetData(); int cStart = 0; for (c = 0; c < circleSamples; ++c) { int i0 = cStart; int i1 = i0 + 1; cStart += radialSamples + 1; int i2 = cStart; int i3 = i2 + 1; for (i = 0; i < radialSamples; ++i, indices += 6) { if (mInside) { indices[0] = i0++; indices[1] = i1; indices[2] = i2; indices[3] = i1++; indices[4] = i3++; indices[5] = i2++; } else // inside view { indices[0] = i0++; indices[1] = i2; indices[2] = i1; indices[3] = i1++; indices[4] = i2++; indices[5] = i3++; } } } // The duplication of vertices at the seam cause the automatically // generated bounding volume to be slightly off center. Reset the bound // to use the true information. TriMesh* mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer); mesh->GetModelBound().SetCenter(APoint::ORIGIN); mesh->GetModelBound().SetRadius(outerRadius); return mesh; }
//---------------------------------------------------------------------------- TriMesh* StandardMesh::Rectangle (int xSamples, int ySamples, float xExtent, float yExtent) { int numVertices = xSamples*ySamples; int numTriangles = 2*(xSamples-1)*(ySamples-1); 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 inv0 = 1.0f/(xSamples - 1.0f); float inv1 = 1.0f/(ySamples - 1.0f); float u, v, x, y; int i, i0, i1; for (i1 = 0, i = 0; i1 < ySamples; ++i1) { v = i1*inv1; y = (2.0f*v - 1.0f)*yExtent; for (i0 = 0; i0 < xSamples; ++i0, ++i) { u = i0*inv0; x = (2.0f*u - 1.0f)*xExtent; vba.Position<Float3>(i) = Float3(x, y, 0.0f); if (mHasNormals) { vba.Normal<Float3>(i) = Float3(0.0f, 0.0f, 1.0f); } Float2 tcoord(u, v); for (int unit = 0; unit < MAX_UNITS; ++unit) { if (mHasTCoords[unit]) { vba.TCoord<Float2>(unit, i) = tcoord; } } } } TransformData(vba); // Generate indices. IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage); int* indices = (int*)ibuffer->GetData(); for (i1 = 0; i1 < ySamples - 1; ++i1) { for (i0 = 0; i0 < xSamples - 1; ++i0) { int v0 = i0 + xSamples * i1; int v1 = v0 + 1; int v2 = v1 + xSamples; int v3 = v0 + xSamples; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v0; *indices++ = v2; *indices++ = v3; } } return new0 TriMesh(mVFormat, 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); } }
//---------------------------------------------------------------------------- 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); }
//---------------------------------------------------------------------------- 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)); }
//---------------------------------------------------------------------------- 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); }