コード例 #1
0
        //---------------------------------------------------------------
        #endregion
        //---------------------------------------------------------------

        //---------------------------------------------------------------
        #region Methods
        //---------------------------------------------------------------
        /// <summary>
        /// Generates a heightmap from a Bitmap.
        /// </summary>
        /// <param name="bmp">The bitmap to use.</param>
        public Mesh Generate(Bitmap bmp)
        {
            VertexUnit     vertexUnit     = new VertexUnit(VertexFormat.PositionTexture, bmp.Width * bmp.Height);
            PositionStream positionStream = (PositionStream)vertexUnit[typeof(PositionStream)];
            TextureStream  textureStream  = (TextureStream)vertexUnit[typeof(TextureStream)];

            BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            byte[] data = new byte[bitmapData.Stride * bitmapData.Height];
            System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, data, 0, data.Length);
            int     quadsX = bmp.Width - 1;
            int     quadsY = bmp.Height - 1;
            Vector3 scale  = new Vector3(0.1f, 0.02f, 0.1f);

            //Vector3 scale = new Vector3(5.0f, 0.1f, 5.0f);
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    int  byteOffset = x * 4 + y * bitmapData.Stride;
                    byte b          = data[byteOffset];
                    byte g          = data[byteOffset + 1];
                    byte r          = data[byteOffset + 2];
                    byte a          = data[byteOffset + 3];

                    Vector3 vec = Vector3.Scale(new Vector3(x - quadsX * 0.5f, r, -y + quadsY * 0.5f), scale);
                    positionStream[x + y * bmp.Width] = vec;

                    Vector2 texVec = new Vector2((float)x / quadsX, (float)y / quadsY);
                    textureStream[x + y * bmp.Width] = texVec;
                }
            }
            bmp.UnlockBits(bitmapData);

            IndexStream indexStream = IndexStream.Create(quadsX * quadsY * 6, (quadsX + 1) * (quadsY + 1));
            int         offset      = 0;

            for (int y = 0; y < quadsY; y++)
            {
                for (int x = 0; x < quadsX; x++)
                {
                    indexStream[offset]     = (x + y * bmp.Width);
                    indexStream[offset + 1] = (x + 1 + y * bmp.Width);
                    indexStream[offset + 2] = (x + (y + 1) * bmp.Width);
                    indexStream[offset + 3] = (x + 1 + y * bmp.Width);
                    indexStream[offset + 4] = (x + 1 + (y + 1) * bmp.Width);
                    indexStream[offset + 5] = (x + (y + 1) * bmp.Width);
                    offset += 6;
                }
            }

            Mesh mesh = new Mesh();

            mesh.SubSets.Add(new SubSet(vertexUnit, indexStream));
            return(mesh);
        }
コード例 #2
0
        /// <summary>
        /// Merges two subsets.
        /// </summary>
        /// <param name="subSet">Subset to merge with.</param>
        public void Merge(SubSet subSet)
        {
            if (!CanMerge(subSet))
            {
                throw new GraphicsException("Subsets can't be merged!");
            }

            // Merge vertex unit
            VertexUnit unit = new VertexUnit(VertexUnit.Format, VertexUnit.Size + subSet.VertexUnit.Size);

            VertexUnit.Copy(VertexUnit, 0, unit, 0, VertexUnit.Size);
            VertexUnit.Copy(subSet.VertexUnit, 0, unit, VertexUnit.Size, subSet.VertexUnit.Size);

            VertexUnit.Dispose();
            VertexUnit = unit;

            // Merge index streams
            IndexStream index = IndexStream.Create(IndexStream.Size + subSet.IndexStream.Size, IndexStream.GetType());

            VertexStreams.IndexStream.Copy(IndexStream, 0, index, 0, IndexStream.Size, 0);
            VertexStreams.IndexStream.Copy(subSet.IndexStream, 0, index, IndexStream.Size, subSet.IndexStream.Size, VertexUnit.Size);
            IndexStream.Dispose();
            IndexStream = index;
        }
