//---------------------------------------------------------------------------- VisualEffectInstance::VisualEffectInstance (const VisualEffect* effect, int techniqueIndex) : mEffect((VisualEffect*)effect), // conceptual constness mTechniqueIndex(techniqueIndex) { assertion(effect != 0, "Effect must be specified.\n"); assertion( 0 <= techniqueIndex && techniqueIndex < effect->GetNumTechniques(), "Invalid technique index.\n"); VisualTechnique* technique = mEffect->GetTechnique(mTechniqueIndex); mNumPasses = technique->GetNumPasses(); mVertexParameters = new1<ShaderParametersPtr>(mNumPasses); mPixelParameters = new1<ShaderParametersPtr>(mNumPasses); int p; for (p = 0; p < mNumPasses; ++p) { VisualPass* pass = technique->GetPass(p); mVertexParameters[p] = new0 ShaderParameters(pass->GetVertexShader()); mPixelParameters[p] = new0 ShaderParameters(pass->GetPixelShader()); } }
//---------------------------------------------------------------------------- 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; }