예제 #1
0
        private void ReadFaces(BSPParser bspParser, VPKParser vpkParser, CancellationToken cancelToken, Action <float, string> onProgressChanged = null)
        {
            for (int i = 0; i < Mathf.RoundToInt(bspParser.faces.Length * FaceLoadPercent); i++)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return;
                }

                dface_t face = bspParser.faces[i];

                texflags currentTexFlags = GetFaceTextureFlags(face, bspParser);
                string   textureLocation = GetFaceTextureLocation(face, bspParser);

                if (!IsUndesiredTexture(textureLocation, currentTexFlags))
                {
                    FaceMesh currentFace = new FaceMesh();
                    currentFace.textureFlag = currentTexFlags;
                    currentFace.lightmapKey = bspParser.faces[i].lightofs;

                    currentFace.faceName = textureLocation;
                    currentFace.material = VMTData.GrabVMT(bspParser, vpkParser, textureLocation);
                    currentFace.meshData = MakeFace(bspParser, face);
                    AddFaceMesh(currentFace, combineMeshesWithSameTexture);
                }

                totalItemsLoaded++;
                onProgressChanged?.Invoke(PercentLoaded, currentMessage);
            }
        }
예제 #2
0
        private string GetFaceTextureLocation(dface_t face, BSPParser bspParser)
        {
            int faceTexInfoIndex     = face.texinfo;
            int texDataIndex         = bspParser.texInfo[faceTexInfoIndex].texdata;
            int nameStringTableIndex = bspParser.texData[texDataIndex].nameStringTableID;

            return(bspParser.textureStringData[nameStringTableIndex]);
        }
예제 #3
0
        private texflags GetFaceTextureFlags(dface_t face, BSPParser bspParser)
        {
            texflags currentTexFlag = texflags.SURF_SKIP;

            if (bspParser.texInfo != null && face.texinfo < bspParser.texInfo.Length)
            {
                currentTexFlag = (texflags)bspParser.texInfo[face.texinfo].flags;
            }
            return(currentTexFlag);
        }
