//---------------------------------------------------------------------------- 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 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); } }
//---------------------------------------------------------------------------- VisualEffectInstance* LightDirPerVerEffect::CreateUniqueInstance ( Light* light, Material* material) { LightDirPerVerEffect* effect = new0 LightDirPerVerEffect(); return effect->CreateInstance(light, material); }