//---------------------------------------------------------------------------- void IntersectingBoxes::ModifyBoxes () { const int numBoxes = (int)mBoxes.size(); int i; for (i = 0; i < numBoxes; ++i) { AxisAlignedBox3f box = mBoxes[i]; float dx = Mathf::IntervalRandom(-4.0f, 4.0f); if (-mSize <= box.Min[0] + dx && box.Max[0] + dx <= mSize) { box.Min[0] += dx; box.Max[0] += dx; } float dy = Mathf::IntervalRandom(-4.0f, 4.0f); if (-mSize <= box.Min[1] + dy && box.Max[1] + dy <= mSize) { box.Min[1] += dy; box.Max[1] += dy; } float dz = Mathf::IntervalRandom(-4.0f, 4.0f); if (-mSize <= box.Min[2] + dz && box.Max[2] + dz <= mSize) { box.Min[2] += dz; box.Max[2] += dz; } mManager->SetBox(i, box); ModifyMesh(i); } mManager->Update(); mScene->Update(); // Switch material to red for any box that overlaps another. TriMesh* mesh; for (i = 0; i < numBoxes; ++i) { // Reset all boxes to blue. mesh = StaticCast<TriMesh>(mScene->GetChild(i)); mesh->SetEffectInstance(mNoIntersectEffect); } const std::set<EdgeKey>& overlap = mManager->GetOverlap(); std::set<EdgeKey>::const_iterator iter = overlap.begin(); std::set<EdgeKey>::const_iterator end = overlap.end(); for (/**/; iter != end; ++iter) { // Set intersecting boxes to red. i = iter->V[0]; mesh = StaticCast<TriMesh>(mScene->GetChild(i)); mesh->SetEffectInstance(mIntersectEffect); i = iter->V[1]; mesh = StaticCast<TriMesh>(mScene->GetChild(i)); mesh->SetEffectInstance(mIntersectEffect); } }
//---------------------------------------------------------------------------- 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 PointInPolyhedron::CreateScene () { mScene = new0 Node(); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Create a semitransparent sphere mesh. VertexFormat* vformatMesh = VertexFormat::Create(1, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0); TriMesh* mesh = StandardMesh(vformatMesh).Sphere(16, 16, 1.0f); Material* material = new0 Material(); material->Diffuse = Float4(1.0f, 0.0f, 0.0f, 0.25f); VisualEffectInstance* instance = MaterialEffect::CreateUniqueInstance( material); instance->GetEffect()->GetAlphaState(0, 0)->BlendEnabled = true; mesh->SetEffectInstance(instance); // Create the data structures for the polyhedron that represents the // sphere mesh. CreateQuery(mesh); // Create a set of random points. Points inside the polyhedron are // colored white. Points outside the polyhedron are colored blue. 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(1024, vstride); VertexBufferAccessor vba(vformat, vbuffer); Float3 white(1.0f, 1.0f, 1.0f); Float3 blue(0.0f, 0.0f, 1.0f); for (int i = 0; i < vba.GetNumVertices(); ++i) { Vector3f random(Mathf::SymmetricRandom(), Mathf::SymmetricRandom(), Mathf::SymmetricRandom()); vba.Position<Vector3f>(i) = random; if (mQuery->Contains(random)) { vba.Color<Float3>(0, i) = white; } else { vba.Color<Float3>(0, i) = blue; } } DeleteQuery(); mPoints = new0 Polypoint(vformat, vbuffer); mPoints->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); mScene->AttachChild(mPoints); mScene->AttachChild(mesh); }
//---------------------------------------------------------------------------- TriMesh* Delaunay3D::CreateSphere () const { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); TriMesh* mesh = StandardMesh(vformat).Sphere(8, 8, 0.01f); mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); mesh->Culling = Spatial::CULL_ALWAYS; return mesh; }
//---------------------------------------------------------------------------- void ProjectedTextures::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); // 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); TriMesh* mesh = StaticCast<TriMesh>(inStream.GetObjectAt(0)); // Create a camera to project the texture. Projector* projector = new0 Projector(Camera::PM_DEPTH_ZERO_TO_ONE); projector->SetFrustum(1.0f, 10.0f, -0.4125f, 0.4125f, -0.55f, 0.55f); AVector proDVector(0.0f, 1.0f, 0.0f); AVector proUVector(0.0f, 0.0f, 1.0f); AVector proRVector = proDVector.Cross(proUVector); APoint proPosition = APoint::ORIGIN - 303.0f*proDVector; projector->SetFrame(proPosition, proDVector, proUVector, proRVector); // Create a directional light for the face. Light* light = new0 Light(Light::LT_DIRECTIONAL); light->Ambient = Float4(0.25f, 0.25f, 0.25f, 1.0f); light->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f); light->Specular = Float4(0.0f, 0.0f, 0.0f, 1.0f); light->DVector = AVector::UNIT_Y; // scene-camera direction // Create a material for the face. Material* material = new0 Material(); material->Emissive = Float4(0.0f, 0.0f, 0.0f, 1.0f); material->Ambient = Float4(0.5f, 0.5f, 0.5f, 1.0f); material->Diffuse = Float4(0.99607f, 0.83920f, 0.67059f, 1.0f); material->Specular = Float4(0.8f, 0.8f, 0.8f, 0.0f); // Create the effect. std::string effectFile = Environment::GetPathR("ProjectedTexture.wmfx"); ProjectedTextureEffect* effect = new0 ProjectedTextureEffect(effectFile); std::string projectedName = Environment::GetPathR("Magician.wmtf"); Texture2D* projectedTexture = Texture2D::LoadWMTF(projectedName); mesh->SetEffectInstance(effect->CreateInstance(projector, light, material, projectedTexture)); mTrnNode->AttachChild(mesh); }
//---------------------------------------------------------------------------- TriMesh* FoucaultPendulum::CreateFloor () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); TriMesh* floor = StandardMesh(vformat).Rectangle(2, 2, 32.0f, 32.0f); std::string path = Environment::GetPathR("Wood.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); floor->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); return floor; }
//---------------------------------------------------------------------------- void Smoke2D::Initialize () { TriMesh* square = mIP->GetRectangle(); RenderTarget* target0 = mIP->GetTarget(0); RenderTarget* target1 = mIP->GetTarget(1); RenderTarget* target2 = mIP->GetTarget(2); RenderTarget* target3 = mIP->GetTarget(3); mBoundaryNeumannInstance->SetPixelTexture(0, "StateSampler", target0->GetColorTexture(0)); mBoundaryDirichletInstance->SetPixelTexture(0, "StateSampler", target3->GetColorTexture(0)); if (mRenderer->PreDraw()) { mRenderer->SetCamera(mIP->GetCamera()); // Set the initial data. mCopyStateInstance->SetPixelTexture(0, "StateSampler", mInitialTexture); square->SetEffectInstance(mCopyStateInstance); mRenderer->Enable(target2); mRenderer->Draw(square); // in: InitialTexture mRenderer->Disable(target2); // out: Target2 mCopyStateInstance->SetPixelTexture(0, "StateSampler", target1->GetColorTexture(0)); // Set the mixed boundary conditions. square->SetEffectInstance(mBoundaryMixedInstance); mRenderer->Enable(target1); mRenderer->Draw(square); // in: Target2, MaskMixed, OffsetMixed mRenderer->Disable(target1); // out: Target1 mRenderer->PostDraw(); } }
//---------------------------------------------------------------------------- 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 ShadowMaps::CreateScene () { CreateScreenSpaceObjects(); CreateShaders(); // Create a scene graph containing a sphere and a plane. The sphere will // cast a shadow on the plane. mScene = new0 Node(); 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); StandardMesh sm(vformat); TriMesh* plane = sm.Rectangle(128, 128, 16.0f, 16.0f); plane->SetEffectInstance(mPlaneSceneInstance); mScene->AttachChild(plane); TriMesh* sphere = sm.Sphere(64, 64, 1.0f); sphere->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 1.0f)); sphere->SetEffectInstance(mSphereSceneInstance); mScene->AttachChild(sphere); }
//---------------------------------------------------------------------------- void GelatinCube::CreateBox () { // Create a quadratic spline using the interior particles as control // points. int numSlices = mModule->GetNumSlices() - 2; int numRows = mModule->GetNumRows() - 2; int numCols = mModule->GetNumCols() - 2; mSpline = new0 BSplineVolumef(numCols, numRows, numSlices, 2, 2, 2); for (int s = 0; s < numSlices; ++s) { for (int r = 0; r < numRows; ++r) { for (int c = 0; c < numCols; ++c) { mSpline->SetControlPoint(c, r, s, mModule->Position(s + 1, r + 1, c + 1)); } } } // Generate the box. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); VertexFormat* vformats[6] = { vformat, vformat, vformat, vformat, vformat, vformat }; mBox = new0 BoxSurface(mSpline, 8, 8, 8, vformats); // The texture effect for the box faces. std::string path = Environment::GetPathR("WaterWithAlpha.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = Texture2DEffect::CreateUniqueInstance( texture, Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT); for (int i = 0; i < 6; ++i) { TriMesh* mesh = StaticCast<TriMesh>(mBox->GetChild(i)); mesh->SetEffectInstance(instance); } // The texture has an alpha channel of 1/2 for all texels. instance->GetEffect()->GetAlphaState(0, 0)->BlendEnabled = true; mBox->EnableSorting(); mTrnNode->AttachChild(mBox); }
//---------------------------------------------------------------------------- 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* 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* ConvexHull3D::CreateSphere () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); Float3 white(1.0f, 1.0f, 1.0f); float radius = 0.01f; TriMesh* sphere = StandardMesh(vformat).Sphere(8, 8, radius); VertexBufferAccessor vba(sphere); for (int i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = white; } sphere->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); return sphere; }
//---------------------------------------------------------------------------- void SphereMaps::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0); TriMesh* mesh = StandardMesh(vformat).Torus(64, 64, 1.0f, 0.5f); mTrnNode->AttachChild(mesh); std::string effectFile = Environment::GetPathR("SphereMap.wmfx"); SphereMapEffect* effect = new0 SphereMapEffect(effectFile); std::string environmentName = Environment::GetPathR("SphereMap.wmtf"); Texture2D* environmentTexture = Texture2D::LoadWMTF(environmentName); mesh->SetEffectInstance(effect->CreateInstance(environmentTexture)); }
//---------------------------------------------------------------------------- BspNode* BspNodes::CreateNode (const Vector2f& v0, const Vector2f& v1, VertexColor3Effect* effect, const Float3& color) { // Create the model-space separating plane. Vector2f dir = v1 - v0; AVector normal(dir[1], -dir[0], 0.0f); normal.Normalize(); float constant = normal[0]*v0[0] + normal[1]*v0[1]; HPlane modelPlane(normal, constant); // Create the BSP node. BspNode* bsp = new0 BspNode(modelPlane); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); // Create the rectangle representation of the model plane and set the // vertex colors to the specified color. float xExtent = 0.5f*dir.Length(); float yExtent = 0.125f; TriMesh* rect = StandardMesh(vformat).Rectangle(2, 2, xExtent, yExtent); VertexBufferAccessor vba(rect); for (int i = 0; i < 4; ++i) { vba.Color<Float3>(0, i) = color; } rect->SetEffectInstance(effect->CreateInstance()); // Set the position and orientation for the world-space plane. APoint trn(0.5f*(v0[0] + v1[0]), 0.5f*(v0[1] + v1[1]), yExtent + 0.001f); HMatrix zRotate(AVector::UNIT_Z, Mathf::ATan2(dir.Y(),dir.X())); HMatrix xRotate(AVector::UNIT_X, Mathf::HALF_PI); HMatrix rotate = zRotate*xRotate; rect->LocalTransform.SetTranslate(trn); rect->LocalTransform.SetRotate(rotate); bsp->AttachCoplanarChild(rect); return bsp; }
//---------------------------------------------------------------------------- void ConvexHull3D::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); mCullState = new0 CullState(); mCullState->Enabled = false; mRenderer->SetOverrideCullState(mCullState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); TriMesh* sphere = StandardMesh(vformat).Sphere(8, 8, 0.01f); sphere->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); mTrnNode->SetChild(1, sphere); // The current file is "Data/data01.txt". LoadData(); }
//---------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- TriMesh* RoughPlaneSolidBox::CreateGround () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); TriMesh* ground = StandardMesh(vformat).Rectangle(2, 2, 32.0f, 32.0f); // Change the texture repeat. VertexBufferAccessor vba(ground); for (int i = 0; i < vba.GetNumVertices(); ++i) { Float2& tcoord = vba.TCoord<Float2>(0, i); tcoord[0] *= 8.0f; tcoord[1] *= 8.0f; } std::string path = Environment::GetPathR("Gravel.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); ground->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT)); return ground; }
//---------------------------------------------------------------------------- Node* SimplePendulumFriction::CreatePendulum () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0); StandardMesh sm(vformat); // Pendulum rod. TriMesh* rod = sm.Cylinder(2, 8, 0.05f, 12.0f, true); rod->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 10.0f)); // The pendulum bulb. Start with a sphere (to get the connectivity) and // then adjust the vertices to form a pair of joined cones. TriMesh* bulb = sm.Sphere(16, 32, 2.0f); VertexBufferAccessor vba(bulb); int numVertices = vba.GetNumVertices(); int i; for (i = 0; i < numVertices; ++i) { Float3& pos = vba.Position<Float3>(i); float r = Mathf::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]); float z = pos[2] + 2.0f; if (z >= 2.0f) { z = 4.0f - r; } else { z = r; } pos[2] = z; } // Translate the pendulum joint to the origin for the purpose of // rotation. for (i = 0; i < numVertices; ++i) { vba.Position<Float3>(i)[2] -= 16.0f; } bulb->UpdateModelSpace(Visual::GU_NORMALS); vba.ApplyTo(rod); numVertices = vba.GetNumVertices(); for (i = 0; i < numVertices; ++i) { vba.Position<Float3>(i)[2] -= 16.0f; } rod->UpdateModelSpace(Visual::GU_NORMALS); // Group the objects into a single subtree. mPendulum = new0 Node(); mPendulum->AttachChild(rod); mPendulum->AttachChild(bulb); // Translate back to original model position. mPendulum->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 16.0f)); // Add a material for coloring. Float4 black(0.0f, 0.0f, 0.0f, 1.0f); Float4 white(1.0f, 1.0f, 1.0f, 1.0f); Material* material = new0 Material(); material->Emissive = black; material->Ambient = Float4(0.1f, 0.1f, 0.1f, 1.0f); material->Diffuse = Float4(0.99607f, 0.83920f, 0.67059f, 1.0f); material->Specular = black; // Use two lights to illuminate the pendulum. Light* light[2]; light[0] = new0 Light(Light::LT_DIRECTIONAL); light[0]->Ambient = white; light[0]->Diffuse = white; light[0]->Specular = black; light[0]->SetDirection(AVector(-1.0f, -1.0f, 0.0f)); light[1] = new0 Light(Light::LT_DIRECTIONAL); light[1]->Ambient = white; light[1]->Diffuse = white; light[1]->Specular = black; light[1]->SetDirection(AVector(+1.0f, -1.0f, 0.0f)); // TODO: The following code is used to piece together an effect with // two passes. It is better to write an effect whose vertex shader // has constants corresponding to the two lights (for a single-pass // effect). LightDirPerVerEffect* effect = new0 LightDirPerVerEffect(); VisualTechnique* technique = effect->GetTechnique(0); VisualPass* pass0 = technique->GetPass(0); VisualPass* pass1 = new0 VisualPass(); pass1->SetVertexShader(pass0->GetVertexShader()); pass1->SetPixelShader(pass0->GetPixelShader()); AlphaState* astate = new0 AlphaState(); astate->BlendEnabled = true; astate->SrcBlend = AlphaState::SBM_ONE; astate->DstBlend = AlphaState::DBM_ONE; pass1->SetAlphaState(astate); pass1->SetCullState(pass0->GetCullState()); pass1->SetDepthState(pass0->GetDepthState()); pass1->SetStencilState(pass0->GetStencilState()); pass1->SetOffsetState(pass0->GetOffsetState()); pass1->SetWireState(pass0->GetWireState()); technique->InsertPass(pass1); VisualEffectInstance* instance = new0 VisualEffectInstance(effect, 0); for (int pass = 0; pass < 2; ++pass) { instance->SetVertexConstant(pass, 0, new0 PVWMatrixConstant()); instance->SetVertexConstant(pass, 1, new0 CameraModelPositionConstant()); instance->SetVertexConstant(pass, 2, new0 MaterialEmissiveConstant(material)); instance->SetVertexConstant(pass, 3, new0 MaterialAmbientConstant(material)); instance->SetVertexConstant(pass, 4, new0 MaterialDiffuseConstant(material)); instance->SetVertexConstant(pass, 5, new0 MaterialSpecularConstant(material)); instance->SetVertexConstant(pass, 6, new0 LightModelDVectorConstant(light[pass])); instance->SetVertexConstant(pass, 7, new0 LightAmbientConstant(light[pass])); instance->SetVertexConstant(pass, 8, new0 LightDiffuseConstant(light[pass])); instance->SetVertexConstant(pass, 9, new0 LightSpecularConstant(light[pass])); instance->SetVertexConstant(pass, 10, new0 LightAttenuationConstant(light[pass])); } rod->SetEffectInstance(instance); bulb->SetEffectInstance(instance); return mPendulum; }
//---------------------------------------------------------------------------- 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)); }
//---------------------------------------------------------------------------- bool NonlocalBlowup::OnInitialize () { if (!WindowApplication3::OnInitialize()) { return false; } #ifdef RUN_CONSOLE RunConsole(); return false; #endif mScene = new0 Node(); mScene->LocalTransform.SetRotate(HMatrix( 0.80475128f, 0.59107417f, -0.054833174f, 0.0f, -0.17529237f, 0.32487807f, 0.92936903f, 0.0f, 0.56714010f, -0.73829913f, 0.36505684f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f)); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); TriMesh* mesh = StandardMesh(vformat).Rectangle(256, 256, 16.0f, 16.0f); mScene->AttachChild(mesh); std::string gridName = Environment::GetPathR("Grid.wmtf"); Texture2D* gridTexture = Texture2D::LoadWMTF(gridName); gridTexture->GenerateMipmaps(); Texture1D* colorTexture = new0 Texture1D(Texture::TF_A8R8G8B8, 8, 1); unsigned char* color = (unsigned char*)colorTexture->GetData(0); color[ 0] = 128; color[ 1] = 128; color[ 2] = 128; color[ 3] = 255; color[ 4] = 255; color[ 5] = 0; color[ 6] = 128; color[ 7] = 255; color[ 8] = 255; color[ 9] = 0; color[10] = 0; color[11] = 255; color[12] = 0; color[13] = 255; color[14] = 0; color[15] = 255; color[16] = 0; color[17] = 255; color[18] = 255; color[19] = 255; color[20] = 0; color[21] = 128; color[22] = 255; color[23] = 255; color[24] = 0; color[25] = 0; color[26] = 255; color[27] = 255; color[28] = 255; color[29] = 255; color[30] = 255; color[31] = 255; float dt = 0.01f, dx = 1.0f, dy = 1.0f; // Uncomment only one of these at a time. NonconvexDomain0p50(dt, dx, dy); //SquareSymmetric0p01(dt, dx, dy); //SquareSymmetric0p50(dt, dx, dy); //SquareSymmetric0p99(dt, dx, dy); //SquareGaussX0p50(dt, dx, dy); //SquareGaussXY0p50(dt, dx, dy); //SquareGaussFour0p50(dt, dx, dy); DisplacementEffect* effect = new0 DisplacementEffect(); mesh->SetEffectInstance(effect->CreateInstance(mHeightTexture, gridTexture, colorTexture, mDomainTexture)); // Set up the camera so that it looks at the graph from slightly above // the xy-plane and at a skewed angle/direction of view. mCamera->SetFrustum(60.0f, GetAspectRatio(), 1.0f, 10000.0f); APoint camPosition(0.0f, 3.46f, 42.97f); AVector camDVector(0.0f, 0.0f, -1.0f); AVector camUVector(0.0f, 1.0f, 0.0f); AVector camRVector = camDVector.Cross(camUVector); mCamera->SetFrame(camPosition, camDVector, camUVector, camRVector); // Initial update of objects. mScene->Update(); // Initial culling of scene. mCuller.SetCamera(mCamera); mCuller.ComputeVisibleSet(mScene); InitializeCameraMotion(0.01f, 0.01f); InitializeObjectMotion(mScene); return true; }
//---------------------------------------------------------------------------- void Smoke2D::DoSimulationStep () { TriMesh* square = mIP->GetRectangle(); RenderTarget* target0 = mIP->GetTarget(0); RenderTarget* target1 = mIP->GetTarget(1); RenderTarget* target2 = mIP->GetTarget(2); RenderTarget* target3 = mIP->GetTarget(3); RenderTarget* target4 = mIP->GetTarget(4); mRenderer->SetCamera(mIP->GetCamera()); // Copy the current state for use in advection. square->SetEffectInstance(mCopyStateInstance); mRenderer->Enable(target4); mRenderer->Draw(square); // in: Target1 mRenderer->Disable(target4); // out: Target4 // Update the fluid. square->SetEffectInstance(mFluidUpdateInstance); mRenderer->Enable(target2); mRenderer->Draw(square); // in: Target1, Target4, Source mRenderer->Disable(target2); // out: Target2 // Set the mixed boundary conditions. square->SetEffectInstance(mBoundaryMixedInstance); mRenderer->Enable(target1); mRenderer->Draw(square); // in: Target2, MaskMixed, OffsetMixed mRenderer->Disable(target1); // out: Target1 // Compute the divergence. square->SetEffectInstance(mDivergenceInstance); mRenderer->Enable(target0); mRenderer->Draw(square); // in: Target1 mRenderer->Disable(target0); // out: Target0 // Set the Neumann boundary conditions. square->SetEffectInstance(mBoundaryNeumannInstance); mRenderer->Enable(target2); mRenderer->Draw(square); // in: Target0, OffsetNeumann mRenderer->Disable(target2); // out: Target2 // Solve Poisson's equation for the divergence. mRenderer->Enable(target0); Float4 saveClearColor = mRenderer->GetClearColor(); mRenderer->SetClearColor(Float4(0.0f, 0.0f, 0.0f, 0.0f)); mRenderer->ClearColorBuffer(); mRenderer->SetClearColor(saveClearColor); mRenderer->Disable(target0); for (int i = 0; i < mNumGaussSeidelIterations; ++i) { // Take one step of the Poisson solver. square->SetEffectInstance(mPoissonSolverInstance); mRenderer->Enable(target3); mRenderer->Draw(square); // in: Target2, Target0 mRenderer->Disable(target3); // out: Target3 // Set the Dirichlet boundary conditions. square->SetEffectInstance(mBoundaryDirichletInstance); mRenderer->Enable(target0); mRenderer->Draw(square); // in: Target3, MaskDirichlet mRenderer->Disable(target0); // out: Target0 } // Adjust the velocity vectors. square->SetEffectInstance(mAdjustVelocityInstance); mRenderer->Enable(target2); mRenderer->Draw(square); // in: Target0, mTarget1 mRenderer->Disable(target2); // out: Target2 // Set the mixed boundary conditions. square->SetEffectInstance(mBoundaryMixedInstance); mRenderer->Enable(target1); mRenderer->Draw(square); // in: Target2, MaskMixed, OffsetMixed mRenderer->Disable(target1); // out: Target1 // Draw the density. square->SetEffectInstance(mDrawDensityInstance); mRenderer->Draw(square); mTime += mDt; }
//---------------------------------------------------------------------------- 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 IntersectingBoxes::CreateScene () { // Create some axis-aligned boxes for intersection testing. const int imax = 16; int i; for (i = 0; i < imax; ++i) { float xMin = 0.5f*mSize*Mathf::SymmetricRandom(); float xMax = xMin + Mathf::IntervalRandom(8.0f, 32.0f); float yMin = 0.5f*mSize*Mathf::SymmetricRandom(); float yMax = yMin + Mathf::IntervalRandom(8.0f, 32.0f); float zMin = 0.5f*mSize*Mathf::SymmetricRandom(); float zMax = zMin + Mathf::IntervalRandom(8.0f, 32.0f); mBoxes.push_back( AxisAlignedBox3f(xMin, xMax, yMin, yMax, zMin, zMax)); } mManager = new0 BoxManagerf(mBoxes); // Scene graph for the visual representation of the boxes. mScene = new0 Node(); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Effects for boxes, blue for nonintersecting and red for intersecting. Float4 black(0.0f, 0.0f, 0.0f, 1.0f); Float4 white(1.0f, 1.0f, 1.0f, 1.0f); Material* blueMaterial = new0 Material(); blueMaterial->Emissive = black; blueMaterial->Ambient = Float4(0.25f, 0.25f, 0.25f, 1.0f); blueMaterial->Diffuse = Float4(0.0f, 0.0f, 1.0f, 1.0f); blueMaterial->Specular = black; Material* redMaterial = new0 Material(); redMaterial->Emissive = black; redMaterial->Ambient = Float4(0.25f, 0.25f, 0.25f, 1.0f); redMaterial->Diffuse = Float4(1.0f, 0.0f, 0.0f, 1.0f); redMaterial->Specular = black; // A light for the effects. Light* light = new0 Light(Light::LT_DIRECTIONAL); light->Ambient = white; light->Diffuse = white; light->Specular = black; light->SetDirection(AVector::UNIT_Z); LightDirPerVerEffect* effect = new0 LightDirPerVerEffect(); mNoIntersectEffect = effect->CreateInstance(light, blueMaterial); mIntersectEffect = effect->CreateInstance(light, redMaterial); // Create visual representations of the boxes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0); for (i = 0; i < imax; ++i) { APoint center( 0.5f*(mBoxes[i].Min[0] + mBoxes[i].Max[0]), 0.5f*(mBoxes[i].Min[1] + mBoxes[i].Max[1]), 0.5f*(mBoxes[i].Min[2] + mBoxes[i].Max[2])); Transform transform; transform.SetTranslate(center); float xExtent = 0.5f*(mBoxes[i].Max[0] - mBoxes[i].Min[0]); float yExtent = 0.5f*(mBoxes[i].Max[1] - mBoxes[i].Min[1]); float zExtent = 0.5f*(mBoxes[i].Max[2] - mBoxes[i].Min[2]); StandardMesh sm(vformat, true, false, &transform); TriMesh* mesh = sm.Box(xExtent, yExtent, zExtent); mesh->SetEffectInstance(mNoIntersectEffect); mScene->AttachChild(mesh); } }
//---------------------------------------------------------------------------- Node* RoughPlaneSolidBox::CreateBox () { mBox = new0 Node(); float xExtent = (float)mModule.XLocExt; float yExtent = (float)mModule.YLocExt; float zExtent = (float)mModule.ZLocExt; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); StandardMesh sm(vformat); VertexColor3Effect* effect = new0 VertexColor3Effect(); VertexBufferAccessor vba; Transform transform; TriMesh* face; int i; // +z face Float3 red(1.0f, 0.0f, 0.0f); transform.SetTranslate(APoint(0.0f, 0.0f, zExtent)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, xExtent, yExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = red; vba.Color<Float3>(0, 1) = red; vba.Color<Float3>(0, 2) = red; vba.Color<Float3>(0, 3) = red; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -z face Float3 darkRed(0.5f, 0.0f, 0.0f); transform.SetTranslate(APoint(0.0f, 0.0f, -zExtent)); transform.SetRotate(HMatrix(AVector::UNIT_Y, AVector::UNIT_X, -AVector::UNIT_Z, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, yExtent, xExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkRed; vba.Color<Float3>(0, 1) = darkRed; vba.Color<Float3>(0, 2) = darkRed; vba.Color<Float3>(0, 3) = darkRed; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // +y face Float3 green(0.0f, 1.0f, 0.0f); transform.SetTranslate(APoint(0.0f, yExtent, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Z, AVector::UNIT_X, AVector::UNIT_Y, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, zExtent, xExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = green; vba.Color<Float3>(0, 1) = green; vba.Color<Float3>(0, 2) = green; vba.Color<Float3>(0, 3) = green; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -y face Float3 darkGreen(0.0f, 1.0f, 0.0f); transform.SetTranslate(APoint(0.0f, -yExtent, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_X, AVector::UNIT_Z, -AVector::UNIT_Y, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, xExtent, zExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkGreen; vba.Color<Float3>(0, 1) = darkGreen; vba.Color<Float3>(0, 2) = darkGreen; vba.Color<Float3>(0, 3) = darkGreen; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // +x face Float3 blue(0.0f, 0.0f, 1.0f); transform.SetTranslate(APoint(xExtent, 0.0f, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Y, AVector::UNIT_Z, AVector::UNIT_X, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, yExtent, zExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = blue; vba.Color<Float3>(0, 1) = blue; vba.Color<Float3>(0, 2) = blue; vba.Color<Float3>(0, 3) = blue; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -x face Float3 darkBlue(0.0f, 0.0f, 1.0f); transform.SetTranslate(APoint(-xExtent, 0.0f, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Z, AVector::UNIT_Y, -AVector::UNIT_X, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, zExtent, yExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkBlue; vba.Color<Float3>(0, 1) = darkBlue; vba.Color<Float3>(0, 2) = darkBlue; vba.Color<Float3>(0, 3) = darkBlue; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); MoveBox(); return mBox; }
//---------------------------------------------------------------------------- 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 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()); }
//---------------------------------------------------------------------------- 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 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)); }