protected void updateHardwareBuffers() { if (mChainElementList.Count < 2) { return; } // Here. we need to compute the position of the camera in the coordinate system of the billboard chain. Vector3 eyePos = this.ParentNode._getDerivedOrientation().Inverse() * (mCamera.GetDerivedPosition() - this.ParentNode._getDerivedPosition()); IntPtr ptrBuff; uint buffIdx = 0; int chainSize = mChainElementList.Count; mVD.vertexCount = (uint)chainSize * 2; // Setup the vertex coordinates HardwareVertexBufferSharedPtr pPosBuffer = mVD.vertexBufferBinding.getBuffer(POSITION_BINDING); ptrBuff = pPosBuffer.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); // Compute the position of the vertices in the chain for (int i = 0; i < chainSize; i++) { myBillBoardChainElement bbe = (myBillBoardChainElement)mChainElementList[i]; Vector3 chainTangent; if (i == 0) { chainTangent = bbe.position - ((myBillBoardChainElement)mChainElementList[0]).position; } else if (i == chainSize - 1) { chainTangent = ((myBillBoardChainElement)mChainElementList[chainSize - 1]).position - ((myBillBoardChainElement)mChainElementList[chainSize - 2]).position; } else { chainTangent = ((myBillBoardChainElement)mChainElementList[i + 1]).position - ((myBillBoardChainElement)mChainElementList[i - 1]).position; } Vector3 p1 = bbe.position; Vector3 vP1ToEye = eyePos - p1; Vector3 vPerpendicular = chainTangent.Cross(vP1ToEye); vPerpendicular.Normalize(); vPerpendicular *= bbe.width; Vector3 pos0 = p1 - vPerpendicular; Vector3 pos1 = p1 + vPerpendicular; // Update the buffer with the 2 vertex positions MeshBuilderHelper.SetVertexFloat(ptrBuff, mVBVertexSize, buffIdx++, mVBPostOff, pos0.x, pos0.y, pos0.z); MeshBuilderHelper.SetVertexFloat(ptrBuff, mVBVertexSize, buffIdx++, mVBPostOff, pos1.x, pos1.y, pos1.z); } pPosBuffer.Get().Unlock(); // Setup the diffuse color of the vertex HardwareVertexBufferSharedPtr pVertexColorBuffer = mVD.vertexBufferBinding.getBuffer(DIFFUSE_COLOR_BINDING); ptrBuff = pVertexColorBuffer.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); buffIdx = 0; for (int i = 0; i < chainSize; i++) { Color col = ((myBillBoardChainElement)mChainElementList[i]).colour; MeshBuilderHelper.SetVertexFloat(ptrBuff, mVCBVertexSize, buffIdx++, mVCBrgbaOff, ((float)col.R / 255.0f), ((float)col.G / 255.0f), ((float)col.B / 255.0f), ((float)col.A / 255.0f)); MeshBuilderHelper.SetVertexFloat(ptrBuff, mVCBVertexSize, buffIdx++, mVCBrgbaOff, ((float)col.R / 255.0f), ((float)col.G / 255.0f), ((float)col.B / 255.0f), ((float)col.A / 255.0f)); } pVertexColorBuffer.Get().Unlock(); // Setup the texture coordinates HardwareVertexBufferSharedPtr pTexCoordBuffer = mVD.vertexBufferBinding.getBuffer(TEXCOORD_BINDING); ptrBuff = pTexCoordBuffer.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); buffIdx = 0; for (int i = 0; i < chainSize; i++) { myBillBoardChainElement bbe = (myBillBoardChainElement)mChainElementList[i]; MeshBuilderHelper.SetVertexFloat(ptrBuff, mTCVertexSize, buffIdx++, mTCBuvOff, bbe.uTexCoord, 0.0f); MeshBuilderHelper.SetVertexFloat(ptrBuff, mTCVertexSize, buffIdx++, mTCBuvOff, bbe.uTexCoord, 1.0f); } pTexCoordBuffer.Get().Unlock(); }
/// <summary> /// createGrassMesh /// This demonstrates how to create a manual mesh /// only use static members of MeshBuilderHelper to help set vertex and index data. /// </summary> void createGrassMesh() { OgreDotNet.MeshPtr mp = MeshManager.Instance.CreateManual(GRASS_MESH_NAME, "General"); SubMesh sm = mp.Get().CreateSubMesh(); sm.useSharedVertices = false; sm.vertexData = new VertexData(); sm.vertexData.vertexStart = 0; sm.vertexData.vertexCount = 12; //mIndexType = HardwareIndexBuffer::IT_16BIT; VertexDeclaration dcl = sm.vertexData.vertexDeclaration; UInt32 offset = 0; UInt32 offPos = dcl.addElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_POSITION).getOffset(); offset = VertexElement.getTypeSize(VertexElementType.VET_FLOAT3); UInt32 offNorm = dcl.addElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_NORMAL).getOffset(); offset += VertexElement.getTypeSize(VertexElementType.VET_FLOAT3); UInt32 offUV = dcl.addElement(0, offset, VertexElementType.VET_FLOAT2, VertexElementSemantic.VES_TEXTURE_COORDINATES).getOffset(); offset += VertexElement.getTypeSize(VertexElementType.VET_FLOAT2); UInt32 vertexsize = offset; mLog.LogMessage(string.Format("createGrassMesh vertexsize={0}", vertexsize)); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.getSingleton().createVertexBuffer( vertexsize, 12, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); IntPtr pV = vbuf.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); Vector3 vec = new Vector3(GRASS_WIDTH / 2.0f, 0.0f, 0.0f); Quaternion rot = Quaternion.FromAngleAxis(60, Vector3.UnitY); uint i; for (i = 0; i < 3; ++i) { OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offPos, -vec.x, GRASS_HEIGHT, -vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offUV, 0.0f, 0.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offPos, vec.x, GRASS_HEIGHT, vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offUV, 1.0f, 0.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offPos, -vec.x, 0.0f, -vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offUV, 0.0f, 1.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offPos, vec.x, 0.0f, vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offUV, 1.0f, 1.0f); //uv vec = rot * vec; } vbuf.Get().Unlock(); sm.vertexData.vertexBufferBinding.setBinding(0, vbuf); sm.indexData.indexCount = 6 * 3; sm.indexData.indexBuffer = HardwareBufferManager.getSingleton().createIndexBuffer( HardwareIndexBuffer.IndexType.IT_16BIT, 6 * 3, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); IntPtr pI = sm.indexData.indexBuffer.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); for (i = 0; i < 3; ++i) { UInt16 off = (UInt16)(i * 4); OgreDotNet.MeshBuilderHelper.SetIndex16bit(pI, (i * 2) + 0, (UInt16)(0 + off), (UInt16)(3 + off), (UInt16)(1 + off)); OgreDotNet.MeshBuilderHelper.SetIndex16bit(pI, (i * 2) + 1, (UInt16)(0 + off), (UInt16)(2 + off), (UInt16)(3 + off)); } sm.indexData.indexBuffer.Get().Unlock(); sm.SetMaterialName(GRASS_MATERIAL); mp.Get().Load(); }