// TODO: Render with effect /// <summary>Compute a bounding sphere for this mesh</summary> public float ComputeBoundingSphere(out Vector3 center) { if (systemMemoryMesh == null) { throw new InvalidOperationException("There is no system memory mesh. Nothing to do here."); } // Get the object declaration int strideSize = VertexInformation.GetFormatSize(systemMemoryMesh.VertexFormat); // Lock the vertex buffer GraphicsStream data = null; try { data = systemMemoryMesh.LockVertexBuffer(LockFlags.ReadOnly); // Now compute the bounding sphere return(Geometry.ComputeBoundingSphere(data, systemMemoryMesh.NumberVertices, systemMemoryMesh.VertexFormat, out center)); } finally { // Make sure to unlock the vertex buffer if (data != null) { systemMemoryMesh.UnlockVertexBuffer(); } } }
/// <summary> /// Called once per frame, the call is the entry point for 3d rendering. This /// function sets up render states, clears the viewport, and renders the scene. /// </summary> protected override void Render() { //Clear the backbuffer to a black color device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); //Begin the scene device.BeginScene(); device.VertexFormat = CustomVertex.PositionNormalColored.Format; // set the vertexbuffer stream source device.SetStreamSource(0, vertexBuffer, 0, VertexInformation.GetFormatSize(CustomVertex.PositionNormalColored.Format)); // set fill mode device.RenderState.FillMode = FillMode.Solid; // set the indices device.Indices = indexBuffer; //use the indices buffer device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, bufferSize * bufferSize, 0, vert_size / 3); // Output statistics drawingFont.DrawText(2, 1, System.Drawing.Color.Yellow, frameStats); drawingFont.DrawText(2, 20, System.Drawing.Color.Yellow, deviceStats); drawingFont.DrawText(2, 40, System.Drawing.Color.White, "Hit 'F' to generate new fractal."); device.EndScene(); }
private void DrawEnvironment() { /*if ( RteEnabled ) { * if ( envPolysIndices [0] == null ) { * for ( int i = 0 ; i < 6 ; i++ ) * CreatePoly ( out envPolysIndices [0], out envPolysVertices [0] ); * } * * lastTextureId = -1; * lastLightmapId = -1; * ibNeedSet = true; * bezierIbNeedSet = true; * * d3dDevice.SetTextureStageState ( 0, TextureStageStates.TextureCoordinateIndex, ( int ) TextureCoordinateIndex.PassThru ); * d3dDevice.SetTextureStageState ( 1, TextureStageStates.ColorOperation, ( int ) TextureOperation.Disable ); * d3dDevice.SetTransform ( TransformType.View , fpsCamera.ViewMatrix ); * d3dDevice.SetTransform ( TransformType.Projection, fpsCamera.ProjMatrix ); * * for ( int i = 0 ; i < 1 ; i++ ) { * d3dDevice.SetTransform ( TransformType.World, Matrix.Translation ( fpsCamera.Position + fpsCamera.Look * 5 + fpsCamera.Right * 2 - fpsCamera.Up ) ); * d3dDevice.DrawIndexedPrimitives ( PrimitiveType.TriangleList, 0, 0, 4, 0, 2 ); * } * }*/ if (RteEnabled) { using (Mesh teapot = Mesh.Sphere(d3dDevice, 2.0f, 16, 16)) { lastTextureId = -1; lastLightmapId = -1; d3dDevice.SetTexture(0, cubeTexture); d3dDevice.SetTextureStageState(0, TextureStageStates.TextureCoordinateIndex, ( int )TextureCoordinateIndex.SphereMap); d3dDevice.SetTextureStageState(0, TextureStageStates.ColorOperation, ( int )TextureOperation.SelectArg1); d3dDevice.SetTextureStageState(0, TextureStageStates.ColorArgument1, ( int )TextureArgument.TextureColor); /*d3dDevice.SetTextureStageState ( 0, TextureStageStates.TextureTransform, ( int ) TextureTransform.Count3 ); * d3dDevice.SamplerState [0].AddressU = TextureAddress.Clamp; * d3dDevice.SamplerState [0].AddressV = TextureAddress.Clamp; * d3dDevice.SamplerState [0].AddressW = TextureAddress.Clamp;*/ d3dDevice.SetTextureStageState(1, TextureStageStates.ColorOperation, ( int )TextureOperation.Disable); d3dDevice.Transform.World = Matrix.Scaling(10.0f, 10.0f, 10.0f) * Matrix.Translation(teapotPos); d3dDevice.Transform.View = fpsCamera.ViewMatrix; d3dDevice.Transform.Projection = fpsCamera.ProjMatrix; using (VertexBuffer vb = teapot.VertexBuffer) { using (IndexBuffer ib = teapot.IndexBuffer) { ibNeedSet = true; bezierIbNeedSet = true; d3dDevice.VertexFormat = teapot.VertexFormat; d3dDevice.SetStreamSource(0, vb, 0, VertexInformation.GetFormatSize(teapot.VertexFormat)); d3dDevice.Indices = ib; d3dDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, teapot.NumberVertices, 0, teapot.NumberFaces); //teapot.DrawSubset ( 0 ); } } } } }
/// <summary> /// Renders 3D text /// </summary> public void Render3DText(string text, RenderFlags flags) { if (device == null) { throw new System.ArgumentNullException(); } // Set up renderstate savedStateBlock.Capture(); drawTextStateBlock.Apply(); device.VertexFormat = CustomVertex.PositionNormalTextured.Format; device.PixelShader = null; device.SetStreamSource(0, vertexBuffer, 0, VertexInformation.GetFormatSize(CustomVertex.PositionNormalTextured.Format)); // Set filter states if ((flags & RenderFlags.Filtered) != 0) { samplerState0.MinFilter = TextureFilter.Linear; samplerState0.MagFilter = TextureFilter.Linear; } // Position for each text element float x = 0.0f; float y = 0.0f; // Center the text block at the origin if ((flags & RenderFlags.Centered) != 0) { System.Drawing.SizeF sz = GetTextExtent(text); x = -(((float)sz.Width) / 10.0f) / 2.0f; y = -(((float)sz.Height) / 10.0f) / 2.0f; } // Turn off culling for two-sided text if ((flags & RenderFlags.TwoSided) != 0) { renderState.CullMode = Cull.None; } // Adjust for character spacing x -= spacingPerChar / 10.0f; float fStartX = x; // Fill vertex buffer GraphicsStream strm = vertexBuffer.Lock(0, 0, LockFlags.Discard); int numTriangles = 0; foreach (char c in text) { if (c == '\n') { x = fStartX; y -= (textureCoords[0, 3] - textureCoords[0, 1]) * textureHeight / 10.0f; } if ((c - 32) < 0 || (c - 32) >= 128 - 32) { continue; } float tx1 = textureCoords[c - 32, 0]; float ty1 = textureCoords[c - 32, 1]; float tx2 = textureCoords[c - 32, 2]; float ty2 = textureCoords[c - 32, 3]; float w = (tx2 - tx1) * textureWidth / (10.0f * textureScale); float h = (ty2 - ty1) * textureHeight / (10.0f * textureScale); if (c != ' ') { strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + 0, 0), new Vector3(0, 0, -1), tx1, ty2)); strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + h, 0), new Vector3(0, 0, -1), tx1, ty1)); strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + 0, 0), new Vector3(0, 0, -1), tx2, ty2)); strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + h, 0), new Vector3(0, 0, -1), tx2, ty1)); strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + 0, 0), new Vector3(0, 0, -1), tx2, ty2)); strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + h, 0), new Vector3(0, 0, -1), tx1, ty1)); numTriangles += 2; if (numTriangles * 3 > (MaxNumfontVertices - 6)) { // Unlock, render, and relock the vertex buffer vertexBuffer.Unlock(); device.DrawPrimitives(PrimitiveType.TriangleList, 0, numTriangles); strm = vertexBuffer.Lock(0, 0, LockFlags.Discard); numTriangles = 0; } } x += w - (2 * spacingPerChar) / 10.0f; } // Unlock and render the vertex buffer vertexBuffer.Unlock(); if (numTriangles > 0) { device.DrawPrimitives(PrimitiveType.TriangleList, 0, numTriangles); } // Restore the modified renderstates savedStateBlock.Apply(); }
/// <summary> /// Saves a mesh to the custom serialized format /// </summary> /// <param name="stream">The stream to which to serialize</param> /// <param name="mesh">The mesh to be serialized</param> /// <param name="materials">The materials for subparts of the mesh /// </param> /// <param name="textures">The filenames for the textures on /// subparts of the mesh</param> public static void SaveMesh(Stream stream, Mesh mesh, Material [] materials, string [] textures) { int flexibleVertexFormat; int numberVertices; byte [] vertices; int numberIndices; byte [] indices; AttributeRange [] attributeRanges; VertexFormats sourceVertexFormat; VertexFormats sourceFormat; IDisposable tempMesh; tempMesh = null; try { // Managed Direct3D mobile uses different Fvf defines than // managed Direct3D for the desktop // when this code is linked against the desktop version // this will convert the Fvf to match MD3DM constants // when this code is linked against MD3DM this section will // not have changed anything. // determine the necessary Fvf sourceVertexFormat = mesh.VertexFormat; int textureCount; sourceFormat = VertexFormats.Position; flexibleVertexFormat = 0; if ((sourceVertexFormat & VertexFormats.Normal) != 0) { flexibleVertexFormat |= md3dmFvfNormal; sourceFormat |= VertexFormats.Normal; } if ((sourceVertexFormat & VertexFormats.Diffuse) != 0) { flexibleVertexFormat |= md3dmFvfDiffuse; sourceFormat |= VertexFormats.Diffuse; } if ((sourceVertexFormat & VertexFormats.Specular) != 0) { flexibleVertexFormat |= md3dmFvfDiffuse; sourceFormat |= VertexFormats.Specular; } // determine number of textures textureCount = (int)(sourceVertexFormat & VertexFormats.TextureCountMask) >> (int)VertexFormats.TextureCountShift; //limit to 4 textures if (textureCount > 4) { textureCount = 4; } // continue setting up necessary fvf sourceFormat |= (VertexFormats)(textureCount << (int)VertexFormats.TextureCountShift); flexibleVertexFormat |= (textureCount << md3dmFvfTextureCountShift); if (sourceFormat != sourceVertexFormat) { mesh = mesh.Clone(mesh.Options.Value, sourceFormat, mesh.Device); tempMesh = (IDisposable)mesh; } attributeRanges = mesh.GetAttributeTable(); if (attributeRanges == null) { throw new MeshSerializationException( "No Attribute table present"); } // determine number of vertices and create buffer numberVertices = mesh.NumberVertices; vertices = new byte[numberVertices * VertexInformation.GetFormatSize(sourceFormat)]; // copy vertices to buffer mesh.VertexBuffer.Lock(0, vertices.Length, LockFlags.None).Read(vertices, 0, vertices.Length); mesh.VertexBuffer.Unlock(); // determine number of indices numberIndices = mesh.NumberFaces * 3; // create index data buffer indices = new byte[numberIndices * (mesh.Options.Use32Bit ? 4 : 2)]; // fill index data into buffer mesh.IndexBuffer.Lock(0, indices.Length, LockFlags.None).Read(indices, 0, indices.Length); mesh.IndexBuffer.Unlock(); // write the data out to file MeshLoader.SaveMeshData(stream, flexibleVertexFormat, numberVertices, vertices, numberIndices, indices, attributeRanges, materials, textures); } finally { if (tempMesh != null) { tempMesh.Dispose(); } } }
/// <summary> /// Loads a mesh from the given stream /// </summary> /// <param name="device">A d3d mobile device which will be displaying /// the mesh</param> /// <param name="stream">The stream containing serialized mesh data /// </param> /// <param name="flags">Option flags</param> /// <param name="materials">Output array is filled with any needed /// materials</param> /// <param name="textures">Output array is filled with the filenames /// of any needed textures</param> /// <returns></returns> public static Mesh LoadMesh(Device device, Stream stream, MeshFlags flags, out Material [] materials, out string [] textures) { if (device == null) { throw new ArgumentException("Argument device was invalid"); } if (stream == null) { throw new ArgumentException("Argument stream was invalid"); } byte [] rgb; byte [] rgbIb; byte [] rgbVb; Mesh meshRet; VertexBuffer vb; IndexBuffer ib; int fileMagicNumber; int fileVersion; VertexFormats flexibleVertexFormat; int numberVertices; int numberIndices; int is16BitIndices; int numberMaterials; int numberAttrRanges; int offsetVertex; int offsetIndices; int offsetAttrRange; int offsetMaterial; int bytesMaterials; int bytesIndices; int [] attributeTable; AttributeRange [] attributeRanges; rgb = new byte [512]; stream.Seek(0, SeekOrigin.Begin); // Read header, any errors will be propagated up stream.Read(rgb, 0, sizeofHeader); // read and verify magic number fileMagicNumber = BitConverter.ToInt32(rgb, 0); if (fileMagicNumber != magicNumber) { throw new MeshSerializationException( "The serialized data does not represent a mesh"); } // read and verify version fileVersion = BitConverter.ToInt32(rgb, 4); if (fileVersion != versionNumber) { throw new MeshSerializationException( "The format version was not recognized"); } flexibleVertexFormat = (VertexFormats) BitConverter.ToInt32(rgb, 8); numberVertices = BitConverter.ToInt32(rgb, 12); numberIndices = BitConverter.ToInt32(rgb, 16); is16BitIndices = BitConverter.ToInt32(rgb, 20); numberMaterials = BitConverter.ToInt32(rgb, 24); numberAttrRanges = BitConverter.ToInt32(rgb, 28); offsetVertex = BitConverter.ToInt32(rgb, 32); offsetIndices = BitConverter.ToInt32(rgb, 36); offsetAttrRange = BitConverter.ToInt32(rgb, 40); offsetMaterial = BitConverter.ToInt32(rgb, 44); bytesMaterials = BitConverter.ToInt32(rgb, 48); // verify number of vertices if (numberVertices < 0) { throw new MeshSerializationException( String.Format(CultureInfo.InvariantCulture, "Invalid number of vertices: {0}", numberVertices)); } // verify number of indices if (numberIndices < 0 || numberIndices % 3 != 0) { throw new MeshSerializationException( String.Format(CultureInfo.InvariantCulture, "Invalid number of indices: {0}", numberIndices)); } // verify number of materials if (numberMaterials < 0) { throw new MeshSerializationException( String.Format(CultureInfo.InvariantCulture, "Invalid number of materials: {0}", numberMaterials)); } // verify number of attribute ranges if (numberAttrRanges < 0) { throw new MeshSerializationException( String.Format(CultureInfo.InvariantCulture, "Invalid number of attribute ranges: {0}", numberAttrRanges)); } // determine number of index bytes and verify Is16BitIndices if (is16BitIndices == 1) { bytesIndices = numberIndices * 2; } else if (is16BitIndices == 0) { bytesIndices = numberIndices * 4; } else { throw new MeshSerializationException( String.Format(CultureInfo.InvariantCulture, "Invalid value for is16BitIndices: {0}", is16BitIndices)); } // Managed Direct3D mobile uses different Fvf defines than // managed Direct3D for the desktop // when this code is linked against the desktop version // this will convert the Fvf to match MD3DM constants // when this code is linked against MD3DM this section will // not have changed anything. // determine the necessary Fvf int sourceFormat = (int)flexibleVertexFormat; int textureCount; flexibleVertexFormat = VertexFormats.Position; if ((sourceFormat & md3dmFvfNormal) != 0) { flexibleVertexFormat |= VertexFormats.Normal; } if ((sourceFormat & md3dmFvfDiffuse) != 0) { flexibleVertexFormat |= VertexFormats.Diffuse; } if ((sourceFormat & md3dmFvfSpecular) != 0) { flexibleVertexFormat |= VertexFormats.Specular; } // determine number of textures textureCount = (sourceFormat & (int)VertexFormats.TextureCountMask) >> (int)md3dmFvfTextureCountShift; //limit to 4 textures if (textureCount > 4) { textureCount = 4; } // continue setting up necessary Fvf flexibleVertexFormat |= (VertexFormats)( textureCount << (int)VertexFormats.TextureCountShift); int bytesVertices = VertexInformation.GetFormatSize(flexibleVertexFormat) * numberVertices; // Verify none of the data regions overlap // the material section is variable size so we can't check // that one yet if (!((offsetVertex >= sizeofHeader) && (offsetIndices >= offsetVertex + bytesVertices) && (offsetAttrRange >= offsetIndices + bytesIndices) && (offsetMaterial >= offsetAttrRange + numberAttrRanges * sizeofAttributeRange) && (stream.Length >= offsetMaterial + bytesMaterials))) { throw new MeshSerializationException( "The data regions are not " + "within the stream or overlap"); } // create our data tables materials = new Material[numberMaterials]; textures = new string[numberMaterials]; attributeRanges = new AttributeRange[numberAttrRanges]; attributeTable = new int[numberIndices / 3]; // move to the attribute range section, propagate up // any exception stream.Seek(offsetAttrRange, SeekOrigin.Begin); // parse attribute ranges for (int i = 0; i < numberAttrRanges; i++) { int attribId; int faceStart; int faceCount; int vertexStart; int vertexCount; // read in the attribute range data stream.Read(rgb, 0, sizeofAttributeRange); attribId = BitConverter.ToInt32(rgb, 0); faceStart = BitConverter.ToInt32(rgb, 4); faceCount = BitConverter.ToInt32(rgb, 8); vertexStart = BitConverter.ToInt32(rgb, 12); vertexCount = BitConverter.ToInt32(rgb, 16); // verify the data if ((vertexStart < 0 || vertexCount < 0 || vertexStart + vertexCount > numberVertices) || (faceStart < 0 || faceCount < 0 || (faceStart + faceCount) * 3 > numberIndices)) { throw new ApplicationException( "Invalid attribute range"); } // store the validated data attributeRanges[i].AttributeId = attribId; attributeRanges[i].FaceStart = faceStart; attributeRanges[i].FaceCount = faceCount; attributeRanges[i].VertexStart = vertexStart; attributeRanges[i].VertexCount = vertexCount; for (int j = faceStart; j < faceStart + faceCount; j++) { attributeTable[j] = attribId; } } // move to the material section stream.Seek(offsetMaterial, SeekOrigin.Begin); // parse materials for (int i = 0; i < numberMaterials; i++) { int cbTexture; // verify that we aren't reading past the end of the stream // its possible an invalid filename length the if (stream.Position + sizeofMaterial > stream.Length) { throw new MeshSerializationException( "Material data region is" + " corrupt"); } // read in the material color data stream.Read(rgb, 0, sizeofMaterial); materials[i].DiffuseColor = new ColorValue( BitConverter.ToSingle(rgb, 0), BitConverter.ToSingle(rgb, 4), BitConverter.ToSingle(rgb, 8), BitConverter.ToSingle(rgb, 12)); materials[i].AmbientColor = new ColorValue( BitConverter.ToSingle(rgb, 16), BitConverter.ToSingle(rgb, 20), BitConverter.ToSingle(rgb, 24), BitConverter.ToSingle(rgb, 28)); materials[i].SpecularColor = new ColorValue( BitConverter.ToSingle(rgb, 32), BitConverter.ToSingle(rgb, 36), BitConverter.ToSingle(rgb, 40), BitConverter.ToSingle(rgb, 44)); materials[i].SpecularSharpness = BitConverter.ToSingle(rgb, 48); // read in the size of the texture filename cbTexture = BitConverter.ToInt32(rgb, 52); // verify that the texture filename has a valid length if (cbTexture < 0 || stream.Position + cbTexture > stream.Length) { throw new MeshSerializationException( "Material data region is corrupt"); } // read the texture filename if (cbTexture > 0) { stream.Read(rgb, 0, cbTexture); textures[i] = Encoding.Unicode.GetString(rgb, 0, cbTexture); } } // create data buffers rgbIb = new byte[bytesIndices]; rgbVb = new byte[bytesVertices]; // read in the index data stream.Seek(offsetIndices, SeekOrigin.Begin); stream.Read(rgbIb, 0, rgbIb.Length); // read in the vertex data stream.Seek(offsetVertex, SeekOrigin.Begin); stream.Read(rgbVb, 0, rgbVb.Length); // set the use 32 bit flag appropriately flags = (flags & ~(MeshFlags.Use32Bit)) | ((is16BitIndices == 0) ? MeshFlags.Use32Bit : 0); // create a new empty mesh meshRet = new Mesh(numberIndices / 3, numberVertices, flags, flexibleVertexFormat, device); try { // create the index and vertex buffer vb = meshRet.VertexBuffer; ib = meshRet.IndexBuffer; // write the vertex data vb.Lock(0, bytesVertices, LockFlags.None).Write(rgbVb, 0, bytesVertices); vb.Unlock(); // write the index data ib.Lock(0, rgbIb.Length, LockFlags.None).Write(rgbIb, 0, rgbIb.Length); ib.Unlock(); // set the attributes meshRet.LockAttributeBuffer(LockFlags.None); meshRet.UnlockAttributeBuffer(attributeTable); meshRet.SetAttributeTable(attributeRanges); } catch (DirectXException e) { // release the mesh if anything went wrong meshRet.Dispose(); meshRet = null; throw e; } return(meshRet); }