예제 #4
0
        public MeshHelpers.MeshData MakeFace(BSPParser bspParser, dface_t face)
        {
            #region Get all vertices of face
            List <Vector3> surfaceVertices  = new List <Vector3>();
            List <Vector3> originalVertices = new List <Vector3>();
            List <Vector3> normals          = new List <Vector3>();
            for (int i = 0; i < face.numedges; i++)
            {
                ushort[] currentEdge = bspParser.edges[Mathf.Abs(bspParser.surfedges[face.firstedge + i])].v;
                Vector3  point1 = bspParser.vertices[currentEdge[0]], point2 = bspParser.vertices[currentEdge[1]];
                Vector3  planeNormal = bspParser.planes[face.planenum].normal;

                point1 = new Vector3(point1.x, point1.y, point1.z);
                point2 = new Vector3(point2.x, point2.y, point2.z);

                if (bspParser.surfedges[face.firstedge + i] >= 0)
                {
                    if (surfaceVertices.IndexOf(point1) < 0)
                    {
                        surfaceVertices.Add(point1);
                        normals.Add(planeNormal);
                    }
                    originalVertices.Add(point1);

                    if (surfaceVertices.IndexOf(point2) < 0)
                    {
                        surfaceVertices.Add(point2);
                        normals.Add(planeNormal);
                    }
                    originalVertices.Add(point2);
                }
                else
                {
                    if (surfaceVertices.IndexOf(point2) < 0)
                    {
                        surfaceVertices.Add(point2);
                        normals.Add(planeNormal);
                    }
                    originalVertices.Add(point2);

                    if (surfaceVertices.IndexOf(point1) < 0)
                    {
                        surfaceVertices.Add(point1);
                        normals.Add(planeNormal);
                    }
                    originalVertices.Add(point1);
                }
            }
            #endregion

            #region Apply Displacement
            if (face.dispinfo > -1)
            {
                ddispinfo_t disp  = bspParser.dispInfo[face.dispinfo];
                int         power = Mathf.RoundToInt(Mathf.Pow(2, disp.power));

                List <Vector3> dispVertices = new List <Vector3>();
                Vector3        startingPosition = surfaceVertices[0];
                Vector3        topCorner = surfaceVertices[1], topRightCorner = surfaceVertices[2], rightCorner = surfaceVertices[3];

                #region Setting Orientation
                Vector3 dispStartingVertex = disp.startPosition;
                if (Vector3.Distance(dispStartingVertex, topCorner) < 0.01f)
                {
                    Vector3 tempCorner = startingPosition;

                    startingPosition = topCorner;
                    topCorner        = topRightCorner;
                    topRightCorner   = rightCorner;
                    rightCorner      = tempCorner;
                }
                else if (Vector3.Distance(dispStartingVertex, rightCorner) < 0.01f)
                {
                    Vector3 tempCorner = startingPosition;

                    startingPosition = rightCorner;
                    rightCorner      = topRightCorner;
                    topRightCorner   = topCorner;
                    topCorner        = tempCorner;
                }
                else if (Vector3.Distance(dispStartingVertex, topRightCorner) < 0.01f)
                {
                    Vector3 tempCorner = startingPosition;

                    startingPosition = topRightCorner;
                    topRightCorner   = tempCorner;
                    tempCorner       = rightCorner;
                    rightCorner      = topCorner;
                    topCorner        = tempCorner;
                }
                #endregion

                int orderNum = 0;
                #region Method 13 (The one and only two)
                Vector3 leftSide = (topCorner - startingPosition), rightSide = (topRightCorner - rightCorner);
                float   leftSideLineSegmentationDistance = leftSide.magnitude / power, rightSideLineSegmentationDistance = rightSide.magnitude / power;
                for (int line = 0; line < (power + 1); line++)
                {
                    for (int point = 0; point < (power + 1); point++)
                    {
                        Vector3 leftPoint      = (leftSide.normalized * line * leftSideLineSegmentationDistance) + startingPosition;
                        Vector3 rightPoint     = (rightSide.normalized * line * rightSideLineSegmentationDistance) + rightCorner;
                        Vector3 currentLine    = rightPoint - leftPoint;
                        Vector3 pointDirection = currentLine.normalized;
                        float   pointSideSegmentationDistance = currentLine.magnitude / power;

                        Vector3 pointA = leftPoint + (pointDirection * pointSideSegmentationDistance * point);

                        Vector3 dispDirectionA = bspParser.dispVerts[disp.DispVertStart + orderNum].vec;
                        dispVertices.Add(pointA + (dispDirectionA * bspParser.dispVerts[disp.DispVertStart + orderNum].dist));
                        orderNum++;
                    }
                }
                #endregion

                surfaceVertices = dispVertices;
            }
            #endregion

            #region Triangulate
            List <int> triangleIndices = new List <int>();

            if (face.dispinfo > -1)
            {
                ddispinfo_t disp  = bspParser.dispInfo[face.dispinfo];
                int         power = Mathf.RoundToInt(Mathf.Pow(2, disp.power));

                #region Method 12 Triangulation
                for (int row = 0; row < power; row++)
                {
                    for (int col = 0; col < power; col++)
                    {
                        int currentLine   = row * (power + 1);
                        int nextLineStart = (row + 1) * (power + 1);

                        triangleIndices.Add(currentLine + col);
                        triangleIndices.Add(currentLine + col + 1);
                        triangleIndices.Add(nextLineStart + col);

                        triangleIndices.Add(currentLine + col + 1);
                        triangleIndices.Add(nextLineStart + col + 1);
                        triangleIndices.Add(nextLineStart + col);
                    }
                }
                #endregion
            }
            else
            {
                for (int i = 0; i < (originalVertices.Count / 2) - 0; i++)
                {
                    int firstOrigIndex = i * 2, secondOrigIndex = (i * 2) + 1, thirdOrigIndex = 0;
                    int firstIndex  = surfaceVertices.IndexOf(originalVertices[firstOrigIndex]);
                    int secondIndex = surfaceVertices.IndexOf(originalVertices[secondOrigIndex]);
                    int thirdIndex  = surfaceVertices.IndexOf(originalVertices[thirdOrigIndex]);

                    triangleIndices.Add(thirdIndex);
                    triangleIndices.Add(secondIndex);
                    triangleIndices.Add(firstIndex);
                }
            }
            #endregion

            #region Map UV Points
            Vector3 s = Vector3.zero, t = Vector3.zero;
            float   xOffset = 0, yOffset = 0;

            try
            {
                s       = new Vector3(bspParser.texInfo[face.texinfo].textureVecs[0][0], bspParser.texInfo[face.texinfo].textureVecs[0][1], bspParser.texInfo[face.texinfo].textureVecs[0][2]);
                t       = new Vector3(bspParser.texInfo[face.texinfo].textureVecs[1][0], bspParser.texInfo[face.texinfo].textureVecs[1][1], bspParser.texInfo[face.texinfo].textureVecs[1][2]);
                xOffset = bspParser.texInfo[face.texinfo].textureVecs[0][3];
                yOffset = bspParser.texInfo[face.texinfo].textureVecs[1][3];
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }

            Vector2[] uvPoints = new Vector2[surfaceVertices.Count];
            int       textureWidth = 0, textureHeight = 0;

            try
            {
                textureWidth  = bspParser.texData[bspParser.texInfo[face.texinfo].texdata].width;
                textureHeight = bspParser.texData[bspParser.texInfo[face.texinfo].texdata].height;
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }

            for (int i = 0; i < uvPoints.Length; i++)
            {
                uvPoints[i] = new Vector2((Vector3.Dot(surfaceVertices[i], s) + xOffset) / textureWidth, (textureHeight - (Vector3.Dot(surfaceVertices[i], t) + yOffset)) / textureHeight);
            }
            #endregion

            #region Organize Mesh Data
            MeshHelpers.MeshData meshData = new MeshHelpers.MeshData();
            meshData.vertices  = surfaceVertices.ToArray();
            meshData.triangles = triangleIndices.ToArray();
            meshData.normals   = normals.ToArray();
            meshData.uv        = uvPoints;
            #endregion

            #region Clear References
            surfaceVertices.Clear();
            surfaceVertices = null;
            originalVertices.Clear();
            originalVertices = null;
            normals.Clear();
            normals = null;
            triangleIndices.Clear();
            triangleIndices = null;
            uvPoints        = null;
            #endregion

            return(meshData);
        }