예제 #1
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);
        }
예제 #2
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();
            }
        }