//---------------------------------------------------------------------------- void RenderToTexture::CreateScene () { // Create the root of the scene. mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Create a screen-space camera to use with the render target. mScreenCamera = ScreenTarget::CreateCamera(); // Create a screen polygon to use with the render target. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); const int rtWidth = 256, rtHeight = 256; mScreenPolygon = ScreenTarget::CreateRectangle(vformat, rtWidth, rtHeight, 0.0f, 0.2f, 0.0f, 0.2f, 0.0f); // Create the render target. //Texture::Format tformat = Texture::TF_A8B8G8R8; // DX9 fails Texture::Format tformat = Texture::TF_A8R8G8B8; //Texture::Format tformat = Texture::TF_A16B16G16R16; //Texture::Format tformat = Texture::TF_A16B16G16R16F; //Texture::Format tformat = Texture::TF_A32B32G32R32F; mRenderTarget = new0 RenderTarget(1, tformat, rtWidth, rtHeight, false, false); // Attach the render target texture to the screen polygon mesh. mScreenPolygon->SetEffectInstance(Texture2DEffect::CreateUniqueInstance( mRenderTarget->GetColorTexture(0), Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); // Load the face model and use multitexturing. #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); TriMeshPtr mesh = DynamicCast<TriMesh>(inStream.GetObjectAt(0)); // Create texture coordinates for the face. Based on knowledge of the // mesh, the (x,z) values of the model-space vertices may be mapped to // (s,t) in [0,1]^2. VertexBufferAccessor vba0(mesh); const int numVertices = vba0.GetNumVertices(); float xmin = Mathf::MAX_REAL, xmax = -Mathf::MAX_REAL; float zmin = Mathf::MAX_REAL, zmax = -Mathf::MAX_REAL; int i; for (i = 1; i < numVertices; ++i) { Float3 position = vba0.Position<Float3>(i); float x = position[0]; if (x < xmin) { xmin = x; } if (x > xmax) { xmax = x; } float z = position[2]; if (z < zmin) { zmin = z; } if (z > zmax) { zmax = z; } } float invXRange = 1.0f/(xmax - xmin); float invZRange = 1.0f/(zmax - zmin); // Strip out the normal vectors, because there is no lighting in this // sample. Add in two texture coordinate channels for a multiplicative // texture effect. vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 1); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba1(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { Float3 position = vba0.Position<Float3>(i); Float2 tcoord( (position[0] - xmin)*invXRange, (position[2] - zmin)*invZRange); vba1.Position<Float3>(i) = position; vba1.TCoord<Float2>(0, i) = tcoord; vba1.TCoord<Float2>(1, i) = tcoord; } mesh->SetVertexFormat(vformat); mesh->SetVertexBuffer(vbuffer); path = Environment::GetPathR("Leaf.wmtf"); Texture2D* texture0 = Texture2D::LoadWMTF(path); path = Environment::GetPathR("Water.wmtf"); Texture2D* texture1 = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = Texture2AddEffect::CreateUniqueInstance( texture0, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE, texture1, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE); mesh->SetEffectInstance(instance); mTrnNode->AttachChild(mesh); }
//---------------------------------------------------------------------------- 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); } }
//---------------------------------------------------------------------------- bool StructuredBuffersWindow::CreateScene() { // Create the shaders and associated resources HLSLDefiner definer; definer.SetInt("WINDOW_WIDTH", mXSize); std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!vshader) { return false; } std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!pshader) { return false; } std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); vshader->Set("PVWMatrix", cbuffer); // Create the pixel shader and associated resources. std::string path = mEnvironment.GetPath("StoneWall.png"); std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, false)); pshader->Set("baseTexture", baseTexture); std::shared_ptr<SamplerState> baseSampler(new SamplerState()); baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P; baseSampler->mode[0] = SamplerState::CLAMP; baseSampler->mode[1] = SamplerState::CLAMP; pshader->Set("baseSampler", baseSampler); mDrawnPixels.reset(new StructuredBuffer(mXSize*mYSize, sizeof(Vector4<float>))); mDrawnPixels->SetUsage(Resource::SHADER_OUTPUT); mDrawnPixels->SetCopyType(Resource::COPY_BIDIRECTIONAL); memset(mDrawnPixels->GetData(), 0, mDrawnPixels->GetNumBytes()); pshader->Set("drawnPixels", mDrawnPixels); // Create the visual effect for the square. std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader)); // Create a vertex buffer for a single triangle. The PNG is stored in // left-handed coordinates. The texture coordinates are chosen to reflect // the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = Vector3<float>(0.0f, 0.0f, 0.0f); vertex[0].tcoord = Vector2<float>(0.0f, 1.0f); vertex[1].position = Vector3<float>(1.0f, 0.0f, 0.0f); vertex[1].tcoord = Vector2<float>(1.0f, 1.0f); vertex[2].position = Vector3<float>(0.0f, 1.0f, 0.0f); vertex[2].tcoord = Vector2<float>(0.0f, 0.0f); vertex[3].position = Vector3<float>(1.0f, 1.0f, 0.0f); vertex[3].tcoord = Vector2<float>(1.0f, 0.0f); // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare.reset(new Visual(vbuffer, ibuffer, effect)); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); mSquare->Update(); // Enable automatic updates of pvw-matrices and w-matrices. SubscribeCW(mSquare, cbuffer); // The structured buffer is written in the pixel shader. This texture // will receive a copy of it so that we can write the results to disk // as a PNG file. mDrawnPixelsTexture = new Texture2(DF_R8G8B8A8_UNORM, mXSize, mYSize); return true; }
bool ModelDefinition::Deserialize(Deserializer &deserializer) { // Clear everything. this->ClearMeshes(); this->ClearBones(); this->ClearAnimations(true); // <-- 'true' = clear animation segments, too. this->ClearConvexHulls(); // We keep looping until we hit the null or unknown chunk. Serialization::ChunkHeader header; while (deserializer.Peek(&header, sizeof(header)) == sizeof(header)) { bool finished = false; switch (header.id) { case Serialization::ChunkID_Model_Bones: { deserializer.Seek(sizeof(header)); if (header.version == 1) { uint32_t boneCount; deserializer.Read(boneCount); for (uint32_t iBone = 0; iBone < boneCount; ++iBone) { // Name. String name; deserializer.ReadString(name); // Local transform. glm::vec3 position; glm::quat rotation; glm::vec3 scale; deserializer.Read(position); deserializer.Read(rotation); deserializer.Read(scale); // 4x4 offset matrix. glm::mat4 offsetMatrix; deserializer.Read(offsetMatrix); auto bone = new Bone; bone->SetName(name.c_str()); bone->SetPosition(position); bone->SetRotation(rotation); bone->SetScale(scale); bone->SetOffsetMatrix(offsetMatrix); this->AddBone(bone); // We need to create a channel for this bone. We then need to map that channel to a bone. auto &channel = m_animation.CreateChannel(); this->animationChannelBones.Add(bone, &channel); } // Parents. auto boneParentIndices = static_cast<uint32_t*>(malloc(boneCount * sizeof(uint32_t))); deserializer.Read(boneParentIndices, boneCount * sizeof(uint32_t)); for (uint32_t iBone = 0; iBone < boneCount; ++iBone) { uint32_t parentIndex = boneParentIndices[iBone]; if (parentIndex != static_cast<uint32_t>(-1)) { m_bones[parentIndex]->AttachChild(*m_bones[iBone]); } } free(boneParentIndices); } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Model_Meshes: { deserializer.Seek(sizeof(header)); if (header.version == 1) { uint32_t meshCount; deserializer.Read(meshCount); for (uint32_t iMesh = 0; iMesh < meshCount; ++iMesh) { ModelDefinition::Mesh newMesh(m_context); // Name. deserializer.ReadString(newMesh.name); // Material String materialName; deserializer.ReadString(materialName); newMesh.material = m_context.GetMaterialLibrary().Create(materialName.c_str()); // Geometry VertexFormat vertexFormat; vertexFormat.Deserialize(deserializer); newMesh.geometry = Renderer::CreateVertexArray(VertexArrayUsage_Static, vertexFormat); // Vertices. uint32_t vertexCount; deserializer.Read(vertexCount); if (vertexCount > 0) { newMesh.geometry->SetVertexData(nullptr, static_cast<size_t>(vertexCount)); auto vertexData = newMesh.geometry->MapVertexData(); { deserializer.Read(vertexData, vertexCount * vertexFormat.GetSizeInBytes()); } newMesh.geometry->UnmapVertexData(); } // Indices. uint32_t indexCount; deserializer.Read(indexCount); if (indexCount > 0) { newMesh.geometry->SetIndexData(nullptr, static_cast<size_t>(indexCount)); auto indexData = newMesh.geometry->MapIndexData(); { deserializer.Read(indexData, indexCount * sizeof(uint32_t)); } newMesh.geometry->UnmapIndexData(); } // Skinning Vertex Attributes uint32_t skinningVertexAttributeCount; deserializer.Read(skinningVertexAttributeCount); if (skinningVertexAttributeCount > 0) { newMesh.skinningVertexAttributes = new SkinningVertexAttribute[skinningVertexAttributeCount]; auto counts = static_cast<uint16_t*>(malloc(skinningVertexAttributeCount * sizeof(uint16_t))); deserializer.Read(counts, skinningVertexAttributeCount * sizeof(uint16_t)); uint32_t totalBoneWeights; deserializer.Read(totalBoneWeights); auto boneWeights = static_cast<BoneWeightPair*>(malloc(totalBoneWeights * sizeof(BoneWeightPair))); deserializer.Read(boneWeights, totalBoneWeights * sizeof(BoneWeightPair)); auto currentBoneWeight = boneWeights; for (uint32_t iVertex = 0; iVertex < skinningVertexAttributeCount; ++iVertex) { auto count = counts[iVertex]; // Here we allocate the buffer for the bones. We trick the vector here by modifying attributes directly. newMesh.skinningVertexAttributes[iVertex].bones.Reserve(count); newMesh.skinningVertexAttributes[iVertex].bones.count = count; for (uint16_t iBone = 0; iBone < count; ++iBone) { newMesh.skinningVertexAttributes[iVertex].bones[iBone] = *currentBoneWeight++; } } free(counts); free(boneWeights); } // Uniforms. newMesh.defaultUniforms.Deserialize(deserializer); // Finally, add the mesh. this->AddMesh(newMesh); } } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Model_Animation: { deserializer.Seek(sizeof(header)); if (header.version == 1) { uint32_t keyFrameCount; deserializer.Read(keyFrameCount); for (size_t iKeyFrame = 0; iKeyFrame < keyFrameCount; ++iKeyFrame) { float time; deserializer.Read(time); size_t keyFrameIndex = m_animation.AppendKeyFrame(static_cast<double>(time)); // With the key frame added, we now need to iterate over each channel in the key frame. uint32_t channelCount; deserializer.Read(channelCount); for (uint32_t iChannel = 0; iChannel < channelCount; ++iChannel) { uint32_t boneIndex; deserializer.Read(boneIndex); auto bone = m_bones[boneIndex]; assert(bone != nullptr); { auto iChannelBone = this->animationChannelBones.Find(bone); assert(iChannelBone != nullptr); { auto channel = iChannelBone->value; glm::vec3 position; glm::quat rotation; glm::vec3 scale; deserializer.Read(position); deserializer.Read(rotation); deserializer.Read(scale); auto key = new TransformAnimationKey(position, rotation, scale); channel->SetKey(keyFrameIndex, key); // We need to cache the key. this->animationKeyCache.PushBack(key); } } } } deserializer.Read(this->animationAABBPadding); } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Model_AnimationSegments: { deserializer.Seek(sizeof(header)); if (header.version == 1) { uint32_t animationSegmentCount; deserializer.Read(animationSegmentCount); for (uint32_t iSegment = 0; iSegment < animationSegmentCount; ++iSegment) { String name; uint32_t startKeyFrame; uint32_t endKeyFrame; deserializer.ReadString(name); deserializer.Read(startKeyFrame); deserializer.Read(endKeyFrame); m_animation.AddNamedSegment(name.c_str(), static_cast<size_t>(startKeyFrame), static_cast<size_t>(endKeyFrame)); } } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Model_AnimationSequences: { deserializer.Seek(sizeof(header)); if (header.version == 1) { } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Model_ConvexHulls: { deserializer.Seek(sizeof(header)); if (header.version == 1) { uint32_t convexHullCount; deserializer.Read(convexHullCount); uint32_t* vertexCounts = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t))); uint32_t* indexCounts = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t))); deserializer.Read(vertexCounts, convexHullCount * sizeof(uint32_t)); deserializer.Read(indexCounts, convexHullCount * sizeof(uint32_t)); uint32_t totalVertexCount; deserializer.Read(totalVertexCount); uint32_t totalIndexCount; deserializer.Read(totalIndexCount); auto vertices = static_cast<float* >(malloc(totalVertexCount * sizeof(float))); auto indices = static_cast<uint32_t*>(malloc(totalIndexCount * sizeof(uint32_t))); deserializer.Read(vertices, totalVertexCount * sizeof(float)); deserializer.Read(indices, totalIndexCount * sizeof(uint32_t)); auto currentVertices = vertices; auto currentIndices = indices; for (uint32_t iConvexHull = 0; iConvexHull < convexHullCount; ++iConvexHull) { size_t vertexCount = static_cast<size_t>(vertexCounts[iConvexHull]); size_t indexCount = static_cast<size_t>(indexCounts[iConvexHull]); m_convexHulls.PushBack(new ConvexHull(currentVertices, vertexCount, currentIndices, indexCount)); // Now we need to move our pointers forward. currentVertices += vertexCount * 3; currentIndices += indexCount; } // Build Settings. deserializer.Read(this->convexHullBuildSettings); free(vertexCounts); free(indexCounts); free(vertices); free(indices); } else { // Unsupported Version. deserializer.Seek(header.sizeInBytes); } break; } case Serialization::ChunkID_Null: { deserializer.Seek(sizeof(header)); finished = true; break; } default: { // Unknown chunk = Error. finished = true; return false; } } if (finished) { break; } } // If we get here, we were successful. return true; }
int WINAPI WinMain( HINSTANCE inst, HINSTANCE, LPSTR cmdLine, int cmdShow ) { Window wnd; P(Context) context = 0; int sw = 640; int sh = 480; int sbpp = 0; bool fullscreen = (0 != sbpp); P(Scene) root = 0; try { // args String fxname = cmdLine; if ( fxname == "" ) fxname = "bump.fx"; // init window DWORD style = WS_VISIBLE; DWORD styleEx = 0; if ( fullscreen ) { style |= WS_POPUP; styleEx |= WS_EX_TOPMOST; } else { style |= WS_OVERLAPPEDWINDOW; } wnd.create( "sgtestclass", "sg test", style, styleEx, 0, 0, sw, sh, inst, 0 ); // init context context = new Context( "gd_dx8" ); context->open( sw, sh, sbpp, 75, Context::SURFACE_TARGET + Context::SURFACE_DEPTH + Context::SURFACE_STENCIL, Context::RASTERIZER_HW, Context::VERTEXP_HW, Context::TC_DISABLED ); // scene root = new Scene; root->setName( "root" ); // camera P(Camera) cam = new Camera; cam->setName( "cam" ); cam->setPosition( Vector3(0,1.5f,-3) ); Matrix3x3 rot = Matrix3x3( Vector3(1,0,0), Math::toRadians(30.f) ); cam->setRotation( rot ); cam->setHorizontalFov( Math::toRadians(100.f) ); cam->setFront( 0.2f ); cam->setBack( 100.f ); cam->linkTo( root ); // light P(DirectLight) lt = new DirectLight; lt->setName( "keylight" ); lt->setIntensity( 0.5f ); lt->linkTo( root ); lt->lookAt( Vector3(-0.5f,-1,0) ); // resources P(Texture) difmap = loadTex( "diffuse_map.tga" ); P(Texture) normmap = loadTex( "normal_map.tga" ); P(CubeTexture) envmap = loadCubeTex( "TestCubeTexture1.dds" ); // read vb and ib data FileInputStream vbin( "vb.dat" ); Array<uint8_t> vbbytes( vbin.available() ); vbin.read( vbbytes.begin(), vbbytes.size() ); int vertexSize = 4*3*4; int vertices = vbbytes.size() / vertexSize; FileInputStream ibin( "ib.dat" ); Array<uint8_t> ibbytes( ibin.available() ); ibin.read( ibbytes.begin(), ibbytes.size() ); int indexSize = 2; int indices = ibbytes.size() / indexSize; // geometry (indirectly from vb and ib dat) VertexFormat vf; vf.addNormal().addTextureCoordinate(3); P(Model) model = new Model( vertices, indices, vf ); { VertexAndIndexLock<Model> lk( model, Model::LOCK_READWRITE ); for ( int i = 0 ; i < vertices ; ++i ) { model->setVertexPositions( i, (Vector3*)(vbbytes.begin()+i*vertexSize) ); model->setVertexNormals( i, (Vector3*)(vbbytes.begin()+12+i*vertexSize) ); model->setVertexTextureCoordinates( i, 0, 3, (float*)(vbbytes.begin()+24+i*vertexSize) ); } void* idata; int istride; model->getIndexData( &idata, &istride ); memcpy( idata, ibbytes.begin(), ibbytes.size() ); } // env transform Matrix4x4 textm(0); textm(0,0) = 1.f; textm(1,1) = 1.f; textm(2,2) = 1.f; textm(0,3) = 0.f; textm(1,3) = 0.f; textm(2,3) = 0.f; // material P(Material) mat = new Material; mat->setTexture( 0, difmap ); mat->setTexture( 1, envmap ); mat->setTextureColorCombine( 1, Material::TA_TEXTURE, Material::TOP_ADD, Material::TA_CURRENT ); mat->setTextureCoordinateTransform( 1, Material::TTFF_COUNT3, textm ); mat->setTextureCoordinateSource( 1, Material::TCS_CAMERASPACENORMAL ); mat->setVertexFormat( model->vertexFormat() ); model->setShader( mat ); // mesh P(Mesh) mesh = new Mesh; mesh->setName( "mesh" ); mesh->linkTo( root ); mesh->addPrimitive( model ); cam->setRotationController( new sgu::LookAtControl(cam,mesh) ); // floor vf = VertexFormat(); vf.addNormal().addTextureCoordinate(2).addTextureCoordinate(2); P(Model) floormodel = createCube( 10, 0.01f, 10, vf ); mat = new Material; mat->setDiffuseColor( Colorf(0,0,0) ); mat->setEmissiveColor( Colorf(0.2f,0.2f,0.2f) ); mat->setVertexFormat( floormodel->vertexFormat() ); floormodel->setShader( mat ); P(Mesh) floor = new Mesh; floor->setName( "floor" ); floor->linkTo( root ); floor->setPosition( Vector3(0,-2,0) ); floor->addPrimitive( floormodel ); // mesh position animation int keys = 8; {P(VectorInterpolator) anim = new VectorInterpolator(3); anim->setKeys( keys ); for ( int i = 0 ; i < keys ; ++i ) { float f = (float)i / (keys-1); float v[3] = { Math::sin(f*Math::PI*2.f)*2.f, 0, 0 }; anim->setKeyValue( i, v, 3 ); anim->setKeyTime( i, f * 4.f ); } anim->sortKeys(); mesh->setPositionController( anim );} // mesh rotation animation {P(QuaternionInterpolator) anim = new QuaternionInterpolator; anim->setKeys( keys ); for ( int i = 0 ; i < keys ; ++i ) { float f = (float)i / (keys-1); float ang = f * Math::PI*2.f; Quaternion quat( Vector3(0,1,0), ang ); float v[] = {quat.x, quat.y, quat.z, quat.w}; anim->setKeyValue( i, v, 4 ); anim->setKeyTime( i, f * 3.f ); } anim->sortKeys(); mesh->setRotationController( anim );} // mesh scale animation /*{P(VectorInterpolator) anim = new VectorInterpolator(3); anim->setKeys( keys ); for ( int i = 0 ; i < keys ; ++i ) { float f = (float)i / (keys-1); float v[3] = { Math::abs(Math::sin(f*Math::PI*2.f))+.5f, 1.f, 1.f }; anim->setKeyValue( i, v, 3 ); anim->setKeyTime( i, f * 5.f ); } anim->sortKeys(); mesh->setScaleController( anim );}*/ // shadow volume P(ShadowVolume) shadow = new ShadowVolume( model, lt->worldDirection(), 20.f ); shadow->setShader( new ShadowShader ); mesh->addPrimitive( shadow ); // shadow filler VertexFormat fillvf; fillvf.addRHW().addDiffuse(); P(Material) fillmat = new Material; fillmat->setDepthEnabled( false ); fillmat->setDepthWrite( false ); fillmat->setBlend( Material::BLEND_SRCALPHA, Material::BLEND_INVSRCALPHA ); fillmat->setTextureColorCombine( 0, Material::TA_DIFFUSE, Material::TOP_SELECTARG1, Material::TextureArgument() ); fillmat->setTextureAlphaCombine( 0, Material::TA_DIFFUSE, Material::TOP_SELECTARG1, Material::TextureArgument() ); fillmat->setLighting( false ); fillmat->setVertexColor( true ); fillmat->setStencil( true ); fillmat->setStencilRef( 1 ); fillmat->setStencilFunc( Material::CMP_LESSEQUAL ); fillmat->setStencilPass( Material::STENCILOP_KEEP ); fillmat->setPass( ShadowShader::DEFAULT_SHADOW_FILL_PASS ); fillmat->setVertexFormat( fillvf ); // shadow filler geometry P(Model) fillgeom = new Model( 4, 6, fillvf ); {VertexAndIndexLock<Model> lock( fillgeom, Model::LOCK_WRITE ); Vector4 fillpos[4] = { Vector4(0,0,0,0), Vector4(sw,0,0,0), Vector4(sw,sh,0,0), Vector4(0,sh,0,0) }; Color fillcolr[4] = { Color(0,0,0,80), Color(0,0,0,80), Color(0,0,0,80), Color(0,0,0,80) }; int fillind[6] = { 0,1,2, 0,2,3 }; fillgeom->setVertexPositionsRHW( 0, fillpos, 4 ); fillgeom->setVertexDiffuseColors( 0, fillcolr, 4 ); fillgeom->setIndices( 0, fillind, 6 );} fillgeom->setShader( fillmat ); mesh->addPrimitive( fillgeom ); // mainloop long prevTime = System::currentTimeMillis(); float time = 0.f; while ( Window::flushWindowMessages() ) { long curTime = System::currentTimeMillis(); float dt = 1e-3f * (float)(curTime - prevTime); prevTime = curTime; if ( wnd.active() ) { if ( GetKeyState('S') < 0 ) dt *= 0.1f; if ( GetKeyState('R') < 0 ) time = 0.f; if ( GetKeyState(VK_ESCAPE) < 0 ) break; time += dt; for ( Node* node = root ; node ; node = node->nextInHierarchy() ) node->setState( time ); context->beginScene(); cam->render(); context->endScene(); context->present(); context->clear(); } } context->destroy(); wnd.destroy(); } catch ( Throwable& e ) { if ( context ) context->destroy(); MoveWindow( wnd.handle(), 0, 0, 0, 0, TRUE ); char msg[1024] = ""; e.getMessage().format().getBytes( msg, sizeof(msg), "ASCII-7" ); MessageBox( 0, msg, "Error", MB_OK ); wnd.destroy(); } return 0; }
//---------------------------------------------------------------------------- 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 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 }
bool ConvexHull3DWindow::LoadData() { std::string filename = "data"; if (mCurrentFile < 10) { filename += "0"; } filename += std::to_string(mCurrentFile) + ".txt"; std::string path = mEnvironment.GetPath(filename); if (path == "") { return false; } std::ifstream input(path); if (!input) { return false; } Vector3<float> center{ 0.0f, 0.0f, 0.0f }; unsigned int numVertices; input >> numVertices; std::vector<Vector3<float>> vertices(numVertices); for (auto& v : vertices) { for (int j = 0; j < 3; ++j) { input >> v[j]; } center += v; } input.close(); center /= static_cast<float>(numVertices); float radius = 0.0f; for (auto const& v : vertices) { Vector3<float> diff = v - center; float length = Length(diff); if (length > radius) { radius = length; } } // The worst-case number of words for UIntegerFP32<N> for 'float' input // to ConvexHull3 is N = 27. For 'double', it is 'N = 197'. ConvexHull3<float, BSNumber<UIntegerFP32<27>>> ch; if (numVertices < 4 || !ch(numVertices, &vertices[0], 0.0f)) { if (mMesh) { mTrackball.Detach(mMesh); mTrackball.Update(); mCameraRig.Unsubscribe(mMesh->worldTransform); mMesh = nullptr; } mMessage = "File = " + std::to_string(mCurrentFile) + " has intrinsic dimension " + std::to_string(ch.GetDimension()); return false; } #if defined(GTE_COLLECT_BSNUMBER_STATISTICS) std::cout << "max size = " << gte::gBSNumberMaxSize << std::endl; #endif std::vector<TriangleKey<true>> const& triangles = ch.GetHullUnordered(); std::mt19937 mte; std::uniform_real_distribution<float> rnd(0.0f, 1.0f); struct Vertex { Vector3<float> position; Vector4<float> color; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, numVertices)); Vertex* vertex = vbuffer->Get<Vertex>(); for (unsigned int i = 0; i < numVertices; ++i) { vertex[i].position = vertices[i]; vertex[i].color[0] = rnd(mte); vertex[i].color[1] = rnd(mte); vertex[i].color[2] = rnd(mte); vertex[i].color[3] = 1.0f; } unsigned int numPrimitives = static_cast<unsigned int>(triangles.size()); std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH, numPrimitives, sizeof(unsigned int))); Memcpy(ibuffer->GetData(), &triangles[0], ibuffer->GetNumBytes()); // Update all information associated with the mesh transforms. if (mMesh) { mTrackball.Detach(mMesh); mTrackball.Update(); mCameraRig.Unsubscribe(mMesh->worldTransform); } mMesh = std::make_shared<Visual>(vbuffer, ibuffer, mEffect); mMesh->localTransform.SetTranslation(-center); mMesh->worldTransform = mMesh->localTransform; mCameraRig.Subscribe(mMesh->worldTransform, mEffect->GetPVWMatrixConstant()); // Move the camera for a centered view of the mesh. Vector4<float> camPosition = Vector4<float>{0.0f, 0.0f, 0.0f, 1.0f} - 2.5f*radius*mCamera->GetDVector(); mCamera->SetPosition(camPosition); // Update the message for display. mMessage = "File = " + std::to_string(mCurrentFile) + " , " + "Vertices = " + std::to_string(numVertices) + " , " + "Triangles =" + std::to_string(numPrimitives); mTrackball.Attach(mMesh); mTrackball.Update(); mCameraRig.UpdatePVWMatrices(); return true; }
//---------------------------------------------------------------------------- void ParticleSystems::CreateScene () { mScene = new0 Node(); 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); int vstride = vformat->GetStride(); const int numParticles = 32; VertexBuffer* vbuffer = new0 VertexBuffer(4*numParticles, vstride); Float4* positionSizes = new1<Float4>(numParticles); for (int i = 0; i < numParticles; ++i) { positionSizes[i][0] = Mathf::SymmetricRandom(); positionSizes[i][1] = Mathf::SymmetricRandom(); positionSizes[i][2] = Mathf::SymmetricRandom(); positionSizes[i][3] = 0.25f*Mathf::UnitRandom(); } Particles* particles = new0 Particles(vformat, vbuffer, sizeof(int), positionSizes, 1.0f); particles->AttachController(new0 BloodCellController()); mScene->AttachChild(particles); // Create an image with transparency. const int xsize = 32, ysize = 32; Texture2D* texture = new0 Texture2D(Texture::TF_A8R8G8B8, xsize, ysize, 1); unsigned char* data = (unsigned char*)texture->GetData(0); float factor = 1.0f/(xsize*xsize + ysize*ysize); for (int y = 0, i = 0; y < ysize; ++y) { for (int x = 0; x < xsize; ++x) { // The image is red. data[i++] = 0; data[i++] = 0; data[i++] = 255; // Semitransparent within a disk, dropping off to zero outside the // disk. int dx = 2*x - xsize; int dy = 2*y - ysize; float value = factor*(dx*dx + dy*dy); if (value < 0.125f) { value = Mathf::Cos(4.0f*Mathf::PI*value); } else { value = 0.0f; } data[i++] = (unsigned char)(255.0f*value); } } Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR); effect->GetAlphaState(0, 0)->BlendEnabled = true; effect->GetDepthState(0, 0)->Enabled = false; particles->SetEffectInstance(effect->CreateInstance(texture)); }
void Vertex::Init(const VertexFormat &vf) { int totalVertexSize = vf.GetStride(); if(totalVertexSize > 0) data = malloc(totalVertexSize); else data = nullptr; }
bool Vertex::HasAttribute(string name, const VertexFormat &vf) const { int offset = vf.GetOffsetOf(name); return (offset != -1); }
bool GeometryShadersWindow::CreateScene() { std::string filename; #if defined(USE_DRAW_DIRECT) filename = mEnvironment.GetPath("RandomSquares.hlsl"); #else filename = mEnvironment.GetPath("RandomSquaresIndirect.hlsl"); #endif std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, filename); if (!program) { return false; } // Create particles used by direct and indirect drawing. struct Vertex { Vector3<float> position; Vector3<float> color; float size; }; // Use a Mersenne twister engine for random numbers. std::mt19937 mte; std::uniform_real_distribution<float> symr(-1.0f, 1.0f); std::uniform_real_distribution<float> unir(0.0f, 1.0f); std::uniform_real_distribution<float> posr(0.01f, 0.1f); int const numParticles = 128; std::vector<Vertex> particles(numParticles); for (auto& particle : particles) { particle.position = { symr(mte), symr(mte), symr(mte) }; particle.color = { unir(mte), unir(mte), unir(mte) }; particle.size = posr(mte); } // Create the constant buffer used by direct and indirect drawing. mMatrices = std::make_shared<ConstantBuffer>( 2 * sizeof(Matrix4x4<float>), true); program->GetGShader()->Set("Matrices", mMatrices); #if defined(USE_DRAW_DIRECT) // Create a mesh for direct drawing. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, numParticles)); Memcpy(vbuffer->GetData(), &particles[0], numParticles*sizeof(Vertex)); #else // Create a mesh for indirect drawing. std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(numParticles)); mParticles = std::make_shared<StructuredBuffer>(numParticles, sizeof(Vertex)); Memcpy(mParticles->GetData(), &particles[0], numParticles*sizeof(Vertex)); gshader->Set("particles", mParticles); #endif std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_POLYPOINT, numParticles)); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); mMesh = std::make_shared<Visual>(vbuffer, ibuffer, effect); return true; }
//---------------------------------------------------------------------------- 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* Castle::LoadMeshPNT2 (const std::string& name) { // Get the vertex format. VertexFormat* vformat = VertexFormat::Create(4, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT3, 2, // normals 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.TCoord<Float3>(2, 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); }
void ShaderGenerator::generateShaders(Material& mat, const RenderState& rs, const VertexFormat& vf, const FogParameters fogParams) { bool hasNormalMap = false; bool hasParallaxMap = false; ctemplate::TemplateDictionary vertexShaderDict("vertexShader"); ctemplate::TemplateDictionary fragmentShaderDict("fragmentShader"); ctemplate::TemplateDictionary* vertexIoDict = vertexShaderDict.AddIncludeDictionary("VERTEX_INPUTS"); vertexIoDict->SetFilename("shader_templates/ft_vertex_inout.tpl"); ctemplate::TemplateDictionary* fragmentOutDict = vertexShaderDict.AddIncludeDictionary("FRAGMENT_INPUTS"); fragmentOutDict->SetFilename("shader_templates/ft_fragment_inout.tpl"); fragmentOutDict->ShowSection("OUT_DIRECTION"); ctemplate::TemplateDictionary* uniformsDict = vertexShaderDict.AddIncludeDictionary("UNIFORMS"); uniformsDict->SetFilename("shader_templates/uniforms.tpl"); // emit the fog uniforms if necessary if (fogParams.m_fogMode != FOG_NONE) { uniformsDict->ShowSection("FOG"); } // use lighting when material uses shading and we have normals bool useLighting = !mat.m_shadeless && vf.getAttributeBySemantic(Vertex_Normal); if (useLighting) { uniformsDict->ShowSection("USE_LIGHTING"); } if (vf.getAttributeBySemantic(Vertex_Normal)) { vertexShaderDict.ShowSection("HAS_NORMALS"); vertexShaderDict.ShowSection("NORMALIZE_NORMALS"); vertexIoDict->ShowSection("HAS_NORMALS"); vertexIoDict->ShowSection("NORMALIZE_NORMALS"); fragmentOutDict->ShowSection("HAS_NORMALS"); uniformsDict->ShowSection("HAS_NORMALS"); } if (vf.getAttributeBySemantic(Vertex_Tangent)) { fragmentOutDict->ShowSection("HAS_TANGENTS"); vertexIoDict->ShowSection("HAS_TANGENTS"); } if (vf.getAttributeBySemantic(Vertex_BiNormal)) { fragmentOutDict->ShowSection("HAS_BINORMALS"); vertexIoDict->ShowSection("HAS_BINORMALS"); } if (vf.getAttributeBySemantic(Vertex_Color)) { vertexShaderDict.ShowSection("HAS_COLORS"); vertexIoDict->ShowSection("HAS_COLORS"); fragmentOutDict->ShowSection("HAS_COLORS"); } // indicates if the tex coords generation functions declarations template has already been // included in the vertex shader template bool texGenDeclIncluded = false; // number of active texture units uint activeTextures = 0; ctemplate::TemplateDictionary* texGenDict = vertexShaderDict.AddIncludeDictionary("TEX_COORDS_GEN"); texGenDict->SetFilename("shader_templates/ft_tex_coords_gen.tpl"); // Loops over all material textures and performs the following: // 1. Declares a respective uniform sampler object which will be named as u_sampler#, // where # is the active texture index. // 2. Emits code for any texture coordinates generation scheme, if not simple UV. ctemplate::TemplateDictionary* parallaxMapDict = 0; for (int i = 0; i < MAX_TEXTURES_STACK; i++) { TexturePtr tex = mat.m_texStack->textures[i]; if (tex) { // for the fragment shader, here we can fill in the dictionary for the texture application section // that takes into account the texture's mapTo, environment color, uvset, etc. ctemplate::TemplateDictionary* texUnitDict = fragmentShaderDict.AddIncludeDictionary( "SINGLE_TEXTURE_STACK_ENTRY"); texUnitDict->SetFilename("shader_templates/ft_tex_stack_application.tpl"); ctemplate::TemplateDictionary* alphaMapDict = 0; ctemplate::TemplateDictionary* tangentNormalMapDict = 0; ctemplate::TemplateDictionary* offsetMappingDict = 0; // depending on the texture's mapTo, we will emit different sections in the template ctemplate::TemplateDictionary* texMapToDict = 0; switch (mat.m_texStack->texOutputs[i].mapTo) { case TexMapTo_Diffuse: texMapToDict = texUnitDict->AddSectionDictionary("TEX_MAP_TO_DIFFUSE"); break; case TexMapTo_CSpecular: texMapToDict = texUnitDict->AddSectionDictionary("TEX_MAP_TO_SPECULAR"); break; case TexMapTo_Shininess: texMapToDict = texUnitDict->AddSectionDictionary("TEX_MAP_TO_SHININESS"); break; case TexMapTo_Alpha: alphaMapDict = fragmentShaderDict.AddSectionDictionary("ALPHA_MAP_APPLICATION"); break; case TexMapTo_Normal: tangentNormalMapDict = fragmentShaderDict.AddIncludeDictionary("TANGENT_SPACE_NORMAL_MAP"); tangentNormalMapDict->SetFilename(TANGENT_SPACE_NMAP_TPL); parallaxMapDict = tangentNormalMapDict; hasNormalMap = true; break; case TexMapTo_Parallax: /* IMPORTANT: Parallax maps must come after the normal maps */ if (parallaxMapDict) { offsetMappingDict = parallaxMapDict->AddSectionDictionary("PARALLAX_OFFSET_MAPPING"); } hasParallaxMap = true; break; default: SAFE_THROW(GLException(E_NOTIMPL, "Unimplemented texture output mapping mode")) } texUnitDict->SetIntValue(TEX_INDEX, activeTextures); texUnitDict->SetIntValue(UV_SET_INDEX, mat.m_texStack->texInputs[i].uvSet); if (alphaMapDict) { alphaMapDict->SetIntValue(TEX_INDEX, activeTextures); alphaMapDict->SetIntValue(UV_SET_INDEX, mat.m_texStack->texInputs[i].uvSet); } if (tangentNormalMapDict) { tangentNormalMapDict->SetIntValue(TEX_INDEX, activeTextures); tangentNormalMapDict->SetIntValue(UV_SET_INDEX, mat.m_texStack->texInputs[i].uvSet); } if (offsetMappingDict) { offsetMappingDict->SetIntValue(TEX_INDEX, activeTextures); offsetMappingDict->SetIntValue(UV_SET_INDEX, mat.m_texStack->texInputs[i].uvSet); } switch (mat.m_texStack->texOutputs[i].blendOp) { case TexBlendOp_Mix: texUnitDict->ShowSection("TEX_BLENDOP_BLEND"); break; case TexBlendOp_Add: texUnitDict->ShowSection("TEX_BLENDOP_ADD"); break; case TexBlendOp_Multiply: texUnitDict->ShowSection("TEX_BLENDOP_MULTIPLY"); break; case TexBlendOp_Decal: texUnitDict->ShowSection("TEX_BLENDOP_DECAL"); break; default: SAFE_THROW(GLException(E_NOTIMPL, "Unimplemented texture blending mode")) } // this is the dictionary for a single uniform sampler declaration ctemplate::TemplateDictionary* samplerDict = uniformsDict->AddSectionDictionary("SINGLE_SAMPLER_DECL"); samplerDict->SetIntValue(TEX_INDEX, activeTextures); const char* samplerToken; const char* coordsToken; switch (tex->getTextureTarget()) { case GL_TEXTURE_1D: samplerToken = "sampler1D"; coordsToken = S_COORD; break; case GL_TEXTURE_CUBE_MAP: samplerToken = "samplerCube"; coordsToken = STP_COORDS; break; case GL_TEXTURE_2D: default: samplerToken = "sampler2D"; coordsToken = ST_COORDS; break; } samplerDict->SetValue("SAMPLER_SPEC", samplerToken); texUnitDict->SetValue(TEX_COORDS, coordsToken); if (alphaMapDict) { alphaMapDict->SetValue(TEX_COORDS, coordsToken); } if (tangentNormalMapDict) { tangentNormalMapDict->SetValue(TEX_COORDS, coordsToken); } if (offsetMappingDict) { offsetMappingDict->SetValue(TEX_COORDS, coordsToken); } // When a special texture coordinate generation system is used, we have to include // the TEX_COORDS_GEN_DECL template which contains function declarations for the various // tex gen systems. Then for each texture unit that uses custom tex gen, we need to // instantiate a SINGLE_TEX_COORDS_GEN section with an appropriately initialized dictionary ctemplate::TemplateDictionary* singleTexGen = texGenDict->AddSectionDictionary("SINGLE_TEXCOORDS_ASSIGN"); singleTexGen->SetIntValue(UV_SET_INDEX, mat.m_texStack->texInputs[i].uvSet); singleTexGen->SetValue(TEX_COORDS, coordsToken); TexMapInput inputMapping = mat.m_texStack->texInputs[i].mapping; if (inputMapping != TexMapInput_UV) { if (!texGenDeclIncluded) { ctemplate::TemplateDictionary* texGenDecl = vertexShaderDict.AddIncludeDictionary( "TEX_COORDS_GEN_DECL"); texGenDecl->SetFilename("shader_templates/ft_tex_coords_gen_decl.tpl"); texGenDeclIncluded = true; } switch (inputMapping) { case TexMapInput_Normal: singleTexGen->ShowSection("NORMAL_TEXGEN"); break; case TexMapInput_Refl: singleTexGen->ShowSection("REFLECTION_TEXGEN"); break; case TexMapInput_Spherical: singleTexGen->ShowSection("SPHERE_TEXGEN"); break; case TexMapInput_EyeSpace: singleTexGen->ShowSection("EYE_TEXGEN"); break; case TexMapInput_ObjectSpace: singleTexGen->ShowSection("OBJECT_TEXGEN"); break; case TexMapInput_Cube: singleTexGen->ShowSection("CUBE_TEXGEN"); break; default: SAFE_THROW(GLException(E_NOTIMPL, "Unimplemented texture mapping mode")) } } else { singleTexGen->ShowSection("UV_MAPPING"); } ++activeTextures; } }
void MassSprings3DWindow::CreateBoxFaces() { // The vertex buffer will use the mass-spring position array for its // CPU data. int const numVertices = mDimension[0] * mDimension[1] * mDimension[2]; #if defined(DO_CPU_MASS_SPRING) VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); mVBuffer = std::make_shared<VertexBuffer>(vformat, numVertices, false); mVBuffer->SetUsage(Resource::DYNAMIC_UPDATE); #else mVBuffer = std::make_shared<VertexBuffer>(numVertices); #endif size_t const idxsize = sizeof(unsigned int); std::shared_ptr<IndexBuffer> ibuffer; int numTriangles, t, x, y, z, v0, v1, v2, v3; // box face z = 1 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (y = 1, t = 0; y < mDimension[1] - 2; ++y) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, y, 1); v1 = GetIndex(x + 1, y, 1); v2 = GetIndex(x, y + 1, 1); v3 = GetIndex(x + 1, y + 1, 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[0] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face z = dim2 - 2 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (y = 1, t = 0; y < mDimension[1] - 2; ++y) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, y, mDimension[2] - 2); v1 = GetIndex(x + 1, y, mDimension[2] - 2); v2 = GetIndex(x, y + 1, mDimension[2] - 2); v3 = GetIndex(x + 1, y + 1, mDimension[2] - 2); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[1] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face y = 1 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, 1, z); v1 = GetIndex(x + 1, 1, z); v2 = GetIndex(x, 1, z + 1); v3 = GetIndex(x + 1, 1, z + 1); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[2] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face y = dim1 - 2 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, mDimension[1] - 2, z); v1 = GetIndex(x + 1, mDimension[1] - 2, z); v2 = GetIndex(x, mDimension[1] - 2, z + 1); v3 = GetIndex(x + 1, mDimension[1] - 2, z + 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[3] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face x = 1 numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (y = 1; y < mDimension[1] - 2; ++y) { v0 = GetIndex(1, y, z); v1 = GetIndex(1, y + 1, z); v2 = GetIndex(1, y, z + 1); v3 = GetIndex(1, y + 1, z + 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[4] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face x = dim0 - 2 numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (y = 1; y < mDimension[1] - 2; ++y) { v0 = GetIndex(mDimension[0] - 2, y, z); v1 = GetIndex(mDimension[0] - 2, y + 1, z); v2 = GetIndex(mDimension[0] - 2, y, z + 1); v3 = GetIndex(mDimension[0] - 2, y + 1, z + 1); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[5] = std::make_shared<Visual>(mVBuffer, ibuffer); Vector4<float> const color[6] = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }; #if defined(DO_CPU_MASS_SPRING) for (int i = 0; i < 6; ++i) { mEffect[i] = std::make_shared<ConstantColorEffect>(color[i]); mBoxFace[i]->SetEffect(mEffect[i]); } #else std::string path = mEnvironment.GetPath("DrawUsingVertexID.hlsl"); std::shared_ptr<ConstantBuffer> pvwMatrixBuffer; std::shared_ptr<ConstantBuffer> colorBuffer; std::shared_ptr<VisualProgram> program; std::shared_ptr<VertexShader> vshader; std::shared_ptr<PixelShader> pshader; for (int i = 0; i < 6; ++i) { pvwMatrixBuffer = std::make_shared<ConstantBuffer>( sizeof(Matrix4x4<float>), true); colorBuffer = std::make_shared<ConstantBuffer>( sizeof(Vector4<float>), false); *colorBuffer->Get<Vector4<float>>() = color[i]; // TODO: Need to terminate application if 'program' is null. program = mProgramFactory.CreateFromFiles(path, path, ""); vshader = program->GetVShader(); vshader->Set("PVWMatrix", pvwMatrixBuffer); vshader->Set("ConstantColor", colorBuffer); vshader->Set("position", mMassSprings->GetPosition()); mEffect[i] = std::make_shared<VisualEffect>(program); mBoxFace[i]->SetEffect(mEffect[i]); } #endif }
//---------------------------------------------------------------------------- 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(); }
//---------------------------------------------------------------------------- void FramesMesh::_Cal(const std::string &texPackFilename) { const TexPack &texPack = PX2_RM.GetTexPack(texPackFilename); if (!texPack.IsValid()) return; std::string outPath; std::string outBaseFilename; StringHelp::SplitFilename(texPackFilename, outPath, outBaseFilename); std::string outBaseName; std::string outExt; StringHelp::SplitBaseFilename(outBaseFilename, outBaseName, outExt); VertexFormat *vf = PX2_GR.GetVertexFormat(GraphicsRoot::VFT_PCT1); SetVertexFormat(vf); mNumAllFrames = (int)texPack.Elements.size(); mNumFramesPerDir = mNumAllFrames / mNumDir; if (0 == mNumFramesPerDir) { //assertion(false, "no frames"); //return; } VBIBObj &obj = VBIBManager::GetSingleton().GetVBID(texPackFilename); if (obj.IsValued) { SetVertexBuffer(obj.mVB); SetIndexBuffer(obj.mIB); } else { int numVertex = mNumAllFrames * 4; int numIndex = mNumAllFrames * 6; int frameIndex = 0; VertexBuffer *vb = new0 VertexBuffer(numVertex, vf->GetStride()); VertexBufferAccessor vba(vf, vb); for (int i = 0; i < mNumDir; i++) { for (int j = 0; j < mNumFramesPerDir; j++) { std::string eleName = outBaseName + "_" + StringHelp::IntToString(i * 45) + "_" + StringHelp::IntToString(j + 1); const TexPackElement &ele = PX2_RM.GetTexPackElement(texPackFilename, eleName); float xPlusPer = 0.0f; float widthPer = 0.0f; float zPlusPer = 0.0f; float heightPer = 0.0f; if (0 != ele.OW) { xPlusPer = (float)ele.OX / (float)ele.OW; widthPer = (float)ele.W / (float)ele.OW; } if (0 != ele.OH) { zPlusPer = 1.0f - (float)(ele.OY + ele.H) / (float)ele.OH; heightPer = (float)ele.H / (float)ele.OH; } float width = mSize; float height = mSize; float xPos = 0.0f - width * 0.5f; float zPos = 0.0f - height * 0.5f; xPos += xPlusPer * width; zPos += zPlusPer * height; width *= widthPer; height *= heightPer; Float3 p0 = Float3(xPos, zPos, 0.0f); Float3 p1 = Float3(xPos + width, zPos, 0.0f); Float3 p2 = Float3(xPos, zPos + height, 0.0f); Float3 p3 = Float3(xPos + width, zPos + height, 0.0f); float uBegin = (float)ele.X / (float)ele.TexWidth; float uEnd = (float)(ele.X + ele.W) / (float)ele.TexWidth; float vBegin = (float)(ele.TexHeight - ele.Y - ele.H) / (float)ele.TexHeight; float vEnd = (float)(ele.TexHeight - ele.Y) / (float)ele.TexHeight; vba.Position<Float3>(frameIndex * 4 + 0) = p0; vba.Position<Float3>(frameIndex * 4 + 1) = p1; vba.Position<Float3>(frameIndex * 4 + 2) = p2; vba.Position<Float3>(frameIndex * 4 + 3) = p3; vba.TCoord<Float2>(0, frameIndex * 4 + 0) = Float2(uBegin, vBegin); vba.TCoord<Float2>(0, frameIndex * 4 + 1) = Float2(uEnd, vBegin); vba.TCoord<Float2>(0, frameIndex * 4 + 2) = Float2(uBegin, vEnd); vba.TCoord<Float2>(0, frameIndex * 4 + 3) = Float2(uEnd, vEnd); frameIndex++; } } IndexBuffer *ib = new0 IndexBuffer(numIndex, 2); for (int i = 0; i < mNumAllFrames; i++) { unsigned short *indices = (unsigned short*)ib->GetData(); indices[i * 6 + 0] = (uint16_t)(i * 4 + 0); indices[i * 6 + 1] = (uint16_t)(i * 4 + 1); indices[i * 6 + 2] = (uint16_t)(i * 4 + 2); indices[i * 6 + 3] = (uint16_t)(i * 4 + 1); indices[i * 6 + 4] = (uint16_t)(i * 4 + 3); indices[i * 6 + 5] = (uint16_t)(i * 4 + 2); } SetVertexBuffer(vb); SetIndexBuffer(ib); VBIBManager::GetSingleton().AddVBIB(texPackFilename, vb, ib); } Texture2D *tex = (Texture2D*)PX2_RM.BlockLoad(texPack.ImageFullPath); MaterialInstance *mi = new0 MaterialInstance( "Data/engine_mtls/tex2d/tex2d.px2obj", "tex2d", false); mi->SetPixelTexture(0, "SampleBase", tex); SetMaterialInstance(mi); mi->GetMaterial()->GetCullProperty(0, 0)->Enabled = false; mIsNeedReCal = false; }
//---------------------------------------------------------------------------- CurveCtrl::CurveCtrl (Curve *curve, CurveCtrlType type, int index) : mIndex(index), mSelected(false), mCurve(curve), mCtrlType(type), mXScale(1.0f), mZScale(1.0f), mDragLength(1.0f), mInVal(-1.0f), mSelectMode(SM_MAX_MODE) { mCtrlNode = new0 Node(); float dragSize = 0.1f; VertexFormat *vFormat = PX2_GR.GetVertexFormat(GraphicsRoot::VFT_PC); StandardMesh sm(vFormat); Float3 curveColor = mCurve->GetCurveColor(); VertexColor4MaterialPtr mtl = new0 VertexColor4Material(); MaterialInstancePtr mtlInst = mtl->CreateInstance(); sm.SetVertexColor(Float4(curveColor[0], curveColor[1], curveColor[2], 1.0f)); mDragBox = sm.Box(dragSize, dragSize, dragSize); mDragBox->SetMaterialInstance(mtlInst); sm.SetVertexColor(Float4::WHITE); mDragBoxArrive = sm.Box(dragSize, dragSize, dragSize); mDragBoxArrive->SetMaterialInstance(mtlInst); mDragBoxLeave = sm.Box(dragSize, dragSize, dragSize); mDragBoxLeave->SetMaterialInstance(mtlInst); VertexBuffer *vBuffer = new0 VertexBuffer(2, vFormat->GetStride(), Buffer::BU_DYNAMIC); mDragLineArrive = new0 Polysegment(vFormat, vBuffer, true); mDragLineArrive->SetMaterialInstance(mtlInst); VertexBuffer *vBuffer1 = new0 VertexBuffer(2, vFormat->GetStride(), Buffer::BU_DYNAMIC); mDragLineLeave = new0 Polysegment(vFormat, vBuffer1, true); mDragLineLeave->SetMaterialInstance(mtlInst); sm.SetVertexColor(Float4::YELLOW); mCtrlNode->AttachChild(mDragBox); mCtrlNode->AttachChild(mDragBoxArrive); mCtrlNode->AttachChild(mDragBoxLeave); mCtrlNode->AttachChild(mDragLineArrive); mCtrlNode->AttachChild(mDragLineLeave); mDragBoxArrive->Culling = Movable::CULL_ALWAYS; mDragBoxLeave->Culling = Movable::CULL_ALWAYS; mDragLineArrive->Culling = Movable::CULL_ALWAYS; mDragLineLeave->Culling = Movable::CULL_ALWAYS; mCtrlNode->Update(); }
bool MultipleRenderTargetsWindow::CreateScene() { // Create a visual effect that populates the draw target. std::string filename = mEnvironment.GetPath("MultipleRenderTargets.hlsl"); std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, ""); if (!program) { return false; } std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); program->GetVShader()->Set("PVWMatrix", cbuffer); std::shared_ptr<PixelShader> pshader = program->GetPShader(); std::shared_ptr<ConstantBuffer> farNearRatio(new ConstantBuffer( sizeof(float), false)); pshader->Set("FarNearRatio", farNearRatio); farNearRatio->SetMember("farNearRatio", mCamera->GetDMax() / mCamera->GetDMin()); std::string path = mEnvironment.GetPath("StoneWall.png"); std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, true)); baseTexture->AutogenerateMipmaps(); pshader->Set("baseTexture", baseTexture); std::shared_ptr<SamplerState> baseSampler(new SamplerState()); baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_L; baseSampler->mode[0] = SamplerState::CLAMP; baseSampler->mode[1] = SamplerState::CLAMP; pshader->Set("baseSampler", baseSampler); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); // Create a vertex buffer for a two-triangle square. The PNG is stored // in left-handed coordinates. The texture coordinates are chosen to // reflect the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = { -1.0f, -1.0f, 0.0f }; vertex[0].tcoord = { 0.0f, 1.0f }; vertex[1].position = { 1.0f, -1.0f, 0.0f }; vertex[1].tcoord = { 1.0f, 1.0f }; vertex[2].position = { -1.0f, 1.0f, 0.0f }; vertex[2].tcoord = { 0.0f, 0.0f }; vertex[3].position = { 1.0f, 1.0f, 0.0f }; vertex[3].tcoord = { 1.0f, 0.0f }; // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create the geometric object for drawing and enable automatic updates // of pvw-matrices and w-matrices. mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect); mTrackball.Attach(mSquare); mTrackball.Update(); mCameraRig.Subscribe(mSquare->worldTransform, cbuffer); return true; }
//---------------------------------------------------------------------------- void ClodMeshes::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // 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); TriMeshPtr mesh = StaticCast<TriMesh>(inStream.GetObjectAt(0)); VertexBufferAccessor vba0(mesh); // Remove the normals and add texture coordinates. 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(vba0.GetNumVertices(), vstride); VertexBufferAccessor vba1(vformat, vbuffer); float xmin = Mathf::MAX_REAL, xmax = -Mathf::MAX_REAL; float ymin = Mathf::MAX_REAL, ymax = -Mathf::MAX_REAL; int i; for (i = 0; i < vba0.GetNumVertices(); ++i) { Float3 position = vba0.Position<Float3>(i); vba1.Position<Float3>(i) = position; float x = position[0]; float y = position[2]; vba1.TCoord<Float2>(0, i) = Float2(x, y); if (x < xmin) { xmin = x; } if (x > xmax) { xmax = x; } if (y < ymin) { ymin = y; } if (y > ymax) { ymax = y; } } float xmult = 1.0f/(xmax - xmin); float ymult = 1.0f/(ymax - ymin); for (i = 0; i < vba1.GetNumVertices(); ++i) { Float2 tcoord = vba1.TCoord<Float2>(0, i); vba1.TCoord<Float2>(0,i) = Float2( (tcoord[0] - xmin)*xmult, (tcoord[1] - ymin)*ymult); } mesh->SetVertexFormat(vformat); mesh->SetVertexBuffer(vbuffer); // Create a texture for the face. Use the generated texture coordinates. Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR); path = Environment::GetPathR("Magician.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); #ifdef USE_CLOD_MESH // Create the collapse records to be shared by two CLOD meshes. int numRecords = 0; CollapseRecord* records = 0; CreateClodMesh ccm(mesh, numRecords, records); CollapseRecordArray* recordArray = new0 CollapseRecordArray(numRecords, records); mClod[0] = new0 ClodMesh(mesh, recordArray); mClod[0]->LocalTransform = mesh->LocalTransform; mClod[0]->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() - 150.0f*AVector::UNIT_X); mClod[0]->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(mClod[0]); mClod[1] = new0 ClodMesh(mesh, recordArray); mClod[1]->LocalTransform = mesh->LocalTransform; mClod[1]->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() + 150.0f*AVector::UNIT_X - 100.0f*AVector::UNIT_Y); mClod[1]->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(mClod[1]); mActive = mClod[0]; #else IndexBuffer* ibuffer = mesh->GetIndexBuffer(); TriMesh* face = new0 TriMesh(vformat, vbuffer,ibuffer); face->LocalTransform = mesh->LocalTransform; face->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() - 150.0f*AVector::UNIT_X); face->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(face); face = new0 TriMesh(vformat, vbuffer, ibuffer); face->LocalTransform = mesh->LocalTransform; face->LocalTransform.SetTranslate(mesh->LocalTransform.GetTranslate() + 150.0f*AVector::UNIT_X); face->SetEffectInstance(effect->CreateInstance(texture)); mTrnNode->AttachChild(face); #endif }
//---------------------------------------------------------------------------- TriMesh *UniMaterialMesh::ToTriMesh() { if (mVertexMapQuantity == 0) return 0; // VertexBuffer VertexFormat *vFormat = new0 VertexFormat(); vFormat->Add(VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0); if (mNormalMap) { vFormat->Add(VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0); } if (mExportTargentBinormal) { vFormat->Add(VertexFormat::AU_TANGENT, VertexFormat::AT_FLOAT3, 0); vFormat->Add(VertexFormat::AU_BINORMAL, VertexFormat::AT_FLOAT3, 0); } if (mExportColor) { vFormat->Add(VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); } if (mTextureCoordMap) { if (1 == mNumTexcoordToExport) { vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); } else if (2 == mNumTexcoordToExport) { vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 1); } } if (mExportSkin) { vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT4, 1); vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT4, 2); } vFormat->Create(); PX2::VertexBuffer *vBuffer = new0 PX2::VertexBuffer(mVertexMapQuantity, vFormat->GetStride()); VertexBufferAccessor vBA(vFormat, vBuffer); for (int i=0; i<mVertexMapQuantity; i++) { vBA.Position<Float3>(i) = mVertexMap[i]; if (mNormalMap) { vBA.Normal<Float3>(i) = mNormalMap[i]; } if (mColorMap) { vBA.Color<Float4>(0, i) = Float4(mColorMap[i][0], mColorMap[i][1], mColorMap[i][2], mColorMap[i][3]); } else { if (mExportColor) vBA.Color<Float4>(0, i) = Float4::WHITE; } if (mAlphaMap) { vBA.Color<Float4>(0, i) = Float4(mColorMap[i][0], mColorMap[i][1], mColorMap[i][2], mAlphaMap[i]); } if (mTextureCoordMap) { if (mNumTexcoordToExport == 1) { vBA.TCoord<Float2>(0, i) = Float2(mTextureCoordMap[i][0], 1.0f-mTextureCoordMap[i][1]); } else if (mNumTexcoordToExport == 2) { Float2 texCoord0 = Float2(mTextureCoordMap[i][0], 1.0f-mTextureCoordMap[i][1]); vBA.TCoord<Float2>(0, i) = texCoord0; if (mTextureCoordMap1) { vBA.TCoord<Float2>(1, i) = Float2(mTextureCoordMap1[i][0], 1.0f-mTextureCoordMap1[i][1]); } else { vBA.TCoord<Float2>(1, i) = texCoord0; } } } } // IndexBuffer IndexBuffer *iBuffer = new0 IndexBuffer(3*mFQuantity, 2); unsigned short *iData = (unsigned short*)iBuffer->GetData(); for (int i=0; i<(int)3*mFQuantity; i++) { iData[i] = (unsigned short)mVFace[i]; } // 创建Mesh TriMesh *triMesh = new0 TriMesh(vFormat, vBuffer, iBuffer); triMesh->UpdateModelSpace(Renderable::GU_MODEL_BOUND_ONLY); if (mExportTargentBinormal) { triMesh->UpdateModelSpace(Renderable::GU_USE_GEOMETRY); } MaterialInstance *mi = 0; mi = mMaterialInstance; triMesh->SetMaterialInstance(mi); triMesh->SetShine(mShine); return triMesh; }
//---------------------------------------------------------------------------- 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); }
//---------------------------------------------------------------------------- RigidTetra::RigidTetra (float size, float mass, const Vector3f& position, const Vector3f& linearMomentum, const Vector3f& angularMomentum) : Moved(false) { Moved = false; 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); vba.Color<Float3>(0, 0) = Float3(1.0f, 1.0f, 1.0f); vba.Color<Float3>(0, 1) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(0.0f, 0.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; mMesh = new0 TriMesh(vformat, vbuffer, ibuffer); mMesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); // Compute the inertia tensor. Matrix3f inertia; int j; for (int i = 0; i < 3; ++i) { inertia[i][i] = 0.0f; for (j = 0; j < 3; ++j) { if (i != j) { inertia[i][j] = 0.0f; for (int k = 0; k < 4; ++k) { Vector3f pos = vba.Position<Vector3f>(k); inertia[i][i] += 0.25f*mass*pos[j]*pos[j]; inertia[i][j] -= 0.25f*mass*pos[i]*pos[j]; } } } } // Compute the radius of a sphere bounding the tetrahedron. Vector3f centroid = (size/6.0f)*Vector3f(1.0f, 1.0f, 1.0f); mRadius = 0.0f; for (j = 0; j < 4; ++j) { vba.Position<Vector3f>(j) -= centroid; float temp = (vba.Position<Vector3f>(j) - centroid).Length(); if (temp > mRadius) { mRadius = temp; } } SetMass(mass); SetBodyInertia(inertia); SetPosition(position); SetQOrientation(Quaternionf::IDENTITY); SetLinearMomentum(linearMomentum); SetAngularMomentum(angularMomentum); }
//---------------------------------------------------------------------------- void Font::RenderText (TriMesh *mesh, float depth) { VertexFormat *vFormat = mesh->GetVertexFormat(); VertexBuffer *vBuffer = mesh->GetVertexBuffer(); IndexBuffer *iBuffer = mesh->GetIndexBuffer(); if (!vBuffer) { vBuffer = new0 VertexBuffer(4*mShowNum, vFormat->GetStride(), Buffer::BU_DYNAMIC); iBuffer = new0 IndexBuffer(6*mShowNum, 2); unsigned short *indices = (unsigned short*)iBuffer->GetData(); for (int i=0; i<mShowNum; i++) { unsigned short v0 = i*4 + 0; unsigned short v1 = i*4 + 1; unsigned short v2 = i*4 + 2; unsigned short v3 = i*4 + 3; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v0; *indices++ = v2; *indices++ = v3; } mesh->SetVertexBuffer(vBuffer); mesh->SetIndexBuffer(iBuffer); } else { int vertexNum = vBuffer->GetNumElements(); if (vertexNum < 4*mShowNum) { vBuffer = new0 VertexBuffer(4*mShowNum, vFormat->GetStride(), Buffer::BU_DYNAMIC); iBuffer = new0 IndexBuffer(6*mShowNum, 2); unsigned short *indices = (unsigned short*)iBuffer->GetData(); for (int i=0; i<mShowNum; i++) { unsigned short v0 = i*4 + 0; unsigned short v1 = i*4 + 1; unsigned short v2 = i*4 + 2; unsigned short v3 = i*4 + 3; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v0; *indices++ = v2; *indices++ = v3; } mesh->SetVertexBuffer(vBuffer); mesh->SetIndexBuffer(iBuffer); } } VertexBufferAccessor vba(vFormat, vBuffer); for (int i=0; i<mShowNum; i++) { FontDrawRect &rect = mDrawRects[i]; vba.Position<Float3>(4*i) = Float3(rect.Rect.Left, depth, rect.Rect.Bottom); vba.Color<Float4>(0, 4*i) = rect.Color; vba.TCoord<Float2>(0, 4*i) = Float2(rect.RectUV.Left, rect.RectUV.Bottom); vba.Position<Float3>(4*i+1) = Float3(rect.Rect.Right, depth, rect.Rect.Bottom); vba.Color<Float4>(0, 4*i+1) = rect.Color; vba.TCoord<Float2>(0, 4*i+1)= Float2(rect.RectUV.Right, rect.RectUV.Bottom); vba.Position<Float3>(4*i+2) = Float3(rect.Rect.Right, depth, rect.Rect.Top); vba.Color<Float4>(0, 4*i+2) = rect.Color; vba.TCoord<Float2>(0, 4*i+2)= Float2(rect.RectUV.Right, rect.RectUV.Top); vba.Position<Float3>(4*i+3) = Float3(rect.Rect.Left, depth, rect.Rect.Top); vba.Color<Float4>(0, 4*i+3) = rect.Color; vba.TCoord<Float2>(0, 4*i+3)= Float2(rect.RectUV.Left, rect.RectUV.Top); } vBuffer->SetNumElements(4*mShowNum); iBuffer->SetNumElements(6*mShowNum); mesh->UpdateModelSpace(Renderable::GU_MODEL_BOUND_ONLY); Renderer::UpdateAll(vBuffer); Renderer::UpdateAll(iBuffer); mShowNum = 0; }
//---------------------------------------------------------------------------- ImageProcessing::ImageProcessing (int numCols, int numRows, int numTargets) : mNumCols(numCols), mNumRows(numRows), mNumTargets(numTargets) { assertion(mNumCols > 1 && mNumRows > 0, "Invalid bound.\n"); assertion(mNumTargets > 0, "Invalid number of targets.\n"); mColSpacing = 1.0f/(float)(mNumCols - 1); mRowSpacing = 1.0f/(float)(mNumRows - 1); // 将相机从[-1,-1]^2 x [0,1]匹配到[0,1]^3 mCamera = new0 Camera(false); mCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // 创建顶点格式 VertexFormat* vformat = new0 VertexFormat(2); vformat->SetAttribute(0, 0, 0, VertexFormat::AT_FLOAT3, VertexFormat::AU_POSITION, 0); vformat->SetAttribute(1, 0, 3*sizeof(float), VertexFormat::AT_FLOAT2, VertexFormat::AU_TEXCOORD, 0); vformat->SetStride(5*sizeof(float)); // 创建顶点缓冲区 int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); float xmin, xmax, ymin, ymax; Float2 tc0, tc1, tc2, tc3; if (VertexShader::GetProfile() == VertexShader::VP_ARBVP1) { xmin = 0.0f; xmax = 1.0f; ymin = 0.0f; ymax = 1.0f; 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 { xmin = -0.5f*mColSpacing; xmax = 1.0f - 0.5f*mColSpacing; ymin = +0.5f*mRowSpacing; ymax = 1.0f + 0.5f*mRowSpacing; tc0 = Float2(0.0f, 1.0f); tc1 = Float2(1.0f, 1.0f); tc2 = Float2(1.0f, 0.0f); tc3 = Float2(0.0f, 0.0f); } vba.Position<Float3>(0) = Float3(xmin, ymin, 0.0f); vba.Position<Float3>(1) = Float3(xmax, ymin, 0.0f); vba.Position<Float3>(2) = Float3(xmax, ymax, 0.0f); vba.Position<Float3>(3) = Float3(xmin, ymax, 0.0f); vba.TCoord<Float2>(0, 0) = tc0; vba.TCoord<Float2>(0, 1) = tc1; vba.TCoord<Float2>(0, 2) = tc2; vba.TCoord<Float2>(0, 3) = tc3; // 创建顶点索引缓冲区 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; // 创建网格 mRectangle = new0 TriMesh(vformat, vbuffer, ibuffer); // 创建顶点着色器 CreateVertexShader(); // 创建RT mTargets = new1<RenderTargetPtr>(mNumTargets); for (int i = 0; i < mNumTargets; ++i) { mTargets[i] = new0 RenderTarget(1, Texture::TF_A32B32G32R32F, mNumCols, mNumRows, false, false, false); } }
//---------------------------------------------------------------------------- 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 PlanarShadows::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 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)); }
//---------------------------------------------------------------------------- void WrigglingSnake::CreateSnakeHead () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Create the snake head as a paraboloid that is attached to the last // ring of vertices on the snake body. These vertices are generated // for t = 1. int numSliceSamples = mSnakeBody->GetNumSliceSamples(); mSlice = new1<Vector3f>(numSliceSamples + 1); // Number of rays (determined by slice samples of tube surface). int numRays = numSliceSamples - 1; // Number of shells less one (your choice, specified in application // constructor). int numShellsM1 = mNumShells - 1; // Generate vertices (positions to be filled in by UpdateSnakeHead). int numVertices = 1 + numRays*numShellsM1; VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); VertexBufferAccessor vba(vformat, vbuffer); Float3 darkGreen(0.0f, 0.25f, 0.0f); for (int i = 0; i < numVertices; ++i) { vba.Color<Float3>(0, i) = darkGreen; } // Generate triangles. int numTriangles = numRays*(2*numShellsM1 - 1); int numIndices = 3*numTriangles; IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); for (int r0 = numRays - 1, r1 = 0, t = 0; r1 < numRays; r0 = r1++) { *indices++ = 0; *indices++ = 1 + numShellsM1*r0; *indices++ = 1 + numShellsM1*r1; ++t; for (int s = 1; s < numShellsM1; ++s) { int i00 = s + numShellsM1*r0; int i01 = s + numShellsM1*r1; int i10 = i00 + 1; int i11 = i01 + 1; *indices++ = i00; *indices++ = i10; *indices++ = i11; *indices++ = i00; *indices++ = i11; *indices++ = i01; t += 2; } } mSnakeHead = new0 TriMesh(vformat, vbuffer, ibuffer); mSnakeHead->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance()); mSnakeRoot->AttachChild(mSnakeHead); UpdateSnake(); }