コード例 #3
0
        //---------------------------------------------------------------
        #endregion
        //---------------------------------------------------------------

        //---------------------------------------------------------------
        #region Methods
        //---------------------------------------------------------------
        private void UpdateMetaInfo()
        {
            faceNormals       = new Vector3[mesh.SubSets.Count][];
            backface          = new bool[mesh.SubSets.Count][];
            edges             = new Edge[mesh.SubSets.Count][];
            this.shadowVolume = new Mesh();

            int maxIndex = 0;

            for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++)
            {
                maxIndex = System.Math.Min(mesh.SubSets[iSubSet].VertexUnit.Size, maxIndex);
            }
            indexStream = IndexStream.Create(1024 * 16, maxIndex);

            for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++)
            {
                SubSet subSet = mesh.SubSets[iSubSet];
                faceNormals[iSubSet] = subSet.CalcFaceNormals();
                backface[iSubSet]    = new bool[subSet.PrimitiveCount];
                edges[iSubSet]       = subSet.CalcEdges();
                shadowVolume.SubSets.Add(new SubSet(subSet.VertexUnit, indexStream));
            }
        }
コード例 #4
0
        /// <summary>
        /// Import a mesh from a stream.
        /// </summary>
        /// <param name="stream">Stream containing mesh data.</param>
        public void Import(Stream stream)
        {
            Profiler.Instance.Begin("Import binary mesh");
            // Header
            BinaryReader reader = new BinaryReader(stream);

            if (ReadString(reader) != "mesh" || ReadString(reader) != "v0.3")
            {
                throw new NotSupportedException("Can't load mesh, file not supported!");
            }

            // Joints
            int jointNum = ReadInt(reader);

            Joint[]   joints     = new Joint[jointNum];
            Matrix4[] jointArray = new Matrix4[jointNum];
            Hashtable jointTable = new Hashtable(joints.Length);

            for (int i = 0; i < joints.Length; i++)
            {
                string name   = ReadString(reader);
                string parent = ReadString(reader);

                reader.Read(matrixBytes, 0, matrixBytes.Length);
                Matrix4 m = Matrix4.From(matrixBytes);

                Joint parentJoint = null;
                if (parent != null && jointTable.Contains(parent))
                {
                    parentJoint = (Joint)jointTable[parent];
                }
                joints[i]        = new Joint(name, i, parentJoint);
                jointArray[i]    = m;
                jointTable[name] = joints[i];
            }
            skeleton = new Skeleton(jointArray, joints);

            // SubSet
            int subSetNum = ReadInt(reader);

            for (int i = 0; i < subSetNum; i++)
            {
                ArrayList streams = new ArrayList(10);
                // Header
                if (ReadString(reader) != "subset")
                {
                    throw new NotSupportedException("Error on loading subSet!");
                }
                string name        = ReadString(reader);
                string parentJoint = ReadString(reader);

                int attributeCount          = ReadInt(reader);
                StringDictionary attributes = new StringDictionary();
                for (int t = 0; t < attributeCount; t++)
                {
                    attributes.Add(ReadString(reader), ReadString(reader));
                }

                // IndexStream
                // Todo Replace ushort.MaxValue with size of vertex unit
                IndexStream indexStream = IndexStream.Create(ReadInt(reader), ushort.MaxValue);
                byte[]      indexBuffer = new byte[indexStream.Size * 4];
                reader.Read(indexBuffer, 0, indexStream.Size * 4);
                for (int t = 0; t < indexStream.Size; t++)
                {
                    indexStream[t] = BitConverter.ToInt32(indexBuffer, t * 4);
                }

                int            vertexSize = ReadInt(reader);
                PositionStream posStream  = new PositionStream(vertexSize);
                streams.Add(posStream);
                byte[] vertexBuffer = new byte[vertexSize * 12];
                reader.Read(vertexBuffer, 0, vertexSize * 12);
                for (int t = 0; t < vertexSize; t++)
                {
                    posStream[t] = Vector3.From(vertexBuffer, 12 * t);
                }

                NormalStream normalStream = new NormalStream(vertexSize);
                streams.Add(normalStream);
                reader.Read(vertexBuffer, 0, vertexSize * 12);
                for (int t = 0; t < vertexSize; t++)
                {
                    normalStream[t] = Vector3.From(vertexBuffer, t * 12);
                }

                ColorStream colorStream = new ColorStream(vertexSize);
                streams.Add(colorStream);
                reader.Read(vertexBuffer, 0, vertexSize * 12);
                for (int t = 0; t < vertexSize; t++)
                {
                    int r = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, t * 12) * 255 + 0.5f), 0, 255);
                    int g = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, 4 + t * 12) * 255 + 0.5f), 0, 255);
                    int b = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, 8 + t * 12) * 255 + 0.5f), 0, 255);
                    colorStream[t] = System.Drawing.Color.FromArgb(r, g, b).ToArgb();
                }

                TextureStream[] textureStreams = new TextureStream[ReadInt(reader)];
                for (int t = 0; t < textureStreams.Length; t++)
                {
                    TextureStream texStream = new TextureStream(vertexSize);
                    streams.Add(texStream);
                    reader.Read(vertexBuffer, 0, vertexSize * 8);
                    for (int j = 0; j < vertexSize; j++)
                    {
                        texStream[j] = Vector2.From(vertexBuffer, j * 8);
                    }
                    textureStreams[t] = texStream;
                }

                IBoneIndicesStream boneStream    = null;
                IBoneWeightsStream weightsStream = null;
                int weightNum = ReadInt(reader);
                if (weightNum != 0)
                {
                    if (HardwareSkinning)
                    {
                        boneStream    = new BoneIndicesStream(vertexSize);
                        weightsStream = new BoneWeightsStream(vertexSize);
                    }
                    else
                    {
                        boneStream    = new SoftwareBoneIndicesStream(vertexSize);
                        weightsStream = new SoftwareBoneWeightsStream(vertexSize);
                    }
                    streams.Add(boneStream);
                    streams.Add(weightsStream);
                    ArrayList[] indicesList = new ArrayList[vertexSize];
                    ArrayList[] weightsList = new ArrayList[vertexSize];
                    for (int t = 0; t < vertexSize; t++)
                    {
                        indicesList[t] = new ArrayList(8);
                        weightsList[t] = new ArrayList(8);
                    }


                    byte[] weightBuffer = new byte[weightNum * 12];
                    reader.Read(weightBuffer, 0, weightNum * 12);
                    for (int t = 0; t < weightNum; t++)
                    {
                        int   vertexIndex = BitConverter.ToInt32(weightBuffer, t * 12);
                        int   jointIndex  = BitConverter.ToInt32(weightBuffer, 4 + t * 12);
                        float weight      = BitConverter.ToSingle(weightBuffer, 8 + t * 12);
                        indicesList[vertexIndex].Add((byte)jointIndex);
                        weightsList[vertexIndex].Add(weight);
                    }

                    for (int t = 0; t < vertexSize; t++)
                    {
                        boneStream.SetIndices(t, (byte[])indicesList[t].ToArray(typeof(byte)));
                        weightsStream.SetWeights(t, (float[])weightsList[t].ToArray(typeof(float)));
                    }
                }

                VertexUnit vertexUnit = new VertexUnit(streams);
                Mesh       mesh       = new Mesh(new SubSet(vertexUnit, indexStream));
                if (model == null)
                {
                    if (skeleton.Joints.Length != 0)
                    {
                        model = new Model(new SkinnedMesh(mesh, skeleton), skeleton);
                    }
                    else
                    {
                        model = new Model(mesh, skeleton);
                    }
                }
                else
                {
                    Joint attachTo = skeleton.RootJoint;
                    if (parentJoint != "")
                    {
                        attachTo = (jointTable[parentJoint] as Joint);
                    }
                    model.AttachModel(new Model(mesh, skeleton), attachTo);
                }
            }
            reader.Close();

            Profiler.Instance.End("Import binary mesh");
        }
