Example #1
0
        /// <summary>
        ///This function should be called after all the vertices and polygons for each object
        ///have been written to the file. The function updates the following information:
        ///The main chunk length
        ///The 3D editor chunk length
        ///The object chunk length
        ///The triangular mesh chunk length
        ///The vertices chunk length
        ///The number of vertices
        ///The polygons chunk length
        ///The number of polygons
        ///Texture information
        /// </summary>
        public void MakeFinalUpdates()
        {
            //Copy the polygon data from the temp file to the main file
            _polygonDataHandler.CopyPlgnData(ref _writer);

            //Write the material information for all the objects
            var faceMaterialChunkLength = MaterialChunkWriter.GetMaterialListChunkLength(_polygonDataHandler.PolygonCount);

            MaterialChunkWriter.WriteMatInformationForObjFaces(_polygonDataHandler.PolygonCount, faceMaterialChunkLength, _writer);

            //Copy the texture data (u,v) values from the temp file to the main file
            //Store the length of the texture chunk in a variable before it is reset in the below call
            var texCoodChunkLength = 0;

            if (_texCoordinatesHandler.DoesTextureValueExist())
            {
                texCoodChunkLength = _texCoordinatesHandler.MappingCoodChunkLength();
                _texCoordinatesHandler.CopyTexCoodData(ref _writer, _polygonDataHandler.PolygonCount);
            }

            //Calculate the length of the vertices list chunk
            var vertChnkLen = (2 + (VertexCount * 3 * sizeof(float)) + 6); //6 for the usual header length
            //The first two bytes are for the quantity value written after the vertices header

            //Calculate the length of the polygons chunk (faces chunk)
            var polsChnkLen = (6 + 2 + (_polygonDataHandler.PolygonCount * 4 * 2) + faceMaterialChunkLength);
            //6 for the usual header length

            //Calculate the length of the triangular mesh chunk
            var meshChnkLen = 6 + vertChnkLen + polsChnkLen + texCoodChunkLength; //Header + sub-chunks

            //Calculate the length of the object block chunk
            var objChnkLen = 6 + ObjNameLen + meshChnkLen; //6 for header

            var prevLen = _writer.BaseStream.Length - objChnkLen;

            //Update the object chunk length
            var offset = (int)(prevLen + 2);  //2 because the chunk length is stored after the chunk id

            _writer.Seek(offset, SeekOrigin.Begin);
            _writer.Write(objChnkLen);

            //Object name is stored at this position in the object chunk

            //Update the triangular mesh chunk length
            offset += 6 + ObjNameLen;
            _writer.Seek(offset, SeekOrigin.Begin);
            _writer.Write(meshChnkLen);

            //Update the vertices chunk length
            offset += 6;
            _writer.Seek(offset, SeekOrigin.Begin);
            _writer.Write(vertChnkLen);
            //Update the number of vertices
            _writer.Write(VertexCount);

            //Update the polygon chunk length
            offset += vertChnkLen;
            _writer.Seek(offset, SeekOrigin.Begin);
            _writer.Write(polsChnkLen);

            //Update the number of polygons
            _writer.Write(_polygonDataHandler.PolygonCount);

            _polygonDataHandler    = null;
            _texCoordinatesHandler = null;
        }
Example #2
0
        public static void ExportTo3DS(string filePath, GeometryModel3D modelData, Image textureFileData)
        {
            //sanity checks
            if (modelData == null)
            {
                throw new ArgumentException("Geometry model info not supplied.");
            }
            if (!(modelData.Geometry != null && modelData.Geometry is MeshGeometry3D))
            {
                throw new ArgumentException("Passed model is not of type mesh geometry 3d");
            }

            //read specific values from xaml file
            var modelColor          = GetModelColor(modelData);
            var mesh                = ((MeshGeometry3D)modelData.Geometry);
            var containsTextureInfo = ContainsTextureInfo(mesh);
            var positionCount       = mesh.Positions.Count;
            var points              = mesh.Positions;
            var textures            = mesh.TextureCoordinates;
            var polygons            = mesh.TriangleIndices;

            //Open the 3DS file for writing
            var writer = InitializeFile(filePath);

            //Write Material Info
            var textureFileName = MakeTextureFileName(filePath);

            MaterialChunkWriter.WriteMaterialChunk(modelColor, containsTextureInfo, textureFileName, writer);

            var objectCount = 0;
            _3DSObjectDataHandler objHandler = null;

            ushort[] setIndicesForObj   = null;
            bool[]   isIndicesSetForObj = null;
            ushort   positionIndexInObj = 0;

            for (var ctr = 0; ctr < polygons.Count; ctr += 3)
            {
                var createNewObject = objHandler == null ||
                                      objHandler.PolygonCount >= MaxValForUnsignedShort ||
                                      objHandler.TextureCoodCount >= MaxValForUnsignedShort ||
                                      objHandler.VertexCount >= MaxValForUnsignedShort;

                if (createNewObject)
                {
                    if (objHandler != null)
                    {
                        objHandler.MakeFinalUpdates();
                    }

                    objectCount++;
                    if (objectCount > 9999)
                    {
                        throw new Exception("Error: Cannot create 3ds file.\n The number of objects into which the model can be broken down exceeds 9999");
                    }

                    objHandler         = new _3DSObjectDataHandler(writer, objectCount);
                    setIndicesForObj   = new ushort[positionCount];
                    isIndicesSetForObj = new bool[positionCount];
                    positionIndexInObj = 0;
                }

                var origIndices = new[] { (ushort)polygons[ctr], (ushort)polygons[ctr + 1], (ushort)polygons[ctr + 2] };
                var newIndices  = new List <ushort>();
                foreach (var origIndex in origIndices)
                {
                    if (isIndicesSetForObj[origIndex])
                    {
                        newIndices.Add(setIndicesForObj[origIndex]);
                    }
                    else
                    {//Add the new position
                        //Interchange y and z coordinates and change the sign of y to accomodate
                        //the difference in the axes orientation between the 3ds and xaml format
                        var origPoint = points[origIndex];
                        var point     = new Point3D(origPoint.X, -origPoint.Z, origPoint.Y);
                        objHandler.AddPosition(point);

                        if (textures != null && textures.Count > origIndex)
                        {
                            var texCood = mesh.TextureCoordinates[origIndex];
                            objHandler.AddTextureIndices((float)texCood.X, (float)texCood.Y);
                        }

                        setIndicesForObj[origIndex]   = positionIndexInObj;
                        isIndicesSetForObj[origIndex] = true;

                        newIndices.Add(positionIndexInObj);

                        positionIndexInObj++;
                    }
                }
                objHandler.AddPolygonIndices(newIndices[0], newIndices[1], newIndices[2]);
            }

            //Make the final updation call on object data handler
            if (objHandler != null)
            {
                objHandler.MakeFinalUpdates();
            }

            //Close the 3ds file (after final updations to the header chunks)
            UpdateAndCloseFile(writer);

            //save the texture image data
            SaveTextureImageData(filePath, textureFileData, textureFileName);
        }