//---------------------------------------------------------------------------- void Fluids3D::CreateScene () { // Get fluid solver parameters. const int bound0M1 = mSmoke->GetIMax(); const int bound1M1 = mSmoke->GetJMax(); const int bound2M1 = mSmoke->GetKMax(); const int bound0 = bound0M1 + 1; const int bound1 = bound1M1 + 1; const int bound2 = bound2M1 + 1; const int quantity = bound0*bound1*bound2; const float* x = mSmoke->GetX(); const float* y = mSmoke->GetY(); const float* z = mSmoke->GetZ(); #ifdef USE_PARTICLES // Create the vertex format. VertexFormat* vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); #else VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); #endif // Create the vertex buffer for the cube. #ifdef USE_PARTICLES const int numVertices = 4*quantity; #else const int numVertices = quantity; #endif int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); int i0, i1, i2, index; #ifdef USE_PARTICLES const float delta = mSmoke->GetDx(); Float4* posSize = new1<Float4>(quantity); for (i2 = 0, index = 0; i2 < bound2; ++i2) { for (i1 = 0; i1 < bound1; ++i1) { for (i0 = 0; i0 < bound0; ++i0, ++index) { posSize[index] = Float4(x[i0], y[i1], z[i2], delta); } } } mCube = new0 Particles(vformat, vbuffer, 4, posSize, 1.0f); UpdateVertexBuffer(); IndexBuffer* ibuffer = mCube->GetIndexBuffer(); #else VertexBufferAccessor vba(vformat, vbuffer); for (i2 = 0, index = 0; i2 < bound2; ++i2) { for (i1 = 0; i1 < bound1; ++i1) { for (i0 = 0; i0 < bound0; ++i0, ++index) { vba.Position<Float3>(index) = Float3(x[i0], y[i1], z[i2]); } } } // Create the index buffer for the cube. const int numIndices = 6*bound0M1*bound1M1*bound2 + 6*bound0M1*bound1*bound2M1 + 6*bound0*bound1M1*bound2M1; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); const int bound01 = bound0*bound1; int j0, j1, j2, j3; for (i2 = 0; i2 < bound2; ++i2) { for (i1 = 0; i1 < bound1M1; ++i1) { for (i0 = 0; i0 < bound0M1; ++i0) { j0 = i0 + bound0*(i1 + bound1*i2); j1 = j0 + 1; j2 = j1 + bound0; j3 = j2 - 1; *indices++ = j0; *indices++ = j1; *indices++ = j2; *indices++ = j0; *indices++ = j2; *indices++ = j3; } } } for (i1 = 0; i1 < bound1; ++i1) { for (i2 = 0; i2 < bound2M1; ++i2) { for (i0 = 0; i0 < bound0M1; ++i0) { j0 = i0 + bound0*(i1 + bound1*i2); j1 = j0 + 1; j2 = j1 + bound01; j3 = j2 - 1; *indices++ = j0; *indices++ = j1; *indices++ = j2; *indices++ = j0; *indices++ = j2; *indices++ = j3; } } } for (i0 = 0; i0 < bound0; ++i0) { for (i1 = 0; i1 < bound1M1; ++i1) { for (i2 = 0; i2 < bound2M1; ++i2) { j0 = i0 + bound0*(i1 + bound1*i2); j1 = j0 + bound0; j2 = j1 + bound01; j3 = j2 - bound0; *indices++ = j0; *indices++ = j1; *indices++ = j2; *indices++ = j0; *indices++ = j2; *indices++ = j3; } } } mCube = new0 TriMesh(vformat, vbuffer, ibuffer); UpdateVertexBuffer(); #endif mNumIndices = ibuffer->GetNumElements(); mIndices = new1<int>(mNumIndices); memcpy(mIndices, ibuffer->GetData(), mNumIndices*sizeof(int)); // Create the cube effect. #ifdef USE_PARTICLES std::string path = Environment::GetPathR("Disk.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = VertexColor4TextureEffect::CreateUniqueInstance(texture, Shader::SF_NEAREST, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE); #else VertexColor4Effect* effect = new0 VertexColor4Effect(); VisualEffectInstance* instance = effect->CreateInstance(); #endif const VisualPass* pass = instance->GetPass(0); AlphaState* astate = pass->GetAlphaState(); astate->BlendEnabled = true; CullState* cstate = pass->GetCullState(); cstate->Enabled = false; DepthState* dstate = pass->GetDepthState(); dstate->Enabled = false; dstate->Writable = false; mCube->SetEffectInstance(instance); mScene = new0 Node(); mScene->AttachChild(mCube); }
//---------------------------------------------------------------------------- void BillboardNodes::CreateScene () { mScene = new0 Node(); mCullState = new0 CullState(); mRenderer->SetOverrideCullState(mCullState); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // All triangle meshes have this common vertex format. Use StandardMesh // to create these meshes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); StandardMesh stdMesh(vformat); // Create the ground. It covers a square with vertices (1,1,0), (1,-1,0), // (-1,1,0), and (-1,-1,0). Multiply the texture coordinates by a factor // to enhance the wrap-around. mGround = stdMesh.Rectangle(2, 2, 16.0f, 16.0f); VertexBufferAccessor vba(mGround); int i; for (i = 0; i < vba.GetNumVertices(); ++i) { Float2& tcoord = vba.TCoord<Float2>(0, i); tcoord[0] *= 128.0f; tcoord[1] *= 128.0f; } // Create a texture effect for the ground. std::string path = Environment::GetPathR("Horizontal.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = Texture2DEffect::CreateUniqueInstance( texture, Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT); mGround->SetEffectInstance(instance); mScene->AttachChild(mGround); // Create a rectangle mesh. The mesh is in the xy-plane. Do not apply // local transformations to the mesh. Use the billboard node transforms // to control the mesh location and orientation. mRectangle = stdMesh.Rectangle(2, 2, 0.125f, 0.25f); // Create a texture effect for the rectangle and for the torus. Texture2DEffect* geomEffect = new0 Texture2DEffect(Shader::SF_LINEAR); path = Environment::GetPathR("RedSky.wmtf"); texture = Texture2D::LoadWMTF(path); mRectangle->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes a rectangle to always be facing // the camera. This is the type of billboard for an avatar. mBillboard0 = new0 BillboardNode(mCamera); mBillboard0->AttachChild(mRectangle); mScene->AttachChild(mBillboard0); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard0->LocalTransform.SetTranslate(APoint(-0.25f, 0.0f, 0.25f)); mBillboard0->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); // Create a torus mesh. Do not apply local transformations to the mesh. // Use the billboard node transforms to control the mesh location and // orientation. mTorus = StandardMesh(vformat, false).Torus(16, 16, 1.0f, 0.25f); mTorus->LocalTransform.SetUniformScale(0.1f); // Create a texture effect for the torus. It uses the RedSky image that // the rectangle uses. mTorus->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes an object to always be oriented // the same way relative to the camera. mBillboard1 = new0 BillboardNode(mCamera); mBillboard1->AttachChild(mTorus); mScene->AttachChild(mBillboard1); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard1->LocalTransform.SetTranslate(APoint(0.25f, 0.0f, 0.25f)); mBillboard1->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); #ifdef DEMONSTRATE_VIEWPORT_BOUNDING_RECTANGLE // The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z') // in [-1,1]^2 x [0,1]. mSSCamera = new0 Camera(false); mSSCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mSSCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // Create a semitransparent screen rectangle. VertexFormat* ssVFormat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); int ssVStride = ssVFormat->GetStride(); VertexBuffer* ssVBuffer = new0 VertexBuffer(4, ssVStride); VertexBufferAccessor ssVba(ssVFormat, ssVBuffer); Float4 ssColor(0.0f, 0.0f, 1.0f, 0.25f); ssVba.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.0f); ssVba.Position<Float3>(1) = Float3(1.0f, 0.0f, 0.0f); ssVba.Position<Float3>(2) = Float3(1.0f, 1.0f, 0.0f); ssVba.Position<Float3>(3) = Float3(0.0f, 1.0f, 0.0f); ssVba.Color<Float4>(0, 0) = ssColor; ssVba.Color<Float4>(0, 1) = ssColor; ssVba.Color<Float4>(0, 2) = ssColor; ssVba.Color<Float4>(0, 3) = ssColor; IndexBuffer* ssIBuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ssIBuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; mSSRectangle = new0 TriMesh(ssVFormat, ssVBuffer, ssIBuffer); mSSRectangle->Update(); // Create a vertex color effect for the screen rectangle. VertexColor4Effect* ssEffect = new0 VertexColor4Effect(); mSSRectangle->SetEffectInstance(ssEffect->CreateInstance()); // Alpha blending must be enabled to obtain the semitransparency. ssEffect->GetAlphaState(0, 0)->BlendEnabled = true; #endif }