public DependencyInfo GetDependencyInfo(Stream stream, Mesh mesh) { BinaryMemoryReader reader = new BinaryMemoryReader(stream); // read the header ID ushort headerID = ReadUShort(reader); if (headerID != (ushort)MeshChunkID.Header) { throw new AxiomException("File header not found."); } // read version string fileVersion = ReadString(reader); // set jump back to the start of the reader Seek(reader, 0, SeekOrigin.Begin); // barf if there specified version is not supported if (!implementations.ContainsKey(fileVersion)) { throw new AxiomException("Cannot find serializer implementation for version '{0}'.", fileVersion); } LogManager.Instance.Write("Mesh: Fetching dependency info '{0}'...", mesh.Name); // call implementation MeshSerializerImpl serializer = (MeshSerializerImpl)implementations[fileVersion]; DependencyInfo rv = serializer.GetDependencyInfo(stream, mesh); // warn on old version of mesh if (fileVersion != currentVersion) { LogManager.Instance.Write("WARNING: {0} is an older format ({1}); you should upgrade it as soon as possible using the OgreMeshUpdate tool.", mesh.Name, fileVersion); } return rv; }
/// <summary> /// Exports a mesh to the file specified. /// </summary> /// <remarks> /// This method takes an externally created Mesh object, and exports both it /// to a .mesh file. /// </remarks> /// <param name="mesh">Reference to the mesh to export.</param> /// <param name="fileName">The destination file name.</param> public void ExportMesh(Mesh mesh, string fileName) { this.mesh = mesh; FileStream stream = new FileStream(fileName, FileMode.Create); try { BinaryWriter writer = new BinaryWriter(stream); WriteFileHeader(writer, version); WriteMesh(writer); } finally { if (stream != null) stream.Close(); } }
/// <summary> /// Creates a plane as a submesh of the given mesh /// </summary> private static void _createPlane( Mesh mesh ) { SubMesh sub = mesh.CreateSubMesh(); float[] vertices = new float[ 32 ] { -100, -100, 0, // pos 0,0,1, // normal 0,1, // texcoord 100, -100, 0, 0,0,1, 1,1, 100, 100, 0, 0,0,1, 1,0, -100, 100, 0 , 0,0,1, 0,0 }; mesh.SharedVertexData = new VertexData(); mesh.SharedVertexData.vertexCount = 4; VertexDeclaration decl = mesh.SharedVertexData.vertexDeclaration; VertexBufferBinding binding = mesh.SharedVertexData.vertexBufferBinding; int offset = 0; decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, 4, BufferUsage.StaticWriteOnly ); binding.SetBinding( 0, vbuf ); vbuf.WriteData( 0, vbuf.Size, vertices, true ); sub.useSharedVertices = true; HardwareIndexBuffer ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, 6, BufferUsage.StaticWriteOnly ); short[] faces = new short[ 6 ] { 0, 1, 2, 0, 2, 3 }; sub.IndexData.indexBuffer = ibuf; sub.IndexData.indexCount = 6; sub.IndexData.indexStart = 0; ibuf.WriteData( 0, ibuf.Size, faces, true ); mesh.BoundingBox = new AxisAlignedBox( new Vector3( -100, -100, 0 ), new Vector3( 100, 100, 0 ) ); mesh.BoundingSphereRadius = Utility.Sqrt( 100 * 100 + 100 * 100 ); }
public static bool Create( Mesh mesh ) { switch ( mesh.Name ) { case "Prefab_Plane": _createPlane( mesh ); return true; case "Prefab_Cube": _createCube( mesh ); return true; case "Prefab_Sphere": _createSphere( mesh ); return true; } return false; }
public DependencyInfo GetDependencyInfo(Stream stream, Mesh mesh) { BinaryMemoryReader reader = new BinaryMemoryReader(stream, System.Text.Encoding.ASCII); // check header ReadFileHeader(reader); MeshChunkID chunkID = 0; // read until the end while (!IsEOF(reader)) { chunkID = ReadChunk(reader); if (chunkID == MeshChunkID.DependencyInfo) { DependencyInfo info = new DependencyInfo(); ReadDependencyInfo(reader, info); return info; } else { break; } } return null; }
protected void SetMesh( Mesh mesh ) { this.mesh = mesh; if ( mesh.HasSkeleton && mesh.Skeleton != null ) { this.skeletonInstance = new SkeletonInstance( mesh.Skeleton ); this.skeletonInstance.Load(); } else { this.skeletonInstance = null; } this.subEntityList.Clear(); BuildSubEntities(); this.lodEntityList.Clear(); // Check if mesh is using manual LOD if ( mesh.IsLodManual ) { for ( var i = 1; i < mesh.LodLevelCount; i++ ) { var usage = mesh.GetLodLevel( i ); // manually create entity var lodEnt = new Entity( string.Format( "{0}Lod{1}", name, i ), usage.ManualMesh ); this.lodEntityList.Add( lodEnt ); } } this.animationState.RemoveAllAnimationStates(); // init the AnimationState, if the mesh is animated if ( HasSkeleton ) { this.numBoneMatrices = this.skeletonInstance.BoneCount; this.boneMatrices = new Matrix4[this.numBoneMatrices]; } if ( HasSkeleton || mesh.HasVertexAnimation ) { mesh.InitAnimationState( this.animationState ); PrepareTempBlendedBuffers(); } ReevaluateVertexProcessing(); // LOD default settings this.meshLodFactorTransformed = 1.0f; // Backwards, remember low value = high detail this.minMeshLodIndex = 99; this.maxMeshLodIndex = 0; // Material LOD default settings this.materialLodFactor = 1.0f; this.maxMaterialLodIndex = 0; this.minMaterialLodIndex = 99; // Do we have a mesh where edge lists are not going to be available? //if ( ( ( this.sceneMgr.ShadowTechnique == ShadowTechnique.StencilAdditive ) // || ( this.sceneMgr.ShadowTechnique == ShadowTechnique.StencilModulative ) ) && // !mesh.IsEdgeListBuilt && !mesh.AutoBuildEdgeLists ) //{ // this.CastShadows = false; //} }
/// <summary> /// Create an Entity (instance of a discrete mesh). /// </summary> /// <param name="name">The name to be given to the entity (must be unique).</param> /// <param name="mesh">The mesh to use.</param> /// <returns></returns> public virtual Entity CreateEntity( string name, Mesh mesh ) { NamedParameterList param = new NamedParameterList(); param.Add( "mesh", mesh ); return (Entity)this.CreateMovableObject( name, EntityFactory.TypeName, param ); }
/// <summary> /// Exports a mesh to the file specified. /// </summary> /// <remarks> /// This method takes an externally created Mesh object, and exports both it /// to a .mesh file. /// </remarks> /// <param name="mesh">Reference to the mesh to export.</param> /// <param name="fileName">The destination file name.</param> public void ExportMesh( Mesh mesh, string fileName ) { LogManager.Instance.Write( "MeshSerializer writing mesh data to {0} ...", fileName ); this.mesh = mesh; // Check that the mesh has it's bounds set if ( mesh.BoundingBox.IsNull || mesh.BoundingSphereRadius == 0.0F ) { throw new AxiomException( "The mesh you supplied does not have its bounds completely defined. Define them first before exporting." ); } var stream = new FileStream( fileName, FileMode.Create ); try { var writer = new BinaryWriter( stream ); WriteFileHeader( writer, version ); LogManager.Instance.Write( "File header written." ); LogManager.Instance.Write( "Writing mesh data..." ); WriteMesh( writer ); LogManager.Instance.Write( "Mesh data exported." ); } finally { if ( stream != null ) { stream.Close(); LogManager.Instance.Write( "MeshSerializer export successful." ); } } }
private void LoadMesh(string filename) { int lastBackslash = filename.LastIndexOf('\\'); string clippedFilename = filename.Substring(lastBackslash + 1); string srcDir = filename.Substring(0, lastBackslash + 1); SetAnimation(null); UpdateAnimationListBox(); if (boneDisplay != null) { boneDisplay.Close(); boneDisplay = null; } if (loadedModel != null) { // clean up the last model if we are loading a new one RemoveCollisionObjects(0); CleanupSockets(); CleanupBones(); CleanupNormalsRenderable(); Debug.Assert(attachedNodes.Count == 0); modelNode.DetachObject(loadedModel); sceneManager.RemoveEntity(loadedModel); } CleanupGroundPlaneRenderable(); Mesh mesh = ReadMesh(Matrix4.Identity, srcDir, clippedFilename); SetupPoseAnimation(mesh); // // Create the list of triangles used to query mouse hits // mesh.CreateTriangleIntersector(); loadedMesh = mesh; loadedModel = sceneManager.CreateEntity("model", mesh); Text = "ModelViewer: " + filename; // move the camera focus to the middle of the new model ModelHeight = loadedModel.BoundingBox.Maximum.y - loadedModel.BoundingBox.Minimum.y; if (CameraRadius < loadedModel.BoundingRadius) { CameraRadius = loadedModel.BoundingRadius; } PositionCamera(); modelNode.AttachObject(loadedModel); AddCollisionObject(loadedModel, modelNode, 0, Path.GetFileNameWithoutExtension(clippedFilename) + ".physics"); //modelNode.DetachObject(loadedModel); loadedModel.ShowBoundingBox = showBoundingBox; if (loadedModel.Mesh != null && loadedModel.Mesh.ContainsAnimation("manual")) { AnimationState manualAnimState = loadedModel.GetAnimationState("manual"); manualAnimState.Time = 0; manualAnimState.IsEnabled = true; } PopulateSubMeshListBox(); PopulateAnimationListBox(); PopulateSocketListBox(); PopulateBonesListBox(); // disable the fields parentBoneLabel.Visible = false; parentBoneValueLabel.Text = ""; parentBoneValueLabel.Visible = false; }
protected internal void FireProcessSkeletonName( Mesh mesh, string name ) { _processSkeletonNameEvent.Fire(this, new MeshSerializerArgs { Mesh = mesh, Name = name}, (args) => { return true; }); }
public static void CopyBoneAssignments(Mesh dst, Mesh src, Dictionary<uint, uint> vertexIdMap) { foreach (KeyValuePair<uint, uint> vertexMapping in vertexIdMap) { List<VertexBoneAssignment> srcVbaList = src.BoneAssignmentList[(int)vertexMapping.Key]; foreach (VertexBoneAssignment srcVba in srcVbaList) { Debug.Assert(srcVba.vertexIndex == (int)vertexMapping.Key); VertexBoneAssignment dstVba = new VertexBoneAssignment(); dstVba.boneIndex = srcVba.boneIndex; dstVba.vertexIndex = (int)vertexMapping.Value; dstVba.weight = srcVba.weight; dst.AddBoneAssignment(dstVba); } } }
// mesh will be null if this fails static void ImportKMZFile( ref string materialScript, Matrix4 transform, string dstDir, string meshFile, FileStream kmzStream, Mesh mesh ) { string daeFile = ExtractKMZComponentFiles( dstDir, kmzStream ); if( ! String.IsNullOrEmpty( daeFile ) ) { string materialNamespace = Path.GetFileNameWithoutExtension( daeFile ); string animationNamespace = materialNamespace; FileStream daeStream = new FileStream( daeFile, FileMode.Open ); ColladaMeshReader meshReader = new ColladaMeshReader( daeStream, animationNamespace ); // Convert from a left handed system where z is up to a right handed system where y is up. Matrix4 yupTrans = new Matrix4( 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 ); Matrix4 yupTransform = transform * yupTrans; // import the .dae file meshReader.Import( yupTransform, mesh, null, "base", materialNamespace ); materialScript = meshReader.MaterialScript; } }
public WaterMesh( String meshName, float planeSize, int cmplx ) { // najak R-F // Assign Fields to the Initializer values this.meshName = meshName; this.size = planeSize; this.cmplx = cmplx; // Number of Rows/Columns in the Water Grid representation cmplxAdj = (float)System.Math.Pow( ( cmplx / 64f ), 1.4f ) * 2; numFaces = 2 * (int)System.Math.Pow( cmplx, 2 ); // Each square is split into 2 triangles. numVertices = (int)System.Math.Pow( ( cmplx + 1 ), 2 ); // Vertex grid is (Complexity+1) squared // Allocate and initialize space for calculated Normals vNorms = new Vector3[ cmplx + 1, cmplx + 1 ]; // vertex Normals for each grid point fNorms = new Vector3[ cmplx, cmplx, 2 ]; // face Normals for each triangle // Create mesh and submesh to represent the Water mesh = (Mesh)MeshManager.Instance.CreateManual( meshName, ResourceGroupManager.DefaultResourceGroupName, null ); subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; // Construct metadata to describe the buffers associated with the water submesh subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = numVertices; // Define local variables to point to the VertexData Properties VertexDeclaration vdecl = subMesh.vertexData.vertexDeclaration; // najak: seems like metadata VertexBufferBinding vbind = subMesh.vertexData.vertexBufferBinding; // najak: pointer to actual buffer //najak: Set metadata to describe the three vertex buffers that will be accessed. vdecl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position ); vdecl.AddElement( 1, 0, VertexElementType.Float3, VertexElementSemantic.Normal ); vdecl.AddElement( 2, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords ); // Prepare buffer for positions - todo: first attempt, slow // Create the Position Vertex Buffer and Bind it index 0 - Write Only posVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(0), numVertices, BufferUsage.DynamicWriteOnly ); vbind.SetBinding( 0, posVBuf ); // Prepare buffer for normals - write only // Create the Normals Buffer and Bind it to index 1 - Write only normVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(1), numVertices, BufferUsage.DynamicWriteOnly ); vbind.SetBinding( 1, normVBuf ); // Prepare Texture Coordinates buffer (static, written only once) // Creates a 2D buffer of 2D coordinates: (Complexity X Complexity), pairs. // Each pair indicates the normalized coordinates of the texture to map to. // (0,1.00), (0.02, 1.00), (0.04, 1.00), ... (1.00,1.00) // (0,0.98), (0.02, 0.98), (0.04, 1.00), ... (1.00,0.98) // ... // (0,0.00), (0.02, 0.00), (0.04, 0.00), ... (1.00,0.00) // This construct is simple and is used to calculate the Texture map. // Todo: Write directly to the buffer, when Axiom supports this in safe manner float[ , , ] tcBufDat = new float[ cmplx + 1, cmplx + 1, 2 ]; for ( int i = 0; i <= cmplx; i++ ) { // 2D column iterator for texture map for ( int j = 0; j <= cmplx; j++ ) { // 2D row iterator for texture map // Define the normalized(0..1) X/Y-coordinates for this element of the 2D grid tcBufDat[ i, j, 0 ] = (float)i / cmplx; tcBufDat[ i, j, 1 ] = 1.0f - ( (float)j / ( cmplx ) ); } } // Now Create the actual hardware buffer to contain the Texture Coordinate 2d map. // and Bind it to buffer index 2 tcVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(2), numVertices, BufferUsage.StaticWriteOnly ); tcVBuf.WriteData( 0, tcVBuf.Size, tcBufDat, true ); vbind.SetBinding( 2, tcVBuf ); // Create a Graphics Buffer on non-shared vertex indices (3 points for each triangle). // Since the water grid consist of [Complexity x Complexity] squares, each square is // split into 2 right triangles 45-90-45. That is how the water mesh is constructed. // Therefore the number of faces = 2 * Complexity * Complexity ushort[ , , ] idxBuf = new ushort[ cmplx, cmplx, 6 ]; for ( int i = 0; i < cmplx; i++ ) { // iterate the rows for ( int j = 0; j < cmplx; j++ ) { // iterate the columns // Define 4 corners of each grid ushort p0 = (ushort)( i * ( cmplx + 1 ) + j ); // top left point on square ushort p1 = (ushort)( i * ( cmplx + 1 ) + j + 1 ); // top right ushort p2 = (ushort)( ( i + 1 ) * ( cmplx + 1 ) + j ); // bottom left ushort p3 = (ushort)( ( i + 1 ) * ( cmplx + 1 ) + j + 1 ); // bottom right // Split Square Grid element into 2 adjacent triangles. idxBuf[ i, j, 0 ] = p2; idxBuf[ i, j, 1 ] = p1; idxBuf[ i, j, 2 ] = p0; // top-left triangle idxBuf[ i, j, 3 ] = p2; idxBuf[ i, j, 4 ] = p3; idxBuf[ i, j, 5 ] = p1; // bottom-right triangle } } // Copy Index Buffer to the Hardware Index Buffer HardwareIndexBuffer hdwrIdxBuf = HwBufMgr.CreateIndexBuffer( IndexType.Size16, 3 * numFaces, BufferUsage.StaticWriteOnly, true ); hdwrIdxBuf.WriteData( 0, numFaces * 3 * 2, idxBuf, true ); // Set index buffer for this submesh subMesh.indexData.indexBuffer = hdwrIdxBuf; subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 3 * numFaces; //Prepare Vertex Position Buffers (Note: make 3, since each frame is function of previous two) vBufs = new Vector3[ 3 ][ , ]; for ( int b = 0; b < 3; b++ ) { vBufs[ b ] = new Vector3[ cmplx + 1, cmplx + 1 ]; for ( int y = 0; y <= cmplx; y++ ) { for ( int x = 0; x <= cmplx; x++ ) { vBufs[ b ][ y, x ].x = (float)( x ) / (float)( cmplx ) * (float)size; vBufs[ b ][ y, x ].y = 0; vBufs[ b ][ y, x ].z = (float)( y ) / (float)( cmplx ) * (float)size; } } } curBufNum = 0; vBuf = vBufs[ curBufNum ]; posVBuf.WriteData( 0, posVBuf.Size, vBufs[ 0 ], true ); AxisAlignedBox meshBounds = new AxisAlignedBox( new Vector3( 0, 0, 0 ), new Vector3( size, 0, size ) ); mesh.BoundingBox = meshBounds; // mesh->_setBounds(meshBounds); // najak: can't find _setBounds() mesh.Load(); mesh.Touch(); } // end WaterMesh Constructor
private static void _createSphere( Mesh mesh ) { // sphere creation code taken from the DeferredShading sample, originally from the [Ogre] wiki var pSphereVertex = mesh.CreateSubMesh(); const int NUM_SEGMENTS = 16; const int NUM_RINGS = 16; const float SPHERE_RADIUS = 50.0f; mesh.SharedVertexData = new VertexData(); var vertexData = mesh.SharedVertexData; // define the vertex format var vertexDecl = vertexData.vertexDeclaration; var offset = 0; // positions vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // normals vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // two dimensional texture coordinates vertexDecl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); // allocate the vertex buffer vertexData.vertexCount = ( NUM_RINGS + 1 )*( NUM_SEGMENTS + 1 ); var vBuf = HardwareBufferManager.Instance.CreateVertexBuffer( vertexDecl.Clone( 0 ), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false ); var binding = vertexData.vertexBufferBinding; binding.SetBinding( 0, vBuf ); // allocate index buffer pSphereVertex.IndexData.indexCount = 6*NUM_RINGS*( NUM_SEGMENTS + 1 ); pSphereVertex.IndexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, pSphereVertex.IndexData. indexCount, BufferUsage.StaticWriteOnly, false ); var iBuf = pSphereVertex.IndexData.indexBuffer; #if !AXIOM_SAFE_ONLY unsafe #endif { var iVertex = 0; var pVertex = vBuf.Lock( BufferLocking.Discard ).ToFloatPointer(); var iIndices = 0; var pIndices = iBuf.Lock( BufferLocking.Discard ).ToUShortPointer(); float fDeltaRingAngle = ( Utility.PI/NUM_RINGS ); float fDeltaSegAngle = ( 2*Utility.PI/NUM_SEGMENTS ); ushort wVerticeIndex = 0; // Generate the group of rings for the sphere for ( var ring = 0; ring <= NUM_RINGS; ring++ ) { float r0 = SPHERE_RADIUS*Utility.Sin( ring*fDeltaRingAngle ); float y0 = SPHERE_RADIUS*Utility.Cos( ring*fDeltaRingAngle ); // Generate the group of segments for the current ring for ( var seg = 0; seg <= NUM_SEGMENTS; seg++ ) { float x0 = r0*Utility.Sin( seg*fDeltaSegAngle ); float z0 = r0*Utility.Cos( seg*fDeltaSegAngle ); // Add one vertex to the strip which makes up the sphere pVertex[ iVertex++ ] = x0; pVertex[ iVertex++ ] = y0; pVertex[ iVertex++ ] = z0; var vNormal = new Vector3( x0, y0, z0 ).ToNormalized(); pVertex[ iVertex++ ] = vNormal.x; pVertex[ iVertex++ ] = vNormal.y; pVertex[ iVertex++ ] = vNormal.z; pVertex[ iVertex++ ] = (float)seg/(float)NUM_SEGMENTS; pVertex[ iVertex++ ] = (float)ring/(float)NUM_RINGS; if ( ring != NUM_RINGS ) { // each vertex (except the last) has six indicies pointing to it pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex ); wVerticeIndex++; } } ; // end for seg } // end for ring } // Unlock vBuf.Unlock(); iBuf.Unlock(); // Generate face list pSphereVertex.useSharedVertices = true; // the original code was missing this line: mesh.BoundingBox = new AxisAlignedBox( new Vector3( -SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS ), new Vector3( SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS ) ); mesh.BoundingSphereRadius = SPHERE_RADIUS; }
private static void _createCube( Mesh mesh ) { var sub = mesh.CreateSubMesh(); const int NUM_VERTICES = 4*6; // 4 vertices per side * 6 sides const int NUM_ENTRIES_PER_VERTEX = 8; const int NUM_VERTEX_ENTRIES = NUM_VERTICES*NUM_ENTRIES_PER_VERTEX; const int NUM_INDICES = 3*2*6; // 3 indices per face * 2 faces per side * 6 sides const float CUBE_SIZE = 100.0f; const float CUBE_HALF_SIZE = CUBE_SIZE/2.0f; // Create 4 vertices per side instead of 6 that are shared for the whole cube. // The reason for this is with only 6 vertices the normals will look bad // since each vertex can "point" in a different direction depending on the face it is included in. var vertices = new float[NUM_VERTEX_ENTRIES] { // front side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, // pos 0, 0, 1, // normal 0, 1, // texcoord CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 0, 0, // back side CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 0, 1, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 1, 1, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 1, 0, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 0, 0, // left side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -1, 0, 0, 0, 1, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -1, 0, 0, 1, 1, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -1, 0, 0, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -1, 0, 0, 0, 0, // right side CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 1, 0, 0, 0, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 1, 0, 0, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 1, 0, 0, 1, 0, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 1, 0, 0, 0, 0, // up side -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 1, 0, 0, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 1, 0, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 1, 0, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 1, 0, 0, 0, // down side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, -1, 0, 0, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, -1, 0, 1, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, -1, 0, 1, 0, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, -1, 0, 0, 0 }; mesh.SharedVertexData = new VertexData(); mesh.SharedVertexData.vertexCount = NUM_VERTICES; var decl = mesh.SharedVertexData.vertexDeclaration; var bind = mesh.SharedVertexData.vertexBufferBinding; var offset = 0; decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); var vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, NUM_VERTICES, BufferUsage.StaticWriteOnly ); bind.SetBinding( 0, vbuf ); vbuf.WriteData( 0, vbuf.Size, vertices, true ); sub.useSharedVertices = true; var ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, NUM_INDICES, BufferUsage.StaticWriteOnly ); var faces = new short[NUM_INDICES] { // front 0, 1, 2, 0, 2, 3, // back 4, 5, 6, 4, 6, 7, // left 8, 9, 10, 8, 10, 11, // right 12, 13, 14, 12, 14, 15, // up 16, 17, 18, 16, 18, 19, // down 20, 21, 22, 20, 22, 23 }; sub.IndexData.indexBuffer = ibuf; sub.IndexData.indexCount = NUM_INDICES; sub.IndexData.indexStart = 0; ibuf.WriteData( 0, ibuf.Size, faces, true ); mesh.BoundingBox = new AxisAlignedBox( new Vector3( -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE ), new Vector3( CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE ) ); mesh.BoundingSphereRadius = CUBE_HALF_SIZE; }
/// <summary> /// /// </summary> /// <param name="meshName"></param> private void PrepareEntity(string meshName) { if(objectEntity != null) { ClearEntity(); } // load mesh if necessary originalMesh = (Mesh)MeshManager.Instance.GetByName(meshName); // load mesh with shadow buffer so we can do fast reads if(originalMesh == null) { originalMesh = (Mesh)MeshManager.Instance.Load( meshName, BufferUsage.StaticWriteOnly, BufferUsage.StaticWriteOnly, true, true, 1); if(originalMesh == null) { throw new Exception(string.Format("Can't find mesh named '{0}'.", meshName)); } } PrepareClonedMesh(); // create a new entity based on the cloned mesh objectEntity = scene.CreateEntity(ENTITY_NAME, MESH_NAME); // setting the material here propogates it down to cloned sub entites, no need to clone them objectEntity.MaterialName = material.Name; Pass pass = material.GetTechnique(0).GetPass(0); // add original sub mesh texture layers after the new cube map recently added for(int i = 0; i < clonedMesh.SubMeshCount; i++) { SubMesh subMesh = clonedMesh.GetSubMesh(i); SubEntity subEntity = objectEntity.GetSubEntity(i); // does this mesh have its own material set? if(subMesh.IsMaterialInitialized) { string matName = subMesh.MaterialName; Material subMat = MaterialManager.Instance.GetByName(matName); if(subMat != null) { subMat.Load(); // Clone the sub entities material Material cloned = subMat.Clone(string.Format("CubeMapTempMaterial#{0}", i)); Pass clonedPass = cloned.GetTechnique(0).GetPass(0); // add global texture layers to the existing material of the entity for(int j = 0; j < pass.NumTextureUnitStages; j++) { TextureUnitState orgLayer = pass.GetTextureUnitState(j); TextureUnitState newLayer = clonedPass.CreateTextureUnitState(orgLayer.TextureName); orgLayer.CopyTo(newLayer); newLayer.SetColorOperationEx(currentLbx); } // set the new material for the subentity and cache it subEntity.MaterialName = cloned.Name; clonedMaterials.Add(cloned); } } } // attach the entity to the scene objectNode.AttachObject(objectEntity); // update noise if currently set to on if(noiseOn) { UpdateNoise(); } }
public static Mesh CopyMesh(Mesh mesh) { Mesh newMesh = new Mesh(mesh.Name); if (mesh.Skeleton != null) newMesh.NotifySkeleton(mesh.Skeleton); newMesh.SetVertexBufferPolicy(mesh.VertexBufferUsage, mesh.UseVertexShadowBuffer); newMesh.SetIndexBufferPolicy(mesh.IndexBufferUsage, mesh.UseIndexShadowBuffer); // this sets bounding radius as well newMesh.BoundingBox = mesh.BoundingBox; MeshUtility meshUtility = new MeshUtility(); for (int i = 0; i < mesh.SubMeshCount; ++i) meshUtility.AddSubmeshData(mesh.GetSubMesh(i)); // This should be done after we finish with the lod stuff newMesh.AutoBuildEdgeLists = true; newMesh.BuildEdgeList(); foreach (AttachmentPoint ap in mesh.AttachmentPoints) newMesh.AttachmentPoints.Add(new AttachmentPoint(ap)); for (int i = 0; i < mesh.SubMeshCount; ++i) { SubMesh srcSubMesh = mesh.GetSubMesh(i); SubMesh dstSubMesh = newMesh.CreateSubMesh(srcSubMesh.Name); CopySubMesh(dstSubMesh, srcSubMesh, meshUtility.subMeshDataMap[srcSubMesh.Name]); } if (mesh.SharedVertexData != null) { newMesh.SharedVertexData = new VertexData(); CopyVertexData(newMesh.SharedVertexData, mesh.SharedVertexData, meshUtility.sharedSubMeshData.VertexIdMap); CopyBoneAssignments(newMesh, mesh, meshUtility.sharedSubMeshData.VertexIdMap); } // newMesh.CompileBoneAssignments(); return newMesh; }
private static void Test( string srcDir, string dstDir, string name ) { MeshSerializer meshReader = new MeshSerializer(); Stream data = new FileStream( srcDir + name, FileMode.Open ); // import the .mesh file Mesh mesh = new Mesh( "testmesh" ); meshReader.ImportMesh( data, mesh ); meshReader.ExportMesh( mesh, dstDir + name ); }
private void _loadManual( Mesh mesh, MeshBuildParams mbp ) { SubMesh subMesh = mesh.CreateSubMesh(); // Set up vertex data // Use a single shared buffer mesh.SharedVertexData = new VertexData(); VertexData vertexData = mesh.SharedVertexData; // Set up Vertex Declaration VertexDeclaration decl = vertexData.vertexDeclaration; int currOffset = 0; // add position data // We always need positions decl.AddElement( 0, currOffset, VertexElementType.Float3, VertexElementSemantic.Position ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // normals are optional if ( mbp.Normals ) { decl.AddElement( 0, currOffset, VertexElementType.Float3, VertexElementSemantic.Normal ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float3 ); } // add texture coords for ( ushort i = 0; i < mbp.TexCoordSetCount; i++ ) { decl.AddElement( 0, currOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float2 ); } vertexData.vertexCount = ( mbp.XSegments + 1 ) * ( mbp.YSegments + 1 ); // create a new vertex buffer (based on current API) HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl.Clone( 0 ), vertexData.vertexCount, mbp.VertexBufferUsage, mbp.VertexShadowBuffer ); // get a reference to the vertex buffer binding VertexBufferBinding binding = vertexData.vertexBufferBinding; // bind the first vertex buffer binding.SetBinding( 0, vbuf ); // transform the plane based on its plane def Matrix4 translate = Matrix4.Identity; Matrix4 transform = Matrix4.Zero; Matrix4 rotation = Matrix4.Identity; Matrix3 rot3x3 = Matrix3.Zero; Vector3 xAxis, yAxis, zAxis; zAxis = mbp.Plane.Normal; zAxis.Normalize(); yAxis = mbp.UpVector; yAxis.Normalize(); xAxis = yAxis.Cross( zAxis ); if ( xAxis.Length == 0 ) { throw new AxiomException( "The up vector for a plane cannot be parallel to the planes normal." ); } rot3x3.FromAxes( xAxis, yAxis, zAxis ); rotation = rot3x3; // set up transform from origin translate.Translation = mbp.Plane.Normal * -mbp.Plane.D; transform = translate * rotation; float xSpace = mbp.Width / mbp.XSegments; float ySpace = mbp.Height / mbp.YSegments; float halfWidth = mbp.Width / 2; float halfHeight = mbp.Height / 2; float xTexCoord = ( 1.0f * mbp.XTile ) / mbp.XSegments; float yTexCoord = ( 1.0f * mbp.YTile ) / mbp.YSegments; Vector3 vec = Vector3.Zero; Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; float maxSquaredLength = 0; bool firstTime = true; // generate vertex data switch ( mbp.Type ) { case MeshBuildType.Plane: _generatePlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, rotation, mbp.TexCoordSetCount, xTexCoord, yTexCoord, subMesh, ref min, ref max, ref maxSquaredLength ); break; case MeshBuildType.CurvedPlane: _generateCurvedPlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, rotation, mbp.Curvature, mbp.TexCoordSetCount, xTexCoord, yTexCoord, subMesh, ref min, ref max, ref maxSquaredLength ); break; case MeshBuildType.CurvedIllusionPlane: _generateCurvedIllusionPlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, mbp.Orientation, mbp.Curvature, xTexCoord, yTexCoord, mbp.TexCoordSetCount, ref min, ref max, ref maxSquaredLength ); break; default: throw new Exception( "" ); } // generate face list _tesselate2DMesh( subMesh, mbp.XSegments + 1, mbp.YSegments + 1, false, mbp.IndexBufferUsage, mbp.IndexShadowBuffer ); // generate bounds for the mesh mesh.BoundingBox = new AxisAlignedBox( min, max ); mesh.BoundingSphereRadius = Utility.Sqrt( maxSquaredLength ); }
/// <summary> /// Utility method to merge animations from other files into a single skeleton /// </summary> /// <param name="srcDir">the directory from which the new animations will be loaded</param> /// <param name="dstDir">the directory to which the modified skeleton will be saved</param> /// <param name="skelFile">the name of the file to which the modified skeleton will be written</param> /// <param name="transform">the transform to apply to the skeleton and animations</param> /// <param name="skeleton">the original skeleton</param> /// <param name="animations">the list of animations</param> private static void AddAnimations( string srcDir, string dstDir, string skelFile, Matrix4 transform, Skeleton skeleton, List<AnimationEntry> animations ) { // mesh loading stats int before, after; // get the tick count before loading the mesh before = Environment.TickCount; foreach( AnimationEntry entry in animations ) { Mesh mesh = new Mesh( "Mesh" ); Stream data = new FileStream( srcDir + entry.animation_file, FileMode.Open ); ColladaMeshReader meshReader = new ColladaMeshReader( data, null ); // import the .dae file meshReader.Import( transform, mesh, skeleton, entry.animation_name, null ); // close the stream (we don't need to leave it open here) data.Close(); } // get the tick count after loading the mesh after = Environment.TickCount; // record the time elapsed while loading the mesh log.InfoFormat( "Mesh: took {0}ms", (after - before) ); //// prepare the mesh for a shadow volume? //if (MeshManager.Instance.PrepareAllMeshesForShadowVolumes) { // if (edgeListsBuilt || autoBuildEdgeLists) { // PrepareForShadowVolume(); // } // if (!edgeListsBuilt && autoBuildEdgeLists) { // BuildEdgeList(); // } //} OgreSkeletonSerializer skelWriter = new OgreSkeletonSerializer(); skelWriter.ExportSkeleton( skeleton, dstDir + skelFile ); }
private static Mesh ReadMesh(Matrix4 transform, string srcDir, string meshFile) { Stream meshData = new FileStream(srcDir + meshFile, FileMode.Open); Mesh mesh = new Mesh(meshFile); if (meshFile.EndsWith(".mesh", StringComparison.CurrentCultureIgnoreCase)) { MeshSerializer meshReader = new MeshSerializer(); meshReader.ImportMesh(meshData, mesh); } else if (meshFile.EndsWith(".mesh.xml", StringComparison.CurrentCultureIgnoreCase)) { OgreXmlMeshReader meshReader = new OgreXmlMeshReader(meshData); meshReader.Import(mesh); } else if (meshFile.EndsWith(".dae", StringComparison.CurrentCultureIgnoreCase)) { string extension = Path.GetExtension(meshFile); string baseFile = Path.GetFileNameWithoutExtension(meshFile); string basename = meshFile.Substring(0, meshFile.Length - extension.Length); ColladaMeshReader meshReader = new ColladaMeshReader(meshData, baseFile); // import the .dae file meshReader.Import(transform, mesh, null, "idle", basename); // materialScript = meshReader.MaterialScript; } else { meshData.Close(); string extension = Path.GetExtension(meshFile); throw new AxiomException("Unsupported mesh format '{0}'", extension); } meshData.Close(); return mesh; }
public void Import( Mesh mesh ) { Import( Matrix4.Identity, mesh, null, "idle", null ); }
private void SetupPoseAnimation(Mesh mesh) { if (mesh != null && mesh.PoseList.Count > 0) { Animation anim = mesh.CreateAnimation("manual", 0); List<ushort> poseTargets = new List<ushort>(); foreach (Pose pose in mesh.PoseList) if (!poseTargets.Contains(pose.Target)) poseTargets.Add(pose.Target); foreach (ushort poseTarget in poseTargets) { VertexAnimationTrack track = anim.CreateVertexTrack(poseTarget, VertexAnimationType.Pose); VertexPoseKeyFrame manualKeyFrame = track.CreateVertexPoseKeyFrame(0); // create pose references, initially zero for (ushort poseIndex = 0; poseIndex < mesh.PoseList.Count; ++poseIndex) { Pose pose = mesh.PoseList[poseIndex]; if (pose.Target == poseTarget) manualKeyFrame.AddPoseReference(poseIndex, 0); } } } }
/// <summary> /// Import into the mesh, using the skeleton provided, and /// assigning the animation data to a new animation. /// </summary> /// <param name="transform">the world transform to apply to this object</param> /// <param name="mesh">the mesh we will populate</param> /// <param name="skeleton">the skeleton to which we will add animations (or null if we are creating one)</param> /// <param name="animationName">the name that will be used for the animation</param> /// <param name="materialNamespace">namespace used for generation of material names</param> public void Import( Matrix4 transform, Mesh mesh, Skeleton skeleton, string animationName, string materialNamespace ) { ColladaMeshReader reader = null; XmlDocument document = new XmlDocument(); document.Load( m_Stream ); XmlElement rootElement = document.DocumentElement; // This is slightly weird. The client calls this method on this object, // but then we determine which version of collada we're actually looking // at, and create a new instances of a derived collada reader. As an // outcome, we have to copy fields from the factory-created instance // back to this instance. // TODO: Need a static factory method on the base class to create the // collada reader instance, then call that instance from the client; // that way we'll only have one instance in the first place. reader = GetColladaParser( rootElement ); reader.m_ColladaRootNode = rootElement; reader.m_Document = document; reader.m_MaterialBuilder = new MaterialScriptBuilder( materialNamespace ); ColladaMeshInfo meshInfo = new ColladaMeshInfo( mesh ); reader.ReadCollada( rootElement, meshInfo ); meshInfo.NoRiggingCulling = NoRiggingCulling; meshInfo.Process( transform, skeleton, m_BaseFile, animationName ); this.m_MaterialBuilder = reader.MaterialBuilder; }
/// <summary> /// Imports mesh data from a .mesh file. /// </summary> /// <param name="stream">A stream containing the .mesh data.</param> /// <param name="mesh">Mesh to populate with the data.</param> public void ImportMesh( Stream stream, Mesh mesh ) { this.mesh = mesh; var reader = new BinaryReader( stream, System.Text.Encoding.UTF8 ); // check header ReadFileHeader( reader ); MeshChunkID chunkID = 0; // read until the end while ( !IsEOF( reader ) ) { chunkID = ReadChunk( reader ); switch ( chunkID ) { case MeshChunkID.DependencyInfo: // NOTE: This case and read is not in Ogre, why is it here? var info = new DependencyInfo(); ReadDependencyInfo( reader, info ); break; case MeshChunkID.Mesh: ReadMesh( reader ); break; } } }
protected override void CreateScene() { viewport.BackgroundColor = ColorEx.White; viewport.OverlaysEnabled = false; gen = new Multiverse.Generator.Generator(); gen.Algorithm = GeneratorAlgorithm.HybridMultifractalWithSeedMap; gen.LoadSeedMap("map.csv"); gen.OutsideMapSeedHeight = 0; gen.SeedMapOrigin = new Vector3(-3200, 0, -5120); gen.SeedMapMetersPerSample = 128; gen.XOff = -0.4f; gen.YOff = -0.3f; gen.HeightFloor = 0; gen.FractalOffset = 0.1f; gen.HeightOffset = -0.15f; gen.HeightScale = 300; gen.MetersPerPerlinUnit = 800; lodSpec = new LODSpec(); lodSpecPrev = new LODSpecPrev(); // water plane setup Plane waterPlane = new Plane(Vector3.UnitY, 10f * oneMeter); waterMesh = MeshManager.Instance.CreatePlane( "WaterPlane", waterPlane, 60 * 128 * oneMeter, 90 * 128 * oneMeter, 20, 20, true, 1, 10, 10, Vector3.UnitZ); Debug.Assert(waterMesh != null); SetupScene(); }
/// <summary> /// </summary> internal Entity( string name, Mesh mesh ) : base( name ) { SetMesh( mesh ); }
public DebugRenderable( Node parent ) { _parent = parent; string materialName = "Axiom/Debug/AxesMat"; _material = (Material)MaterialManager.Instance[ materialName ]; if ( _material == null ) { _material = (Material)MaterialManager.Instance.Create( materialName, ResourceGroupManager.InternalResourceGroupName ); Pass p = _material.GetTechnique( 0 ).GetPass( 0 ); p.LightingEnabled = false; //TODO: p.PolygonModeOverrideable = false; p.VertexColorTracking = TrackVertexColor.Ambient; p.SetSceneBlending( SceneBlendType.TransparentAlpha ); p.CullingMode = CullingMode.None; p.DepthWrite = false; } string meshName = "Axiom/Debug/AxesMesh"; _mesh = MeshManager.Instance[ meshName ]; if ( _mesh == null ) { ManualObject mo = new ManualObject( "tmp" ); mo.Begin( Material.Name, OperationType.TriangleList ); /* 3 axes, each made up of 2 of these (base plane = XY) * .------------|\ * '------------|/ */ mo.EstimateVertexCount( 7 * 2 * 3 ); mo.EstimateIndexCount( 3 * 2 * 3 ); Quaternion[] quat = new Quaternion[ 6 ]; ColorEx[] col = new ColorEx[ 3 ]; // x-axis quat[ 0 ] = Quaternion.Identity; quat[ 1 ] = Quaternion.FromAxes( Vector3.UnitX, Vector3.NegativeUnitZ, Vector3.UnitY ); col[ 0 ] = ColorEx.Red; col[ 0 ].a = 0.8f; // y-axis quat[ 2 ] = Quaternion.FromAxes( Vector3.UnitY, Vector3.NegativeUnitX, Vector3.UnitZ ); quat[ 3 ] = Quaternion.FromAxes( Vector3.UnitY, Vector3.UnitZ, Vector3.UnitX ); col[ 1 ] = ColorEx.Green; col[ 1 ].a = 0.8f; // z-axis quat[ 4 ] = Quaternion.FromAxes( Vector3.UnitZ, Vector3.UnitY, Vector3.NegativeUnitX ); quat[ 5 ] = Quaternion.FromAxes( Vector3.UnitZ, Vector3.UnitX, Vector3.UnitY ); col[ 2 ] = ColorEx.Blue; col[ 2 ].a = 0.8f; Vector3[] basepos = new Vector3[ 7 ] { // stalk new Vector3(0f, 0.05f, 0f), new Vector3(0f, -0.05f, 0f), new Vector3(0.7f, -0.05f, 0f), new Vector3(0.7f, 0.05f, 0f), // head new Vector3(0.7f, -0.15f, 0f), new Vector3(1f, 0f, 0f), new Vector3(0.7f, 0.15f, 0f) }; // vertices // 6 arrows for ( int i = 0; i < 6; ++i ) { // 7 points for ( int p = 0; p < 7; ++p ) { Vector3 pos = quat[ i ] * basepos[ p ]; mo.Position( pos ); mo.Color( col[ i / 2 ] ); } } // indices // 6 arrows for ( int i = 0; i < 6; ++i ) { ushort baseIndex = (ushort)( i * 7 ); mo.Triangle( (ushort)( baseIndex + 0 ), (ushort)( baseIndex + 1 ), (ushort)( baseIndex + 2 ) ); mo.Triangle( (ushort)( baseIndex + 0 ), (ushort)( baseIndex + 2 ), (ushort)( baseIndex + 3 ) ); mo.Triangle( (ushort)( baseIndex + 4 ), (ushort)( baseIndex + 5 ), (ushort)( baseIndex + 6 ) ); } mo.End(); _mesh = mo.ConvertToMesh( meshName, ResourceGroupManager.InternalResourceGroupName ); } }
/// <summary> /// Add vertex and index sets of a mesh to the builder. /// </summary> /// <param name="mesh">The mesh object.</param> /// <param name="lodIndex">The LOD level to be processed.</param> public void AddObject( Mesh mesh, int lodIndex ) { if ( mesh == null ) throw new ArgumentNullException(); //mesh.AddVertexAndIndexSets(this, lodIndex); //NOTE: The Mesh.AddVertexAndIndexSets() assumes there weren't any vertex data added to the builder yet. //For this class I decided to break that assumption, thus using following replacement for the commented call. //I guess rarely, but still you might want to add vertex/index sets of several objects to one builder. //Maybe AddVertexAndIndexSets could be removed and this method utilized back in Mesh. //TODO: find out whether custom index buffer needs to be created in cases (like in the AddObject(IRenderable)). //Borrilis, do you know? int vertexSetCount = vertexDataList.Count; int indexOfSharedVertexSet = vertexSetCount; if ( mesh.SharedVertexData != null ) { AddVertexData( mesh.SharedVertexData ); vertexSetCount++; } // Prepare the builder using the submesh information for ( int i = 0; i < mesh.SubMeshCount; i++ ) { SubMesh sm = mesh.GetSubMesh( i ); if ( sm.useSharedVertices ) { // Use shared vertex data if ( lodIndex == 0 ) { AddIndexData( sm.IndexData, indexOfSharedVertexSet, sm.OperationType ); } else { AddIndexData( sm.LodFaceList[ lodIndex - 1 ], indexOfSharedVertexSet, sm.OperationType ); } } else { // own vertex data, add it and reference it directly AddVertexData( sm.VertexData ); if ( lodIndex == 0 ) { // base index data AddIndexData( sm.IndexData, vertexSetCount++, sm.OperationType ); } else { // LOD index data AddIndexData( sm.LodFaceList[ lodIndex - 1 ], vertexSetCount++, sm.OperationType ); } } } }
/// <summary> /// /// </summary> private void PrepareClonedMesh() { // create a new mesh based on the original, only with different BufferUsage flags (inside PrepareVertexData) clonedMesh = MeshManager.Instance.CreateManual(MESH_NAME); clonedMesh.BoundingBox = (AxisAlignedBox)originalMesh.BoundingBox.Clone(); clonedMesh.BoundingSphereRadius = originalMesh.BoundingSphereRadius; // clone the actual data clonedMesh.SharedVertexData = PrepareVertexData(originalMesh.SharedVertexData); // clone each sub mesh for(int i = 0; i < originalMesh.SubMeshCount; i++) { SubMesh orgSub = originalMesh.GetSubMesh(i); SubMesh newSub = clonedMesh.CreateSubMesh(string.Format("ClonedSubMesh#{0}", i)); if(orgSub.IsMaterialInitialized) { newSub.MaterialName = orgSub.MaterialName; } // prepare new vertex data newSub.useSharedVertices = orgSub.useSharedVertices; newSub.vertexData = PrepareVertexData(orgSub.vertexData); // use existing index buffer as is since it wont be modified anyway newSub.indexData.indexBuffer = orgSub.indexData.indexBuffer; newSub.indexData.indexStart = orgSub.indexData.indexStart; newSub.indexData.indexCount = orgSub.indexData.indexCount; } }