Exemplo n.º 1
0
        /// <summary>
        /// Clones this object
        /// </summary>
        public VertexStructure Clone(bool copyGeometryData = true, int capacityMultiplier = 1)
        {
            capacityMultiplier.EnsurePositiveAndNotZero(nameof(capacityMultiplier));

            // Create new VertexStructure object
            int             vertexCount = m_vertices.Count;
            VertexStructure result      = new VertexStructure(
                vertexCount * capacityMultiplier);

            // Copy geometry
            if (copyGeometryData)
            {
                for (int loop = 0; loop < vertexCount; loop++)
                {
                    result.m_vertices.Add(m_vertices[loop]);
                }
            }

            // Copy surfaces
            foreach (VertexStructureSurface actSurface in m_surfaces)
            {
                result.m_surfaces.Add(actSurface.Clone(result, copyGeometryData, capacityMultiplier));
            }

            // Copy metadata
            result.m_description = m_description;
            result.m_name        = m_name;

            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Clones this object.
        /// </summary>
        public VertexStructureSurface Clone(
            VertexStructure newOwner,
            bool copyGeometryData = true, int capacityMultiplier = 1,
            int baseIndex         = 0)
        {
            newOwner.EnsureNotNull(nameof(newOwner));

            // Create new VertexStructure object
            int indexCount = m_indices.Count;
            VertexStructureSurface result = new VertexStructureSurface(newOwner, (indexCount / 3) * capacityMultiplier);

            // Copy geometry
            if (copyGeometryData)
            {
                for (int loop = 0; loop < indexCount; loop++)
                {
                    result.m_indices.Add(m_indices[loop] + baseIndex);
                }
            }

            // Copy metadata
            result.m_materialProperties = m_materialProperties.Clone();

            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates a shadow volume structure out of the given vertex structures.
        /// </summary>
        public static VertexStructure GenerateShadowVolume(this IEnumerable <VertexStructure> structures, Vector3 lightDirection, float shadowVolumeLength)
        {
            VertexStructure result = new VertexStructure();

            //Find all edges from given view direction
            List <Line> shadowVolumeEdges = GenerateEdgesSeenFromViewpoint(structures, lightDirection);

            //Build the structure based on the found edges
            Vector3 lightNormal = Vector3.Normalize(lightDirection);
            VertexStructureSurface actSurface = result.FirstSurface;

            foreach (Line actEdge in shadowVolumeEdges)
            {
                Line targetEdge = new Line(
                    actEdge.StartPosition + lightNormal * shadowVolumeLength,
                    actEdge.EndPosition + lightNormal * shadowVolumeLength);

                actSurface.AddTriangle(
                    new Vertex(actEdge.StartPosition, Color4.White),
                    new Vertex(actEdge.EndPosition, Color4.White),
                    new Vertex(targetEdge.EndPosition, Color4.White));
                actSurface.AddTriangle(
                    new Vertex(targetEdge.EndPosition, Color4.White),
                    new Vertex(targetEdge.StartPosition, Color4.White),
                    new Vertex(actEdge.StartPosition, Color4.White));
            }

            return(result);
        }
Exemplo n.º 4
0
 internal VertexStructureSurface(VertexStructure owner, int triangleCapacity)
 {
     m_owner              = owner;
     m_indices            = new List <int>(triangleCapacity * 3);
     m_indexCollection    = new IndexCollection(m_indices);
     m_triangleCollection = new TriangleCollection(m_indices, m_owner.VerticesInternal);
     m_materialProperties = new MaterialProperties();
 }
Exemplo n.º 5
0
 /// <summary>
 /// Imports a ac file from the given stream.
 /// </summary>
 /// <param name="resourceLink">The link to the ac file.</param>
 public static ObjectType ImportObjectType(ResourceLink resourceLink)
 {
     using (Stream inStream = resourceLink.OpenInputStream())
     {
         VertexStructure structure = ImportVertexStructure(inStream, resourceLink);
         return(new GenericObjectType(structure));
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Reads the model in ASCII format from the specified stream.
        /// </summary>
        private ImportedModelContainer TryReadAscii(Stream stream, StlImportOptions importOptions)
        {
            using (var reader = new StreamReader(stream, ENCODING, false, 128, true))
            {
                VertexStructure newStructure = new VertexStructure();
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line == null)
                    {
                        continue;
                    }

                    line = line.Trim();
                    if (line.Length == 0 || line.StartsWith("\0") || line.StartsWith("#") || line.StartsWith("!") ||
                        line.StartsWith("$"))
                    {
                        continue;
                    }

                    string id, values;
                    ParseLine(line, out id, out values);
                    switch (id)
                    {
                    // Header.. not needed here
                    case "solid":
                        break;

                    // Geometry data
                    case "facet":
                        this.ReadFacet(reader, values, newStructure, importOptions);
                        break;

                    // End of file
                    case "endsolid":
                        break;
                    }
                }

                // Generate result container
                ImportedModelContainer result         = new ImportedModelContainer(importOptions);
                NamedOrGenericKey      geoResourceKey = result.GetResourceKey(
                    RES_KEY_GEO_CLASS, RES_KEY_GEO_NAME);
                result.ImportedResources.Add(new ImportedResourceInfo(
                                                 geoResourceKey,
                                                 () => new GeometryResource(newStructure)));
                GenericObject geoObject = new GenericObject(geoResourceKey);
                result.Objects.Add(geoObject);

                // Append an object which transform the whole coordinate system
                ScenePivotObject rootObject = result.CreateAndAddRootObject();
                result.ParentChildRelationships.Add(new Tuple <SceneObject, SceneObject>(rootObject, geoObject));

                return(result);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Reads the model from the specified binary stream.
        /// </summary>
        private ImportedModelContainer TryReadBinary(Stream stream, StlImportOptions importOptions)
        {
            // Check length
            long length = stream.Length;

            if (length < 84)
            {
                throw new SeeingSharpException("Incomplete file (smaller that 84 bytes)");
            }

            // Read number of triangles
            uint numberTriangles = 0;

            using (var reader = new BinaryReader(stream, Encoding.GetEncoding("us-ascii"), true))
            {
                // Read header (is not needed)
                //  (solid stands for Ascii format)
                string header = ENCODING.GetString(reader.ReadBytes(80), 0, 80).Trim();
                if (header.StartsWith("solid", StringComparison.OrdinalIgnoreCase))
                {
                    return(null);
                }

                // Read and check number of triangles
                numberTriangles = ReadUInt32(reader);
                if (length - 84 != numberTriangles * 50)
                {
                    throw new SeeingSharpException("Incomplete file (smaller that expected byte count)");
                }

                // Read geometry data
                VertexStructure newStructure = new VertexStructure((int)numberTriangles * 3);
                newStructure.CreateSurface((int)numberTriangles);
                for (int loop = 0; loop < numberTriangles; loop++)
                {
                    this.ReadTriangle(reader, newStructure, importOptions);
                }

                // Generate result container
                ImportedModelContainer result         = new ImportedModelContainer(importOptions);
                NamedOrGenericKey      geoResourceKey = result.GetResourceKey(
                    RES_KEY_GEO_CLASS, RES_KEY_GEO_NAME);
                result.ImportedResources.Add(new ImportedResourceInfo(
                                                 geoResourceKey,
                                                 () => new GeometryResource(newStructure)));
                GenericObject geoObject = new GenericObject(geoResourceKey);
                result.Objects.Add(geoObject);

                // Append an object which transform the whole coordinate system
                ScenePivotObject rootObject = result.CreateAndAddRootObject();
                result.ParentChildRelationships.Add(new Tuple <SceneObject, SceneObject>(rootObject, geoObject));

                return(result);
            }
        }
Exemplo n.º 8
0
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            VertexStructure result = new VertexStructure();

            result.CreateOrGetExistingSurface(MaterialProperties.Empty)
            .BuildCube24V(
                new Vector3(-0.5f, -0.5f, -0.5f),
                new Vector3(1f, 1f, 1f),
                Color4.Transparent);
            return(result);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Builds all vertex structures for the given detail level.
        /// </summary>
        /// <param name="buildOptions">Some generic options for structure building</param>
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            VertexStructure structureFromChild = m_objTypeToStack.BuildStructure(buildOptions);

            structureFromChild.EnsureNotNull(nameof(structureFromChild));

            BoundingBox childStructBox   = structureFromChild.GenerateBoundingBox();
            Vector3     correctionVector = -childStructBox.GetBottomCenter();

            // Copy metadata infomration of the VertexStructures
            VertexStructure result = structureFromChild.Clone(
                copyGeometryData: false,
                capacityMultiplier: m_stackSize);

            // Build geometry
            for (int loop = 0; loop < m_stackSize; loop++)
            {
                float   actYCorrection  = childStructBox.Height * loop;
                Vector3 localCorrection = new Vector3(correctionVector.X, correctionVector.Y + actYCorrection, correctionVector.Z);

                int baseVertex = loop * structureFromChild.CountVertices;
                foreach (Vertex actVertex in structureFromChild.Vertices)
                {
                    // Change vertex properties based on stack position
                    Vertex changedVertex = actVertex;
                    changedVertex.Position = changedVertex.Position + localCorrection;
                    if (loop % 2 == 1)
                    {
                        changedVertex.Color = changedVertex.Color.ChangeColorByLight(0.05f);
                    }

                    // Add the vertex
                    result.AddVertex(changedVertex);
                }

                // Clone all surfaces
                foreach (VertexStructureSurface actSurfaceFromChild in structureFromChild.Surfaces)
                {
                    VertexStructureSurface newSurface = result.CreateSurface(actSurfaceFromChild.CountTriangles);
                    foreach (Triangle actTriangle in actSurfaceFromChild.Triangles)
                    {
                        newSurface.AddTriangle(
                            baseVertex + actTriangle.Index1,
                            baseVertex + actTriangle.Index2,
                            baseVertex + actTriangle.Index3);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Adds all triangles of the given VertexStructure to this one.
        /// </summary>
        /// <param name="otherStructure">The structure to add to this one.</param>
        public void AddStructure(VertexStructure otherStructure)
        {
            int baseIndex = (int)m_vertices.Count;

            m_vertices.AddRange(otherStructure.Vertices);
            int otherStructureSurfaceCount = otherStructure.m_surfaces.Count;

            for (int loopSurface = 0; loopSurface < otherStructureSurfaceCount; loopSurface++)
            {
                m_surfaces.Add(otherStructure.m_surfaces[loopSurface].Clone(
                                   this,
                                   baseIndex: baseIndex));
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Generates all vertex structures needed for this object
        /// </summary>
        private static VertexStructure GenerateStructure(ACFileInfo fileInfo)
        {
            VertexStructure result = new VertexStructure();

            // Create all vertex structures
            Matrix4Stack transformStack = new Matrix4Stack();

            foreach (ACObjectInfo actObject in fileInfo.Objects)
            {
                FillVertexStructure(result, fileInfo.Materials, actObject, transformStack);
            }

            return(result);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Adds all vertices and surfaces of the given structure to this one.
        /// All surfaces of the given structure are merged to this single surface.
        /// </summary>
        /// <param name="structure">The structure.</param>
        public void AddStructure(VertexStructure structure)
        {
            int baseIndex = m_owner.VerticesInternal.Count;

            // Add all vertices to local structure
            m_owner.VerticesInternal.AddRange(structure.VerticesInternal);

            // Add all indices to local surface
            foreach (VertexStructureSurface actSurface in structure.Surfaces)
            {
                List <int> indices    = actSurface.m_indices;
                int        indexCount = indices.Count;
                for (int loop = 0; loop < indexCount; loop++)
                {
                    m_indices.Add(indices[loop] + baseIndex);
                }
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Imports VertexStructures from the given stream.
        /// </summary>
        /// <param name="inStream">The stream to load the data from.</param>
        /// <param name="originalSource">The original source of the generated geometry.</param>
        public static VertexStructure ImportVertexStructure(Stream inStream, ResourceLink originalSource)
        {
            try
            {
                // Load the file and generate all VertexStructures
                ACFileInfo      fileInfo = LoadFile(inStream);
                VertexStructure result   = GenerateStructure(fileInfo);
                result.ResourceLink = originalSource;

                // return the result
                return(result);
            }
            catch (Exception)
            {
                // Create dummy VertexStructure
                VertexStructure dummyStructure = new VertexStructure();
                dummyStructure.FirstSurface.BuildCube24V(
                    new Vector3(),
                    new Vector3(1f, 1f, 1f),
                    Color4.Transparent);
                return(dummyStructure);
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ObjFileReader"/> class.
        /// </summary>
        /// <param name="resource">The resource to be loaded.</param>
        /// <param name="targetContainer">The target ModelContainer into which to put the generated objects and resources.</param>
        /// <param name="importOptions">Current import settings.</param>
        public ObjFileReader(ResourceLink resource, ImportedModelContainer targetContainer, ObjImportOptions importOptions)
        {
            resource.EnsureNotNull(nameof(resource));
            targetContainer.EnsureNotNull(nameof(targetContainer));
            importOptions.EnsureNotNull(nameof(importOptions));

            m_resource        = resource;
            m_targetContainer = targetContainer;
            m_importOptions   = importOptions;

            m_rawVertices           = new List <Vector3>(1024);
            m_rawNormals            = new List <Vector3>(1014);
            m_rawTextureCoordinates = new List <Vector2>(1024);
            m_targetVertexStructure = new VertexStructure();

            // Apply transform matrix in case of a different coordinate system (switched coordinate axes)
            Matrix4x4 coordSpaceTransformMatrix = importOptions.GetTransformMatrixForCoordinateSystem();

            if (coordSpaceTransformMatrix != Matrix4x4.Identity)
            {
                m_targetVertexStructure.EnableBuildTimeTransform(coordSpaceTransformMatrix);
            }
        }
Exemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BuiltVerticesRange" /> struct.
 /// </summary>
 /// <param name="structure">The structure.</param>
 /// <param name="startVertex">The start vertex.</param>
 /// <param name="vertexCount">The vertex count.</param>
 public BuiltVerticesRange(VertexStructure structure, int startVertex, int vertexCount)
 {
     this.Structure   = structure;
     this.StartVertex = startVertex;
     this.VertexCount = vertexCount;
 }
Exemplo n.º 16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BuiltVerticesRange" /> struct.
 /// </summary>
 /// <param name="structure">The structure.</param>
 public BuiltVerticesRange(VertexStructure structure)
 {
     this.Structure   = structure;
     this.StartVertex = 0;
     this.VertexCount = 0;
 }
Exemplo n.º 17
0
        /// <summary>
        /// Imports the texture node where the xml reader is currently located.
        /// </summary>
        /// <param name="inStreamXml">The xml reader object.</param>
        /// <param name="container">The container where to import to.</param>
        /// <param name="xglImportOptions">Current import options.</param>
        private void ImportMesh(XmlReader inStreamXml, ImportedModelContainer container, XglImportOptions xglImportOptions)
        {
            string          id = inStreamXml.GetAttribute("ID");
            VertexStructure actVertexStructure = new VertexStructure();
            int             minVertexID        = int.MaxValue;
            int             actVertexIndex     = -1;
            int             actNormalIndex     = -1;
            int             actTextureIndex    = -1;
            Vertex          actTempVertex      = Vertex.Empty;

            int[] actFaceReferences = new int[3];
            Dictionary <int, MaterialProperties> localMaterialInfos = new Dictionary <int, MaterialProperties>();

            while (inStreamXml.Read())
            {
                // Ending condition
                if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                    (inStreamXml.Name == NODE_NAME_MESH))
                {
                    break;
                }

                // Continue condition
                if (inStreamXml.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                switch (inStreamXml.Name)
                {
                case NODE_NAME_SURFACE:
                    // If this tag is present, faces will be visible from both sides. If this flag is absent, faces will be visible from only one side as described in the <F> tag
                    break;

                case NODE_NAME_MAT:
                    // Read the next material
                    var materialAndID = ImportMaterial(inStreamXml, container, xglImportOptions);
                    localMaterialInfos[materialAndID.Item1] = materialAndID.Item2;
                    break;

                case NODE_NAME_PATCH:
                    // A patch is a group of faces
                    // We don't need to handle this one
                    break;

                case NODE_NAME_POINT:
                    // Read next point
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actVertexIndex++;
                    actTempVertex       = actVertexStructure.EnsureVertexAt(actVertexIndex);
                    actTempVertex.Color = Color4.White;
                    inStreamXml.Read();
                    actTempVertex.Position = inStreamXml.ReadContentAsVector3() * xglImportOptions.ResizeFactor;
                    actVertexStructure.Vertices[actVertexIndex] = actTempVertex;
                    break;

                case NODE_NAME_NORMAL:
                    // Read next normal
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actNormalIndex++;
                    actTempVertex = actVertexStructure.EnsureVertexAt(actNormalIndex);
                    inStreamXml.Read();
                    actTempVertex.Normal = inStreamXml.ReadContentAsVector3();
                    actVertexStructure.Vertices[actNormalIndex] = actTempVertex;
                    break;

                case NODE_NAME_TC:
                    // Read next texture coordinate
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actTextureIndex++;
                    actTempVertex = actVertexStructure.EnsureVertexAt(actTextureIndex);
                    inStreamXml.Read();
                    actTempVertex.TexCoord = inStreamXml.ReadContentAsVector2();
                    actVertexStructure.Vertices[actTextureIndex] = actTempVertex;
                    break;

                case NODE_NAME_FACE:
                    // Read next face
                    actFaceReferences[0] = 0;
                    actFaceReferences[1] = 0;
                    actFaceReferences[2] = 0;
                    int loopFacePoint     = 0;
                    int referencedMat     = -1;
                    int referencedTexture = -1;
                    while (inStreamXml.Read())
                    {
                        // Ending condition
                        if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                            (inStreamXml.Name == NODE_NAME_FACE))
                        {
                            break;
                        }
                        if (inStreamXml.NodeType != XmlNodeType.Element)
                        {
                            continue;
                        }

                        // Read next face index
                        if (inStreamXml.Name == NODE_NAME_FACE_MATERIAL_REF)
                        {
                            inStreamXml.Read();
                            referencedMat = inStreamXml.ReadContentAsInt();
                        }
                        else if (inStreamXml.Name == NODE_NAME_FACE_TEXTUREREF_REF)
                        {
                            inStreamXml.Read();
                            referencedTexture = inStreamXml.ReadContentAsInt();
                        }
                        else if (inStreamXml.Name == NODE_NAME_FACE_POINT_REF)
                        {
                            if (loopFacePoint >= 3)
                            {
                                throw new SeeingSharpGraphicsException("Invalid face index count!");
                            }
                            inStreamXml.Read();
                            actFaceReferences[loopFacePoint] = inStreamXml.ReadContentAsInt() - minVertexID;
                            loopFacePoint++;
                        }
                        else
                        {
                        }
                    }

                    // Get the correct material
                    MaterialProperties referencedMatObject = MaterialProperties.Empty;
                    if (referencedMat > -1)
                    {
                        localMaterialInfos.TryGetValue(referencedMat, out referencedMatObject);
                    }
                    if (referencedTexture > -1)
                    {
                        referencedMatObject            = referencedMatObject.Clone();
                        referencedMatObject.TextureKey = container.GetResourceKey(RES_CLASS_TEXTURE, referencedTexture.ToString());
                    }

                    //for (int actFaceLoc = 0; actFaceLoc < 3; actFaceLoc++)
                    //{
                    //    int actVertexIndexInner = actFaceReferences[actFaceLoc];
                    //    actTempVertex = actVertexStructure.Vertices[actVertexIndexInner];
                    //    actTempVertex.Color = referencedMatObject.DiffuseColor;
                    //    actVertexStructure.Vertices[actVertexIndexInner] = actTempVertex;
                    //}

                    // Add the triangle
                    if (loopFacePoint != 3)
                    {
                        throw new SeeingSharpGraphicsException("Invalid face index count!");
                    }
                    actVertexStructure
                    .CreateOrGetExistingSurface(referencedMatObject)
                    .AddTriangle(actFaceReferences[0], actFaceReferences[1], actFaceReferences[2]);
                    break;

                default:
                    //throw new SeeingSharpGraphicsException(string.Format(
                    //    "Unknown element {0} in xgl file!",
                    //    inStreamXml.Name));
                    break;
                }
            }

            // Add the geometry resource
            container.ImportedResources.Add(new ImportedResourceInfo(
                                                container.GetResourceKey(RES_CLASS_MESH, id),
                                                () => new GeometryResource(actVertexStructure)));
        }
Exemplo n.º 18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GenericObjectType"/> class.
 /// </summary>
 /// <param name="vertexStructure">The vertex structures.</param>
 /// <param name="vertexStructureLowDetail">The vertex structures for low detail level.</param>
 public GenericObjectType(VertexStructure vertexStructure, VertexStructure vertexStructureLowDetail)
 {
     m_vertexStructure          = vertexStructure;
     m_vertexStructureLowDetail = vertexStructureLowDetail;
 }
Exemplo n.º 19
0
        /// <summary>
        /// Loads an object from the given uri
        /// </summary>
        public static ObjectType ImportObjectType(Stream inStream)
        {
            VertexStructure structures = ImportVertexStructure(inStream);

            return(new GenericObjectType(structures));
        }
Exemplo n.º 20
0
        /// <summary>
        /// Fills the given vertex structure using information from the given AC-File-Objects.
        /// </summary>
        /// <param name="objInfo">The object information from the AC file.</param>
        /// <param name="acMaterials">A list containing all materials from the AC file.</param>
        /// <param name="structure">The VertexStructure to be filled.</param>
        /// <param name="transformStack">Current matrix stack (for stacked objects).</param>
        private static void FillVertexStructure(VertexStructure structure, List <ACMaterialInfo> acMaterials, ACObjectInfo objInfo, Matrix4Stack transformStack)
        {
            List <Tuple <int, int> > standardShadedVertices = new List <Tuple <int, int> >();

            transformStack.Push();
            try
            {
                // Perform local transformation for the current AC object
                transformStack.TransformLocal(objInfo.Rotation);
                transformStack.TranslateLocal(objInfo.Translation);

                // Build structures material by material
                for (int actMaterialIndex = 0; actMaterialIndex < acMaterials.Count; actMaterialIndex++)
                {
                    ACMaterialInfo actMaterial = acMaterials[actMaterialIndex];

                    VertexStructureSurface actStructSurface = structure.CreateOrGetExistingSurface(actMaterial.CreateMaterialProperties());
                    bool isNewSurface = actStructSurface.CountTriangles == 0;

                    // Create and configure vertex structure
                    actStructSurface.Material   = NamedOrGenericKey.Empty;
                    actStructSurface.TextureKey = !string.IsNullOrEmpty(objInfo.Texture) ? new NamedOrGenericKey(objInfo.Texture) : NamedOrGenericKey.Empty;
                    actStructSurface.MaterialProperties.DiffuseColor  = actMaterial.Diffuse;
                    actStructSurface.MaterialProperties.AmbientColor  = actMaterial.Ambient;
                    actStructSurface.MaterialProperties.EmissiveColor = actMaterial.Emissive;
                    actStructSurface.MaterialProperties.Shininess     = actMaterial.Shininess;
                    actStructSurface.MaterialProperties.SpecularColor = actMaterial.Specular;

                    // Initialize local index table (needed for vertex reuse)
                    int   oneSideVertexCount = objInfo.Vertices.Count;
                    int[] localIndices       = new int[oneSideVertexCount * 2];
                    for (int loop = 0; loop < localIndices.Length; loop++)
                    {
                        localIndices[loop] = int.MaxValue;
                    }

                    // Process all surfaces
                    foreach (ACSurface actSurface in objInfo.Surfaces)
                    {
                        // Get the vertex index on which to start
                        int startVertexIndex   = structure.CountVertices;
                        int startTriangleIndex = actStructSurface.CountTriangles;

                        // Only handle surfaces of the current material
                        if (actSurface.Material != actMaterialIndex)
                        {
                            continue;
                        }

                        // Sort out unsupported surfaces
                        if (actSurface.VertexReferences.Count < 3)
                        {
                            continue;
                        }
                        if (actSurface.IsLine)
                        {
                            continue;
                        }
                        if (actSurface.IsClosedLine)
                        {
                            continue;
                        }

                        // Preprocess referenced vertices
                        int        oneSideSurfaceVertexCount     = actSurface.VertexReferences.Count;
                        int        countSurfaceSides             = actSurface.IsTwoSided ? 2 : 1;
                        int[]      onStructureReferencedVertices = new int[oneSideSurfaceVertexCount * countSurfaceSides];
                        List <int> surfaceVertexReferences       = actSurface.VertexReferences;
                        for (int loop = 0; loop < surfaceVertexReferences.Count; loop++)
                        {
                            Vector2 actTexCoord = actSurface.TextureCoordinates[loop];

                            if (!actSurface.IsFlatShaded)
                            {
                                // Try to reuse vertices on standard shading
                                if (localIndices[surfaceVertexReferences[loop]] == int.MaxValue)
                                {
                                    Vector3 position = Vector3.Transform(
                                        objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                        transformStack.Top);
                                    localIndices[surfaceVertexReferences[loop]] = structure.AddVertex(new Vertex(
                                                                                                          position, Color4.White, actTexCoord, Vector3.Zero));
                                    if (actSurface.IsTwoSided)
                                    {
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount] = structure.AddVertex(new Vertex(
                                                                                                                                   position, Color4.White, actTexCoord, Vector3.Zero));
                                    }
                                }

                                // Store vertex reference for this surface's index
                                onStructureReferencedVertices[loop] = localIndices[surfaceVertexReferences[loop]];
                                if (actSurface.IsTwoSided)
                                {
                                    onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] =
                                        localIndices[surfaceVertexReferences[loop] + oneSideVertexCount];
                                }
                            }
                            else
                            {
                                // Create one vertex for one reference for flat shading
                                Vector3 position = Vector3.Transform(
                                    objInfo.Vertices[surfaceVertexReferences[loop]].Position,
                                    transformStack.Top);
                                onStructureReferencedVertices[loop] = structure.AddVertex(new Vertex(
                                                                                              position, Color4.White, actTexCoord, Vector3.Zero));
                                if (actSurface.IsTwoSided)
                                {
                                    onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] = structure.AddVertex(new Vertex(
                                                                                                                              position, Color4.White, actTexCoord, Vector3.Zero));
                                }
                            }
                        }

                        // Build object geometry
                        switch (actSurface.VertexReferences.Count)
                        {
                        case 3:
                            // Front side
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[0],
                                onStructureReferencedVertices[1],
                                onStructureReferencedVertices[2]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[5],
                                    onStructureReferencedVertices[4],
                                    onStructureReferencedVertices[3]);
                            }
                            break;

                        case 4:
                            // Front side
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[0],
                                onStructureReferencedVertices[1],
                                onStructureReferencedVertices[2]);
                            actStructSurface.AddTriangle(
                                onStructureReferencedVertices[2],
                                onStructureReferencedVertices[3],
                                onStructureReferencedVertices[0]);

                            // Back side
                            if (actSurface.IsTwoSided)
                            {
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[6],
                                    onStructureReferencedVertices[5],
                                    onStructureReferencedVertices[4]);
                                actStructSurface.AddTriangle(
                                    onStructureReferencedVertices[4],
                                    onStructureReferencedVertices[7],
                                    onStructureReferencedVertices[6]);
                            }
                            break;

                        default:
                            if (!actSurface.IsTwoSided)
                            {
                                // Front side
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices);
                            }
                            else
                            {
                                // Front and back side
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(0, oneSideSurfaceVertexCount));
                                actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(oneSideSurfaceVertexCount, oneSideSurfaceVertexCount));
                            }
                            break;
                        }

                        // Perform shading
                        if (actSurface.IsFlatShaded)
                        {
                            actStructSurface.CalculateNormalsFlat(
                                startTriangleIndex, actStructSurface.CountTriangles - startTriangleIndex);
                        }
                        else
                        {
                            // Nothing to be done for now..
                            int vertexCount = structure.CountVertices - startVertexIndex;
                            if (vertexCount > 0)
                            {
                                standardShadedVertices.Add(
                                    Tuple.Create((int)startVertexIndex, vertexCount));
                            }
                        }
                    }

                    // Calculate default shading finally (if any)
                    foreach (var actStandardShadedPair in standardShadedVertices)
                    {
                        structure.CalculateNormals(
                            actStandardShadedPair.Item1,
                            actStandardShadedPair.Item2);
                    }
                    standardShadedVertices.Clear();

                    // Append generated VertexStructure to the output collection
                    if ((actStructSurface.CountTriangles <= 0) &&
                        (isNewSurface))
                    {
                        structure.RemoveSurface(actStructSurface);
                    }
                }

                //Fill in all child object data
                foreach (ACObjectInfo actObjInfo in objInfo.Childs)
                {
                    FillVertexStructure(structure, acMaterials, actObjInfo, transformStack);
                }
            }
            finally
            {
                transformStack.Pop();
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Builds the structure needed for the pallet
        /// </summary>
        /// <param name="buildOptions">Some generic options for structure building</param>
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            bool createContent = m_contentHeight > 0f;

            // Prepare result array
            VertexStructure result = new VertexStructure();

            VertexStructureSurface surfacePallet  = result.CreateSurface();
            VertexStructureSurface surfaceContent = null;

            if (createContent)
            {
                surfaceContent = result.CreateSurface();
            }

            // Build pallet
            #region -----------------------------------------------------------
            if (buildOptions.IsHighDetail)
            {
                float middleFront            = m_width / 2f;
                float middleSide             = m_depth / 2f;
                float middleFrontBegin       = middleFront - m_bigFooterWidth / 2f;
                float middleSideBegin        = middleSide - m_bigFooterWidth / 2f;
                float lastBeginSmall         = m_width - m_smallFooterWidth;
                float lastBeginBig           = m_depth - m_bigFooterWidth;
                float footerHeight           = m_palletHeight - m_boardHeight * 3f;
                float quarterFrontBegin      = ((m_bigFooterWidth / 2f) + ((middleFront - (m_bigFooterWidth / 2f)) / 2f)) - (m_smallFooterWidth / 2f); // +(middleFront / 2f - m_smallFooterWidth / 2f);
                float threeQuarterFrontBegin = middleFront + (middleFront - quarterFrontBegin - m_smallFooterWidth);                                   //(middleFront / 2f) * 3f - m_smallFooterWidth / 2f;

                surfacePallet.Material = m_palletMaterial;

                // Build 3 board on bottom
                surfacePallet.BuildCube24V(new Vector3(0f, 0f, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(middleFrontBegin, 0f, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(lastBeginSmall, 0f, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), m_palletColor);

                // Build 9 footers
                surfacePallet.BuildCubeSides16V(new Vector3(0f, m_boardHeight, 0f), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(0f, m_boardHeight, middleSideBegin), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(0f, m_boardHeight, lastBeginBig), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight, 0f), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight, middleSideBegin), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight, lastBeginBig), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight, 0f), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight, middleSideBegin), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight, lastBeginBig), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), m_palletColor);

                // Build boards above footers
                surfacePallet.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight, 0f), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight, middleSideBegin), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight, lastBeginBig), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), m_palletColor);

                // Build top boards
                float localYPos = m_palletHeight - m_boardHeight;
                surfacePallet.BuildCube24V(new Vector3(0f, localYPos, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(middleFrontBegin, localYPos, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(m_width - m_bigFooterWidth, localYPos, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(quarterFrontBegin, localYPos, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), m_palletColor);
                surfacePallet.BuildCube24V(new Vector3(threeQuarterFrontBegin, localYPos, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), m_palletColor);
            }
            else
            {
                surfacePallet.BuildCube24V(
                    new Vector3(0f, 0f, 0f),
                    new Vector3(m_width, m_palletHeight, m_depth),
                    m_palletColor);
            }
            #endregion -----------------------------------------------------------

            // Build content
            #region -----------------------------------------------------------
            if (createContent)
            {
                surfaceContent.Material = m_contentMaterial;
                surfaceContent.BuildCubeSides16V(new Vector3(0f, m_palletHeight, 0f), new Vector3(m_width, m_contentHeight, m_depth), m_contentColor);
                surfaceContent.BuildCubeTop4V(new Vector3(0f, m_palletHeight, 0f), new Vector3(m_width, m_contentHeight, m_depth), m_contentColor);
                surfaceContent.BuildCubeBottom4V(new Vector3(0f, m_palletHeight, 0f), new Vector3(m_width, m_contentHeight, m_depth), m_contentColor);
            }
            #endregion -----------------------------------------------------------

            Matrix4x4 rotMatrix = Matrix4x4.CreateRotationY(EngineMath.RAD_90DEG);
            result.UpdateVerticesUsingRelocationBy(new Vector3(-m_width / 2f, 0f, -m_depth / 2f));
            result.CalculateTangentsAndBinormals();
            result.TransformVertices(rotMatrix);

            return(result);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Builds the structure.
        /// </summary>
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            VertexStructure result = new VertexStructure();

            // Hold dictionary containg materials and corresponding structures
            Dictionary <NamedOrGenericKey, VertexStructureSurface> materialRelated = new Dictionary <NamedOrGenericKey, VertexStructureSurface>();

            // Build bottom structure
            VertexStructureSurface bottomSurface = result.CreateSurface();

            bottomSurface.Material            = m_bottomMaterial;
            materialRelated[m_bottomMaterial] = bottomSurface;

            // Calculate half vector of total ground size.
            Vector2 totalHalfSize = new Vector2(m_totalSizeWithoutBorder.X / 2f, m_totalSizeWithoutBorder.Y / 2f);
            Vector2 tileHalfSize  = new Vector2(m_tileSize.X / 2f, m_tileSize.Y / 2f);

            // Build all tiles
            foreach (FloorTile actTile in m_groundTiles)
            {
                // Get the material of the tile
                NamedOrGenericKey actMaterial = actTile.Material;
                if (actMaterial.IsEmpty)
                {
                    actMaterial = m_groundMaterial;
                }

                // Get surface object
                VertexStructureSurface actSurface = null;
                if (materialRelated.ContainsKey(actMaterial))
                {
                    actSurface = materialRelated[actMaterial];
                }
                else
                {
                    actSurface                   = result.CreateSurface();
                    actSurface.Material          = actMaterial;
                    materialRelated[actMaterial] = actSurface;
                }

                // Get position of the tile
                Vector3 tilePosition = new Vector3(
                    (actTile.XPos * m_tileSize.X) - totalHalfSize.X,
                    0f,
                    (actTile.YPos * m_tileSize.Y) - totalHalfSize.Y);

                // Add tile information to current VertexStructures
                actSurface.BuildCubeTop4V(
                    new Vector3(tilePosition.X, -m_height, tilePosition.Z),
                    new Vector3(m_tileSize.X, m_height, m_tileSize.Y),
                    Color4.White);
                bottomSurface.BuildCubeBottom4V(
                    new Vector3(tilePosition.X, -m_height, tilePosition.Z),
                    new Vector3(m_tileSize.X, m_height, m_tileSize.Y),
                    Color4.White);
            }

            // Build all borders
            VertexStructureSurface borderSurface = null;

            if (materialRelated.ContainsKey(m_borderMaterial))
            {
                borderSurface = materialRelated[m_borderMaterial];
            }
            else
            {
                borderSurface                     = result.CreateSurface();
                borderSurface.Material            = m_borderMaterial;
                materialRelated[m_borderMaterial] = borderSurface;
            }
            foreach (BorderInformation actBorder in m_borders)
            {
                if (m_borderSize <= 0f)
                {
                    Vector3 tilePosition = new Vector3(
                        (actBorder.TileXPos * m_tileSize.X) - totalHalfSize.X,
                        0f,
                        (actBorder.TileYPos * m_tileSize.Y) - totalHalfSize.Y);

                    //Build simple borders
                    switch (actBorder.Location)
                    {
                    case BorderLocation.Left:
                        borderSurface.BuildRect4V(
                            new Vector3(tilePosition.X, -m_height, tilePosition.Z),
                            new Vector3(tilePosition.X, 0f, tilePosition.Z),
                            new Vector3(tilePosition.X, 0f, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X, -m_height, tilePosition.Z + m_tileSize.Y));
                        break;

                    case BorderLocation.Top:
                        borderSurface.BuildRect4V(
                            new Vector3(tilePosition.X, -m_height, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X, 0f, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X + m_tileSize.X, 0f, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X + m_tileSize.X, -m_height, tilePosition.Z + m_tileSize.Y));
                        break;

                    case BorderLocation.Right:
                        borderSurface.BuildRect4V(
                            new Vector3(tilePosition.X + m_tileSize.X, -m_height, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X + m_tileSize.X, 0f, tilePosition.Z + m_tileSize.Y),
                            new Vector3(tilePosition.X + m_tileSize.X, 0f, tilePosition.Z),
                            new Vector3(tilePosition.X + m_tileSize.X, -m_height, tilePosition.Z));
                        break;

                    case BorderLocation.Bottom:
                        borderSurface.BuildRect4V(
                            new Vector3(tilePosition.X + m_tileSize.X, -m_height, tilePosition.Z),
                            new Vector3(tilePosition.X + m_tileSize.X, 0f, tilePosition.Z),
                            new Vector3(tilePosition.X, 0f, tilePosition.Z),
                            new Vector3(tilePosition.X, -m_height, tilePosition.Z));
                        break;
                    }
                }
                else
                {
                    //Build complex borders
                }
            }

            //Return all generated VertexStructures
            return(result);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Builds the structure needed for the pallet
        /// </summary>
        /// <param name="buildOptions">Some generic options for structure building</param>
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            VertexStructure        result  = new VertexStructure();
            VertexStructureSurface surface = result.CreateSurface();

            //Build pallet
            #region -----------------------------------------------------------
            if (buildOptions.IsHighDetail)
            {
                float middleFront            = m_width / 2f;
                float middleSide             = m_depth / 2f;
                float middleFrontBegin       = middleFront - m_bigFooterWidth / 2f;
                float middleSideBegin        = middleSide - m_bigFooterWidth / 2f;
                float lastBeginSmall         = m_width - m_smallFooterWidth;
                float lastBeginBig           = m_depth - m_bigFooterWidth;
                float footerHeight           = m_palletHeight - m_boardHeight * 3f;
                float quarterFrontBegin      = ((m_bigFooterWidth / 2f) + ((middleFront - (m_bigFooterWidth / 2f)) / 2f)) - (m_smallFooterWidth / 2f); // +(middleFront / 2f - m_smallFooterWidth / 2f);
                float threeQuarterFrontBegin = middleFront + (middleFront - quarterFrontBegin - m_smallFooterWidth);                                   //(middleFront / 2f) * 3f - m_smallFooterWidth / 2f;

                for (int loop = 0; loop < m_palletCount; loop++)
                {
                    Color4 actColor  = loop % 2 == 0 ? m_palletColor : m_palletCollor2;
                    float  actYCoord = m_palletHeight * loop;

                    surface.Material = m_palletMaterial;

                    //Build 3 board on bottom
                    surface.BuildCube24V(new Vector3(0f, actYCoord, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(middleFrontBegin, actYCoord, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(lastBeginSmall, actYCoord, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), actColor);

                    //Build 9 footers
                    surface.BuildCubeSides16V(new Vector3(0f, m_boardHeight + actYCoord, 0f), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(0f, m_boardHeight + actYCoord, middleSideBegin), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(0f, m_boardHeight + actYCoord, lastBeginBig), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight + actYCoord, 0f), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight + actYCoord, middleSideBegin), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(middleFrontBegin, m_boardHeight + actYCoord, lastBeginBig), new Vector3(m_bigFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight + actYCoord, 0f), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight + actYCoord, middleSideBegin), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);
                    surface.BuildCubeSides16V(new Vector3(lastBeginSmall, m_boardHeight + actYCoord, lastBeginBig), new Vector3(m_smallFooterWidth, footerHeight, m_bigFooterWidth), actColor);

                    //Build boards above footers
                    surface.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight + actYCoord, 0f), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), actColor);
                    surface.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight + actYCoord, middleSideBegin), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), actColor);
                    surface.BuildCube24V(new Vector3(0f, m_boardHeight + footerHeight + actYCoord, lastBeginBig), new Vector3(m_width, m_boardHeight, m_bigFooterWidth), actColor);

                    //Build top boards
                    float localYPos = m_palletHeight - m_boardHeight;
                    surface.BuildCube24V(new Vector3(0f, localYPos + actYCoord, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(middleFrontBegin, localYPos + actYCoord, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(m_width - m_bigFooterWidth, localYPos + actYCoord, 0f), new Vector3(m_bigFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(quarterFrontBegin, localYPos + actYCoord, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), actColor);
                    surface.BuildCube24V(new Vector3(threeQuarterFrontBegin, localYPos + actYCoord, 0f), new Vector3(m_smallFooterWidth, m_boardHeight, m_depth), actColor);
                }
            }
            else
            {
                for (int loop = 0; loop < m_palletCount; loop++)
                {
                    Color4 actColor = loop % 2 == 0 ? m_palletColor : m_palletCollor2;
                    surface.BuildCube24V(
                        new Vector3(0f, m_palletHeight * loop, 0f),
                        new Vector3(m_width, m_palletHeight, m_depth),
                        actColor);
                }
            }
            #endregion -----------------------------------------------------------

            Matrix4x4 rotMatrix = Matrix4x4.CreateRotationY(EngineMath.RAD_90DEG);

            result.UpdateVerticesUsingRelocationBy(new Vector3(-m_width / 2f, 0f, -m_depth / 2f));
            result.CalculateTangentsAndBinormals();
            result.TransformVertices(rotMatrix);
            result.FitToCenteredCube(1f, FitToCuboidMode.Stretch, SpacialOriginLocation.LowerCenter);

            return(result);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Reads a facet.
        /// </summary>
        private void ReadFacet(StreamReader reader, string normalString, VertexStructure newStructure, StlImportOptions importOptions)
        {
            m_cachedPoints.Clear();

            // Read all geometry
            Vector3 normal = ParseNormal(normalString);

            ReadLine(reader, "outer");
            while (true)
            {
                string  line = reader.ReadLine();
                Vector3 point;
                if (TryParseVertex(line, out point))
                {
                    m_cachedPoints.Add(point);
                    continue;
                }

                string id, values;
                ParseLine(line, out id, out values);

                if (id == "endloop")
                {
                    break;
                }
            }

            // Read end
            ReadLine(reader, "endfacet");

            // Overtake geometry data
            VertexStructureSurface targetSurfae = newStructure.FirstSurface;
            int pointCount = m_cachedPoints.Count;

            switch (m_cachedPoints.Count)
            {
            case 0:
            case 1:
            case 2:
                break;

            case 3:
                if (importOptions.IsChangeTriangleOrderNeeded())
                {
                    targetSurfae.AddTriangle(
                        new Vertex(m_cachedPoints[2], Color4.Transparent, Vector2.Zero, normal),
                        new Vertex(m_cachedPoints[1], Color4.Transparent, Vector2.Zero, normal),
                        new Vertex(m_cachedPoints[0], Color4.Transparent, Vector2.Zero, normal));
                }
                else
                {
                    targetSurfae.AddTriangle(
                        new Vertex(m_cachedPoints[0], Color4.Transparent, Vector2.Zero, normal),
                        new Vertex(m_cachedPoints[1], Color4.Transparent, Vector2.Zero, normal),
                        new Vertex(m_cachedPoints[2], Color4.Transparent, Vector2.Zero, normal));
                }
                break;

            default:
                int[] indices = new int[pointCount];
                if (importOptions.IsChangeTriangleOrderNeeded())
                {
                    for (int loop = pointCount - 1; loop > -1; loop--)
                    {
                        indices[loop] = newStructure.AddVertex(
                            new Vertex(m_cachedPoints[loop], Color4.Transparent, Vector2.Zero, normal));
                    }
                }
                else
                {
                    for (int loop = 0; loop < pointCount; loop++)
                    {
                        indices[loop] = newStructure.AddVertex(
                            new Vertex(m_cachedPoints[loop], Color4.Transparent, Vector2.Zero, normal));
                    }
                }

                targetSurfae.AddPolygonByCuttingEars(indices);
                break;
            }
        }
Exemplo n.º 25
0
        /// <summary>
        /// Reads a triangle from a binary STL file.
        /// </summary>
        private void ReadTriangle(BinaryReader reader, VertexStructure vertexStructure, StlImportOptions importOptions)
        {
            float ni     = ReadFloat(reader);
            float nj     = ReadFloat(reader);
            float nk     = ReadFloat(reader);
            var   normal = new Vector3(ni, nj, nk);

            float x1 = ReadFloat(reader);
            float y1 = ReadFloat(reader);
            float z1 = ReadFloat(reader);
            var   v1 = new Vector3(x1, y1, z1);

            float x2 = ReadFloat(reader);
            float y2 = ReadFloat(reader);
            float z2 = ReadFloat(reader);
            var   v2 = new Vector3(x2, y2, z2);

            float x3 = ReadFloat(reader);
            float y3 = ReadFloat(reader);
            float z3 = ReadFloat(reader);
            var   v3 = new Vector3(x3, y3, z3);

            // Try to read color information
            var   attrib       = Convert.ToString(ReadUInt16(reader), 2).PadLeft(16, '0').ToCharArray();
            var   hasColor     = attrib[0].Equals('1');
            Color currentColor = Color.Transparent;

            if (hasColor)
            {
                int blue = attrib[15].Equals('1') ? 1 : 0;
                blue = attrib[14].Equals('1') ? blue + 2 : blue;
                blue = attrib[13].Equals('1') ? blue + 4 : blue;
                blue = attrib[12].Equals('1') ? blue + 8 : blue;
                blue = attrib[11].Equals('1') ? blue + 16 : blue;
                int b = blue * 8;

                int green = attrib[10].Equals('1') ? 1 : 0;
                green = attrib[9].Equals('1') ? green + 2 : green;
                green = attrib[8].Equals('1') ? green + 4 : green;
                green = attrib[7].Equals('1') ? green + 8 : green;
                green = attrib[6].Equals('1') ? green + 16 : green;
                int g = green * 8;

                int red = attrib[5].Equals('1') ? 1 : 0;
                red = attrib[4].Equals('1') ? red + 2 : red;
                red = attrib[3].Equals('1') ? red + 4 : red;
                red = attrib[2].Equals('1') ? red + 8 : red;
                red = attrib[1].Equals('1') ? red + 16 : red;
                int r = red * 8;

                currentColor = new Color(Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
            }

            VertexStructureSurface targetSurface = vertexStructure.FirstSurface;

            if (importOptions.IsChangeTriangleOrderNeeded())
            {
                targetSurface.AddTriangle(
                    new Vertex(v3, currentColor, Vector2.Zero, normal),
                    new Vertex(v2, currentColor, Vector2.Zero, normal),
                    new Vertex(v1, currentColor, Vector2.Zero, normal));
            }
            else
            {
                targetSurface.AddTriangle(
                    new Vertex(v1, currentColor, Vector2.Zero, normal),
                    new Vertex(v2, currentColor, Vector2.Zero, normal),
                    new Vertex(v3, currentColor, Vector2.Zero, normal));
            }
        }
Exemplo n.º 26
0
        /// <summary>
        /// Builds the structures.
        /// </summary>
        public override VertexStructure BuildStructure(StructureBuildOptions buildOptions)
        {
            VertexStructure result = new VertexStructure();

            // Calculate parameters
            Vector3 firstCoordinate = new Vector3(
                -((TilesX * TileWidth) / 2f),
                0f,
                -((TilesZ * TileWidth) / 2f));
            float tileWidthX     = this.TileWidth;
            float tileWidthZ     = this.TileWidth;
            float fieldWidth     = tileWidthX * TilesX;
            float fieldDepth     = tileWidthZ * TilesZ;
            float fieldWidthHalf = fieldWidth / 2f;
            float fieldDepthHalf = fieldDepth / 2f;

            int tileMiddleX = (TilesX % 2 == 0) && (this.HighlightXZLines) ? this.TilesX / 2 : 1;
            int tileMiddleZ = (TilesZ % 2 == 0) && (this.HighlightXZLines) ? this.TilesZ / 2 : 1;

            // Define lower ground structure
            if (this.GenerateGround)
            {
                VertexStructureSurface lowerGround = result.CreateSurface();
                lowerGround.EnableTextureTileMode(new Vector2(TileWidth, TileWidth));
                lowerGround.BuildRect4V(
                    new Vector3(-fieldWidthHalf, -0.01f, -fieldDepthHalf),
                    new Vector3(fieldWidthHalf, -0.01f, -fieldDepthHalf),
                    new Vector3(fieldWidthHalf, -0.01f, fieldDepthHalf),
                    new Vector3(-fieldWidthHalf, -0.01f, fieldDepthHalf),
                    new Vector3(0f, 1f, 0f),
                    this.GroundColor);
                lowerGround.Material = this.GroundMaterial;
            }

            // Define line structures
            VertexStructureSurface genStructureDefaultLine = result.CreateSurface();
            VertexStructureSurface genStructureGroupLine   = result.CreateSurface();

            for (int actTileX = 0; actTileX < TilesX + 1; actTileX++)
            {
                Vector3 localStart = firstCoordinate + new Vector3(actTileX * tileWidthX, 0f, 0f);
                Vector3 localEnd   = localStart + new Vector3(0f, 0f, tileWidthZ * TilesZ);

                Color4 actLineColor = this.LineColor;
                float  devider      = actTileX % this.GroupTileCount == 0 ? this.LineSmallDevider : this.LineBigDevider;
                if (this.HighlightXZLines && (actTileX == tileMiddleX))
                {
                    actLineColor = this.ZLineHighlightColor;
                    devider      = this.LineSmallDevider;
                }

                VertexStructureSurface targetStruture = actTileX % this.GroupTileCount == 0 ? genStructureGroupLine : genStructureDefaultLine;
                targetStruture.BuildRect4V(
                    localStart - new Vector3(tileWidthX / devider, 0f, 0f),
                    localStart + new Vector3(tileWidthX / devider, 0f, 0f),
                    localEnd + new Vector3(tileWidthX / devider, 0f, 0f),
                    localEnd - new Vector3(tileWidthX / devider, 0f, 0f),
                    actLineColor);
                if (this.BuildBackFaces)
                {
                    targetStruture.BuildRect4V(
                        localEnd - new Vector3(tileWidthX / devider, 0f, 0f),
                        localEnd + new Vector3(tileWidthX / devider, 0f, 0f),
                        localStart + new Vector3(tileWidthX / devider, 0f, 0f),
                        localStart - new Vector3(tileWidthX / devider, 0f, 0f),
                        actLineColor);
                }
            }
            for (int actTileZ = 0; actTileZ < TilesZ + 1; actTileZ++)
            {
                Vector3 localStart = firstCoordinate + new Vector3(0f, 0f, actTileZ * tileWidthZ);
                Vector3 localEnd   = localStart + new Vector3(tileWidthX * TilesX, 0f, 0f);

                Color4 actLineColor = this.LineColor;
                float  devider      = actTileZ % this.GroupTileCount == 0 ? this.LineSmallDevider : this.LineBigDevider;
                if (this.HighlightXZLines && (actTileZ == tileMiddleZ))
                {
                    actLineColor = this.XLineHighlightColor;
                    devider      = this.LineSmallDevider;
                }

                VertexStructureSurface targetStruture = actTileZ % this.GroupTileCount == 0 ? genStructureGroupLine : genStructureDefaultLine;
                targetStruture.BuildRect4V(
                    localStart + new Vector3(0f, 0f, tileWidthZ / devider),
                    localStart - new Vector3(0f, 0f, tileWidthZ / devider),
                    localEnd - new Vector3(0f, 0f, tileWidthZ / devider),
                    localEnd + new Vector3(0f, 0f, tileWidthZ / devider),
                    actLineColor);
                if (this.BuildBackFaces)
                {
                    targetStruture.BuildRect4V(
                        localEnd + new Vector3(0f, 0f, tileWidthZ / devider),
                        localEnd - new Vector3(0f, 0f, tileWidthZ / devider),
                        localStart - new Vector3(0f, 0f, tileWidthZ / devider),
                        localStart + new Vector3(0f, 0f, tileWidthZ / devider),
                        actLineColor);
                }
            }
            genStructureDefaultLine.Material = this.LineMaterial;
            genStructureGroupLine.Material   = this.LineMaterial;
            if (genStructureDefaultLine.CountTriangles == 0)
            {
                result.RemoveSurface(genStructureDefaultLine);
            }
            if (genStructureGroupLine.CountTriangles == 0)
            {
                result.RemoveSurface(genStructureGroupLine);
            }

            // Return all generated structures
            return(result);
        }
        /// <summary>
        /// IDWriteTextLayout::Draw calls this function to instruct the client to render a run of glyphs.
        /// </summary>
        /// <param name="clientDrawingContext">The application-defined drawing context passed to  <see cref="M:SharpDX.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" />.</param>
        /// <param name="baselineOriginX">The pixel location (X-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="baselineOriginY">The pixel location (Y-coordinate) at the baseline origin of the glyph run.</param>
        /// <param name="measuringMode">The measuring method for glyphs in the run, used with the other properties to determine the rendering mode.</param>
        /// <param name="glyphRun">Pointer to the glyph run instance to render.</param>
        /// <param name="glyphRunDescription">A pointer to the optional glyph run description instance which contains properties of the characters  associated with this run.</param>
        /// <param name="clientDrawingEffect">Application-defined drawing effects for the glyphs to render. Usually this argument represents effects such as the foreground brush filling the interior of text.</param>
        /// <returns>
        /// If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        /// <unmanaged>HRESULT DrawGlyphRun([None] void* clientDrawingContext,[None] FLOAT baselineOriginX,[None] FLOAT baselineOriginY,[None] DWRITE_MEASURING_MODE measuringMode,[In] const DWRITE_GLYPH_RUN* glyphRun,[In] const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,[None] IUnknown* clientDrawingEffect)</unmanaged>
        /// <remarks>
        /// The <see cref="M:SharpDX.DirectWrite.TextLayout.Draw_(System.IntPtr,System.IntPtr,System.Single,System.Single)" /> function calls this callback function with all the information about glyphs to render. The application implements this callback by mostly delegating the call to the underlying platform's graphics API such as {{Direct2D}} to draw glyphs on the drawing context. An application that uses GDI can implement this callback in terms of the <see cref="M:SharpDX.DirectWrite.BitmapRenderTarget.DrawGlyphRun(System.Single,System.Single,SharpDX.Direct2D1.MeasuringMode,SharpDX.DirectWrite.GlyphRun,SharpDX.DirectWrite.RenderingParams,SharpDX.Color4)" /> method.
        /// </remarks>
        public override SDX.Result DrawGlyphRun(
            object clientDrawingContext, float baselineOriginX, float baselineOriginY,
            MeasuringMode measuringMode, GlyphRun glyphRun, GlyphRunDescription glyphRunDescription, SDX.ComObject clientDrawingEffect)
        {
            if ((glyphRun.Indices == null) ||
                (glyphRun.Indices.Length == 0))
            {
                return(SDX.Result.Ok);;
            }

            SharpDX.DirectWrite.Factory dWriteFactory = GraphicsCore.Current.FactoryDWrite;
            SharpDX.Direct2D1.Factory   d2DFactory    = GraphicsCore.Current.FactoryD2D;

            // Extrude geometry data out of given glyph run
            SimplePolygon2DGeometrySink geometryExtruder = new SimplePolygon2DGeometrySink(new Vector2(baselineOriginX, baselineOriginY));

            using (PathGeometry pathGeometry = new PathGeometry(d2DFactory))
            {
                // Write all geometry data into a standard PathGeometry object
                using (GeometrySink geoSink = pathGeometry.Open())
                {
                    glyphRun.FontFace.GetGlyphRunOutline(
                        glyphRun.FontSize,
                        glyphRun.Indices,
                        glyphRun.Advances,
                        glyphRun.Offsets,
                        glyphRun.IsSideways,
                        glyphRun.BidiLevel % 2 == 1,
                        geoSink);
                    geoSink.Close();
                }

                // Simplify written geometry and write it into own structure
                pathGeometry.Simplify(GeometrySimplificationOption.Lines, m_geometryOptions.SimplificationFlatternTolerance, geometryExtruder);
            }

            // Structure for caching the result
            VertexStructure        tempStructure = new VertexStructure();
            VertexStructureSurface tempSurface   = tempStructure.CreateSurface();

            // Create the text surface
            if (m_geometryOptions.MakeSurface)
            {
                // Separate polygons by clock direction
                // Order polygons as needed for further hole finding algorithm
                IEnumerable <Polygon2D> fillingPolygons = geometryExtruder.GeneratedPolygons
                                                          .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.CounterClockwise)
                                                          .OrderBy(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y);
                List <Polygon2D> holePolygons = geometryExtruder.GeneratedPolygons
                                                .Where(actPolygon => actPolygon.EdgeOrder == EdgeOrder.Clockwise)
                                                .OrderByDescending(actPolygon => actPolygon.BoundingBox.Size.X * actPolygon.BoundingBox.Size.Y)
                                                .ToList();

                // Build geometry for all polygons
                int loopPolygon = 0;
                foreach (Polygon2D actFillingPolygon in fillingPolygons)
                {
                    // Find all corresponding holes
                    BoundingBox2D           actFillingPolygonBounds = actFillingPolygon.BoundingBox;
                    IEnumerable <Polygon2D> correspondingHoles      = holePolygons
                                                                      .Where(actHolePolygon => actHolePolygon.BoundingBox.IsContainedBy(actFillingPolygonBounds))
                                                                      .ToList();

                    // Two steps here:
                    // - Merge current filling polygon and all its holes.
                    // - Remove found holes from current hole list
                    Polygon2D      polygonForRendering     = actFillingPolygon;
                    Polygon2D      polygonForTriangulation = actFillingPolygon.Clone();
                    List <Vector2> cutPoints = new List <Vector2>();
                    foreach (Polygon2D actHole in correspondingHoles)
                    {
                        holePolygons.Remove(actHole);
                        polygonForRendering     = polygonForRendering.MergeWithHole(actHole, Polygon2DMergeOptions.Default, cutPoints);
                        polygonForTriangulation = polygonForTriangulation.MergeWithHole(actHole, new Polygon2DMergeOptions()
                        {
                            MakeMergepointSpaceForTriangulation = true
                        });
                    }

                    loopPolygon++;
                    int actBaseIndex = (int)tempStructure.CountVertices;

                    EdgeOrder edgeOrder = polygonForRendering.EdgeOrder;
                    float     edgeSize  = edgeOrder == EdgeOrder.CounterClockwise ? 0.1f : 0.4f;

                    // Append all vertices to temporary VertexStructure
                    for (int loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                    {
                        // Calculate 3d location and texture coordinate
                        Vector3 actVertexLocation = new Vector3(
                            polygonForRendering.Vertices[loop].X,
                            0f,
                            polygonForRendering.Vertices[loop].Y);
                        Vector2 actTexCoord = new Vector2(
                            (polygonForRendering.Vertices[loop].X - polygonForRendering.BoundingBox.Location.X) / polygonForRendering.BoundingBox.Size.X,
                            (polygonForRendering.Vertices[loop].Y - polygonForRendering.BoundingBox.Location.Y) / polygonForRendering.BoundingBox.Size.Y);
                        if (float.IsInfinity(actTexCoord.X) || float.IsNaN(actTexCoord.X))
                        {
                            actTexCoord.X = 0f;
                        }
                        if (float.IsInfinity(actTexCoord.Y) || float.IsNaN(actTexCoord.Y))
                        {
                            actTexCoord.Y = 0f;
                        }

                        // Append the vertex to the result
                        tempStructure.AddVertex(
                            new Vertex(
                                actVertexLocation,
                                m_geometryOptions.SurfaceVertexColor,
                                actTexCoord,
                                new Vector3(0f, 1f, 0f)));
                    }

                    // Generate cubes on each vertex if requested
                    if (m_geometryOptions.GenerateCubesOnVertices)
                    {
                        for (int loop = 0; loop < polygonForRendering.Vertices.Count; loop++)
                        {
                            Color4 colorToUse      = Color4.GreenColor;
                            float  pointRenderSize = 0.1f;
                            if (cutPoints.Contains(polygonForRendering.Vertices[loop]))
                            {
                                colorToUse      = Color4.RedColor;
                                pointRenderSize = 0.15f;
                            }

                            Vector3 actVertexLocation = new Vector3(
                                polygonForRendering.Vertices[loop].X,
                                0f,
                                polygonForRendering.Vertices[loop].Y);
                            tempSurface.BuildCube24V(actVertexLocation, pointRenderSize, colorToUse);
                        }
                    }

                    // Triangulate the polygon
                    IEnumerable <int> triangleIndices = polygonForTriangulation.TriangulateUsingCuttingEars();
                    if (triangleIndices == null)
                    {
                        continue;
                    }
                    if (triangleIndices == null)
                    {
                        throw new SeeingSharpGraphicsException("Unable to triangulate given PathGeometry object!");
                    }

                    // Append all triangles to the temporary structure
                    using (IEnumerator <int> indexEnumerator = triangleIndices.GetEnumerator())
                    {
                        while (indexEnumerator.MoveNext())
                        {
                            int index1 = indexEnumerator.Current;
                            int index2 = 0;
                            int index3 = 0;

                            if (indexEnumerator.MoveNext())
                            {
                                index2 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }
                            if (indexEnumerator.MoveNext())
                            {
                                index3 = indexEnumerator.Current;
                            }
                            else
                            {
                                break;
                            }

                            tempSurface.AddTriangle(
                                (int)(actBaseIndex + index3),
                                (int)(actBaseIndex + index2),
                                (int)(actBaseIndex + index1));
                        }
                    }
                }
            }

            // Make volumetric outlines
            int triangleCountWithoutSide = tempSurface.CountTriangles;

            if (m_geometryOptions.MakeVolumetricText)
            {
                float volumetricTextDepth = m_geometryOptions.VolumetricTextDepth;
                if (m_geometryOptions.VerticesScaleFactor > 0f)
                {
                    volumetricTextDepth = volumetricTextDepth / m_geometryOptions.VerticesScaleFactor;
                }

                // Add all side surfaces
                foreach (Polygon2D actPolygon in geometryExtruder.GeneratedPolygons)
                {
                    foreach (Line2D actLine in actPolygon.Lines)
                    {
                        tempSurface.BuildRect4V(
                            new Vector3(actLine.StartPosition.X, -volumetricTextDepth, actLine.StartPosition.Y),
                            new Vector3(actLine.EndPosition.X, -volumetricTextDepth, actLine.EndPosition.Y),
                            new Vector3(actLine.EndPosition.X, 0f, actLine.EndPosition.Y),
                            new Vector3(actLine.StartPosition.X, 0f, actLine.StartPosition.Y),
                            m_geometryOptions.VolumetricSideSurfaceVertexColor);
                    }
                }
            }

            // Do also make back surface?
            if (m_geometryOptions.MakeBackSurface)
            {
                for (int loop = 0; loop < triangleCountWithoutSide; loop++)
                {
                    Triangle triangle     = tempSurface.Triangles[loop];
                    Vertex   vertex0      = tempStructure.Vertices[triangle.Index1];
                    Vertex   vertex1      = tempStructure.Vertices[triangle.Index2];
                    Vertex   vertex2      = tempStructure.Vertices[triangle.Index3];
                    Vector3  changeVector = new Vector3(0f, -m_geometryOptions.VolumetricTextDepth, 0f);

                    tempSurface.AddTriangle(
                        vertex2.Copy(vertex2.Position - changeVector, Vector3.Negate(vertex2.Normal)),
                        vertex1.Copy(vertex1.Position - changeVector, Vector3.Negate(vertex1.Normal)),
                        vertex0.Copy(vertex0.Position - changeVector, Vector3.Negate(vertex0.Normal)));
                }
            }

            // TODO: Make this configurable
            tempStructure.ToggleCoordinateSystem();

            // Scale the text using given scale factor
            if (m_geometryOptions.VerticesScaleFactor > 0f)
            {
                Matrix4x4 scaleMatrix = Matrix4x4.CreateScale(
                    m_geometryOptions.VerticesScaleFactor,
                    m_geometryOptions.VerticesScaleFactor,
                    m_geometryOptions.VerticesScaleFactor);

                Matrix4Stack transformMatrix = new Matrix4Stack(scaleMatrix);
                transformMatrix.TransformLocal(m_geometryOptions.VertexTransform);

                tempStructure.UpdateVerticesUsingRelocationFunc((actVector) => Vector3.Transform(actVector, transformMatrix.Top));
            }

            // Calculate all normals before adding to target structure
            if (m_geometryOptions.CalculateNormals)
            {
                tempStructure.CalculateNormalsFlat();
            }

            // Merge temporary structure to target structure
            m_targetSurface.AddStructure(tempStructure);

            return(SDX.Result.Ok);
        }