コード例 #5
0
        /// <summary>
        /// loads a quake3 level from a stream
        /// </summary>
        /// <param name="stream">stream to load from</param>
        /// <returns>level as a mesh</returns>
        public Mesh Load(Stream stream)
        {
            Mesh mesh = new Mesh();

            this.stream = stream;

            // get header and check if it is ok
            QuakeHeader header = (QuakeHeader)RawSerializer.Deserialize(stream, typeof(QuakeHeader));

            if (header.ID != 1347633737 || header.Version != 0x2e)
            {
                return(null);
            }

            // get locations of lumps
            locations = RawSerializer.DeserializeArray(stream, typeof(LumpLocation), (int)QuakeLumps.LumpNumber);

            // get lumps
            IList quakeVertices  = LoadLump(QuakeLumps.Vertices, typeof(QuakeVertex));
            IList quakeFaces     = LoadLump(QuakeLumps.Faces, typeof(QuakeFace));
            IList quakeTextures  = LoadLump(QuakeLumps.Textures, typeof(QuakeTexture));
            IList quakeLightMaps = LoadLump(QuakeLumps.Lightmaps, typeof(QuakeLightMap));


            // Load all texture images and put into array
            IList textures = LoadTextures(quakeTextures);
            // Load lightMaps, create texture and put into array
            IList lightMaps = LoadLightMaps(quakeLightMaps);

            // create list from vertices
            VertexUnit     vertexUnit = new VertexUnit(VertexFormat.PositionTexture2, quakeVertices.Count);
            PositionStream pos        = (PositionStream)vertexUnit[typeof(PositionStream)];
            TextureStream  texStream  = (TextureStream)vertexUnit[typeof(TextureStream)];
            TextureStream  light      = (TextureStream)vertexUnit[typeof(TextureStream), 1];

            int i = 0;

            foreach (QuakeVertex v in quakeVertices)
            {
                pos[i]       = new Math.Vector3(v.Position[0], v.Position[2], -v.Position[1]);
                texStream[i] = new Math.Vector2(v.TextureCoord[0], v.TextureCoord[1]);
                light[i]     = new Math.Vector2(v.LightmapCoord[0], v.LightmapCoord[1]);
                i++;
            }

            // presort faces
            Array.Sort(((Array)quakeFaces));

            // create mesh
            int       oldLightMap = ((QuakeFace)quakeFaces[0]).LightmapID;
            int       oldTexture  = ((QuakeFace)quakeFaces[0]).TextureID;
            ArrayList indices     = new ArrayList();

            for (i = 0; i < quakeFaces.Count; ++i)
            {
                QuakeFace qf = (QuakeFace)quakeFaces[i];
                if (qf.Type == 1)
                {
                    if (qf.TextureID != oldTexture || qf.LightmapID != oldLightMap)
                    {
                        mesh.SubSets.Add(new SubSet(vertexUnit, IndexStream.Create(indices, vertexUnit.Size)));
                        Textures texs = new Textures("color", (ITexture)textures[oldTexture]);
                        if (oldLightMap == -1)
                        {
                            texs["lightMap"] = null;
                        }
                        else
                        {
                            texs["lightMap"] = (ITexture)lightMaps[oldLightMap];
                        }
                        mesh.Textures.Add(texs);
                        indices.Clear();
                    }

                    // add indices => convert from fan to list
                    for (int j = 2; j < qf.NumOfVerts; j++)
                    {
                        indices.Add(qf.VertexIndex);
                        indices.Add(qf.VertexIndex + j - 1);
                        indices.Add(qf.VertexIndex + j);
                    }

                    oldTexture  = qf.TextureID;
                    oldLightMap = qf.LightmapID;
                }
            }
            return(mesh);
        }