예제 #1
0
 public SourceMap(World world)
 {
     this.world = world;
     Commands.Instance.AddCommand("movedebug", new CommandDelegate(MoveDebug_f));
     //redCube.Color = new Color4[6];
     //for (int i = 0; i < 6; i++)
     //{
     //    redCube.Color[i] = new Color4(1.0f, 0.0f, 0.0f);
     //}
     //ambientLightTexture = new Texture(Renderer.Instance.device, 256, 256, 0, Usage.Dynamic | Usage.WriteOnly, Format.A16B16G16R16F, Pool.Default);
 }
예제 #2
0
        // Hook displacements into the bsp tree
        static void DispTreeLeafnum(World world)
        {
            //
            // get the number of displacements per leaf
            //
            List<dDispTri> tris = new List<dDispTri>();
            world.dispCollTrees = new DispCollTree[world.DispIndexToFaceIndex.Length];
            List<dDispVert> verts = new List<dDispVert>();
            int currTri = 0, currVert = 0;
            for (int i = 0; i < world.DispIndexToFaceIndex.Length; i++)
            {
                int j;
                int faceIndex = world.DispIndexToFaceIndex[i];
                int dispId = world.faces_t[faceIndex].dispinfo;
                ddispinfo_t info = world.ddispinfos[dispId];

                int power = info.power;
                int nVerts = (((1 << (power)) + 1) * ((1 << (power)) + 1));
                verts.Clear();
                // fail code
                for (j = 0; j < nVerts; j++)
                {
                    verts.Add(world.dispVerts[j + currVert]);
                }
                currVert += nVerts;

                int nTris = ((1 << (power)) * (1 << (power)) * 2);
                tris.Clear();
                for (j = 0; j < nTris; j++)
                {
                    tris.Add(world.dispTris[j + currTri]);
                }
                currTri += nTris;

                Displacement displace = new Displacement();
                displace.Surface = new DispSurface();
                DispSurface dispSurf = displace.Surface;
                dispSurf.m_PointStart = info.startPosition;
                dispSurf.m_Contents = info.contents;

                displace.InitDispInfo(info.power, info.minTess, info.smoothingAngle, verts, tris);

                dispSurf.m_Index = faceIndex;
                face_t face = world.faces_t[faceIndex];

                if (face.numedges > 4)
                    continue;

                Vector3[] surfPoints = new Vector3[4];
                dispSurf.m_PointCount = face.numedges;

                for (j = 0; j < face.numedges; j++)
                {
                    int eIndex = world.surfEdges[face.firstedge + j];
                    if (eIndex < 0)
                        surfPoints[j] = world.verts[world.edges[-eIndex].v[1]].position;
                    else
                        surfPoints[j] = world.verts[world.edges[eIndex].v[0]].position;
                }

                dispSurf.m_Points = surfPoints;
                dispSurf.FindSurfPointStartIndex();
                dispSurf.AdjustSurfPointData();

                //
                // generate the collision displacement surfaces
                //
                world.dispCollTrees[i] = new DispCollTree();
                DispCollTree dispTree = world.dispCollTrees[i];

                //
                // check for null faces, should have been taken care of in vbsp!!!
                //
                if (dispSurf.m_PointCount != 4)
                    continue;

                displace.Create();

                // new collision
                dispTree.Create(displace);

                DispTreeLeafnum_r(world, faceIndex, i, 0);
            }
        }
예제 #3
0
        static void createDispSurface(Face face, ddispinfo_t dispInfo, World map, int faceIndex)
        {
            face.HasDisplacement = true;
            Face actualFace = face;
            int ndx = faceIndex;
            while (actualFace.face_t.origFace > 0 && actualFace.face_t.origFace != ndx)
            {
                ndx = actualFace.face_t.origFace;
                actualFace = world.faces_t[actualFace.face_t.origFace].face;
            }
            actualFace.HasDisplacement = true;
            actualFace.DisplaceFaces = new int[] { faceIndex };

            face.displace_offset = world.verts.Count;

            //// Get the texture vectors and offsets.  These are used to calculate
            //// texture coordinates
            Vector3 texU = new Vector3(face.texinfo.textureVecs[0].X,
                     face.texinfo.textureVecs[0].Y,
                     face.texinfo.textureVecs[0].Z);
            float texUOffset = face.texinfo.textureVecs[0].W;

            Vector3 texV = new Vector3(face.texinfo.textureVecs[1].X,
                     face.texinfo.textureVecs[1].Y,
                     face.texinfo.textureVecs[1].Z);
            float texVOffset = face.texinfo.textureVecs[1].W;

            // Get the base vertices for this face
            Vector3[] vertices = new Vector3[face.nVerts];
            for (int i = 0; i < face.nVerts; i++)
            {
                vertices[i] = world.verts[face.VertexOffset + i].position;
            }

            // Rotate the base coordinates for the surface until the first vertex
            // matches the start position
            float minDist = float.MaxValue;
            int minIndex = 0;
            for (int i = 0; i < 4; i++)
            {
                // Calculate the distance of the start position from this vertex
                float dist = (world.verts[face.VertexOffset + i].position - dispInfo.startPosition).Length();// * 0.0254f).Length();

                // If this is the smallest distance we've seen, remember it
                if (dist < minDist)
                {
                    minDist = dist;
                    minIndex = i;
                }
            }

            // Rotate the displacement surface quad until we get the starting vertex
            // in the 0th position
            for (int i = 0; i < minIndex; i++)
            {
                Vector3 temp = vertices[0];
                vertices[0] = vertices[1];
                vertices[1] = vertices[2];
                vertices[2] = vertices[3];
                vertices[3] = temp;
            }

            // Calculate the vectors for the left and right edges of the surface
            // (remembering that the surface is wound clockwise)
            Vector3 leftEdge = vertices[1] - vertices[0];
            Vector3 rightEdge = vertices[2] - vertices[3];

            // Calculate the number of vertices along each edge of the surface
            int numEdgeVertices = (1 << dispInfo.power) + 1;

            // Calculate the subdivide scale, which will tell us how far apart to
            // put each vertex (relative to the length of the surface's edges)
            double subdivideScale = 1.0f / (double)(numEdgeVertices - 1);

            // Calculate the step size between vertices on the left and right edges
            Vector3 leftEdgeStep = Vector3.Multiply(leftEdge, (float)subdivideScale);
            Vector3 rightEdgeStep = Vector3.Multiply(rightEdge, (float)subdivideScale);

            // Remember the first vertex index in the vertex array
            uint firstVertex = (uint)world.verts.Count;

            float lightdeltaU = (1f) / (numEdgeVertices - 1);
            float lightdeltaV = (1f) / (numEdgeVertices - 1);

            float texUScale = 1.0f / (float)face.texinfo.texdata_t.width;
            float texVScale = 1.0f / (float)face.texinfo.texdata_t.height;

            // Temporary lists for accumulating the pars of a full VertexPositionTexturedNormalLightmap
            List<Vector3> verts = new List<Vector3>();
            List<Vector2> texcoords = new List<Vector2>();
            List<Vector2> lightcoords = new List<Vector2>();

            // Generate the displaced vertices (this technique comes from the
            // Source SDK)
            for (int i = 0; i < numEdgeVertices; i++)
            {
                // Calculate the two endpoints for this section of the surface
                Vector3 leftEnd = Vector3.Multiply(leftEdgeStep, i);
                leftEnd += vertices[0];
                Vector3 rightEnd = Vector3.Multiply(rightEdgeStep, i);
                rightEnd += vertices[3];

                // Now, get the vector from left to right, and subdivide it as well
                Vector3 leftRightSeg = rightEnd - leftEnd;
                Vector3 leftRightStep = Vector3.Multiply(leftRightSeg, (float)subdivideScale);

                // Generate the vertices for this section
                for (int j = 0; j < numEdgeVertices; j++)
                {
                    // Get the displacement info for this vertex
                    uint dispVertIndex = (uint)Math.Abs(dispInfo.DispVertStart);
                    dispVertIndex += (uint)(i * numEdgeVertices + j);
                    dDispVert dispVertInfo = world.dispVerts[(int)dispVertIndex];

                    // Calculate the flat vertex
                    Vector3 flatVertex = leftRightStep;
                    flatVertex = Vector3.Multiply(flatVertex, j) + leftEnd;

                    // Calculate the displaced vertex
                    Vector3 dispVertex = dispVertInfo.vec;
                    dispVertex = Vector3.Multiply(dispVertex, (float)(dispVertInfo.dist)) + flatVertex;
                    verts.Add(dispVertex);

                    // Calculate the texture coordinates for this vertex.  Texture
                    // coordinates are calculated using a planar projection, so we need
                    // to use the non-displaced vertex position here
                    float u = Vector3.Dot(texU, flatVertex) + texUOffset;
                    u *= texUScale;
                    float v = Vector3.Dot(texV, flatVertex) + texVOffset;
                    v *= texVScale;
                    Vector2 texCoord = new Vector2(u, v);
                    texcoords.Add(texCoord);

                    // Generate lightmap coordinates
                    float lightmapU = (lightdeltaU * j * face.face_t.LightmapTextureSizeInLuxels[0]) + face.lightOffsetX + 0.5f; // pixel space
                    float lightmapV = (lightdeltaV * i * face.face_t.LightmapTextureSizeInLuxels[1]) + face.lightOffsetY + 0.5f; // pixel space
                    lightmapU /= LightmapSize.Width;
                    lightmapV /= LightmapSize.Height;
                    lightcoords.Add(new Vector2(lightmapU, lightmapV));

                    // Get the texture blend parameter for this vertex as well
                    //float eh = (float)(dispVertInfo.alpha / 255.0);
                }
            }

            List<Vector3> normals = new List<Vector3>();
            // Calculate normals at each vertex (this is adapted from the Source SDK,
            // including the two helper functions)
            for (int i = 0; i < numEdgeVertices; i++)
            {
                for (int j = 0; j < numEdgeVertices; j++)
                {
                    // See which of the 4 possible edges (left, up, right, or down) are
                    // incident on this vertex
                    byte edgeBits = 0;
                    for (int k = 0; k < 4; k++)
                    {
                        if (doesEdgeExist(j, i, (int)k, numEdgeVertices))
                            edgeBits |= (byte)(1 << (byte)k);
                    }

                    // Calculate the normal based on the adjacent edges
                    Vector3 normal = getNormalFromEdges(j, i, edgeBits,
                                                numEdgeVertices, verts);

                    // Add the normal to the normal array
                    normals.Add(normal);
                }
            }

            Vector3[] BBox = new Vector3[2];
            BBox[0] = Vector3.Zero;
            BBox[1] = Vector3.Zero;
            // Build real vertices && BBox
            for (int i = 0; i < verts.Count; i++)
            {
                BBox[0] = Vector3.Minimize(verts[i], BBox[0]);
                BBox[1] = Vector3.Maximize(verts[i], BBox[1]);
                VertexPositionNormalTexturedLightmap vert = new VertexPositionNormalTexturedLightmap(verts[i], normals[i], texcoords[i], lightcoords[i]);
                world.verts.Add(vert);
            }

            face.BBox = BBox;

            // Build indices
            List<uint> indices = new List<uint>();
            // Now, triangulate the surface (this technique comes from the Source SDK)
            for (int i = 0; i < numEdgeVertices - 1; i++)
            {
                for (int j = 0; j < numEdgeVertices - 1; j++)
                {
                    // Get the current vertex index (local to this surface)
                    uint index = (uint)(i * numEdgeVertices + j);
                    //if (index + numEdgeVertices + 1 + firstVertex > map.disp_vertex_array.Count - 1 || index + firstVertex < firstVertex)
                    //{
                    //    int test = 2;
                    //}
                    // See if this index is odd
                    if ((index % 2) == 1)
                    {
                        // Add the vertex offset (so we reference this surface's
                        // vertices in the array)
                        index += firstVertex;

                        // Create two triangles on this vertex from top-left to
                        // bottom-right
                        indices.Add((uint) index + 1);
                        indices.Add((uint) index);

                        indices.Add((uint) index + (uint)numEdgeVertices);
                        indices.Add((uint) index + (uint)numEdgeVertices + 1);
                        indices.Add((uint) index + 1);

                        indices.Add((uint)index + (uint)numEdgeVertices);
                    }
                    else
                    {
                        // Add the vertex offset (so we reference this surface's
                        // vertices in the array)
                        index += firstVertex;

                        // Create two triangles on this vertex from bottom-left to
                        // top-right
                        indices.Add((uint) index + (uint)numEdgeVertices + 1);
                        indices.Add((uint)index);

                        indices.Add((uint)index + (uint)numEdgeVertices);
                        indices.Add((uint)index + 1);
                        indices.Add((uint) index);

                        indices.Add((uint)index + (uint)numEdgeVertices + 1);
                    }
                }
                //face.VertexOffset = firstVertex;

            }

            face.nVerts = world.verts.Count - (int)firstVertex;
            face.indices = indices.ToArray();

            //face.nDisplace = map.disp_primitive_set.Count - face.displace_offset;
        }
예제 #4
0
        public static void LoadWorldMap(string filename)
        {
            FileStream stream;
            // Check filecache
            if (FileCache.Instance.Contains(filename))
            {
                stream = File.OpenRead(FileCache.Instance.GetFile(filename).FullName);
            }
            // Check absolute path
            else if (File.Exists(filename))
            {
                stream = File.OpenRead(filename);
            }
            else
            {
                Common.Instance.Error(string.Format("LoadWorldMap: {0} not found", filename));
                return;
            }
            world = new World();

            BinaryReader br = new BinaryReader(stream, Encoding.UTF8);

            // Read header..
            int magic = (('P' << 24) + ('S' << 16) + ('B' << 8) + 'V');
            int id = br.ReadInt32();
            if (id != magic)
            {
                Common.Instance.Error(string.Format("LoadWorldMap:{0}: Wrong magic number", filename));
                return;
            }

            Header sHeader = new Header();
            sHeader.ident = id;
            sHeader.version = br.ReadInt32();

            // GoldSrc map
            if (sHeader.version == 30)
            {
                GoldSrcParser.LoadWorldMap(sHeader, br);
                return;
            }

            sHeader.lumps = new Lump_t[Header.HEADER_LUMPS];
            for (int i = 0; i < Header.HEADER_LUMPS; i++)
            {
                Lump_t lump;
                lump.fileofs = br.ReadInt32();
                lump.filelen = br.ReadInt32();
                lump.version = br.ReadInt32();
                lump.fourCC = br.ReadChars(4);

                sHeader.lumps[i] = lump;
            }

            sHeader.mapRevision = br.ReadInt32();
            LoadWorldLights(br, sHeader);
            LoadLightGrids(br, sHeader);
            LoadLightmaps(br, sHeader);
            LoadPak(br, sHeader);
            LoadTextures(br, sHeader);
            LoadPlanes(br, sHeader);
            LoadDisplacement(br, sHeader);
            LoadFaces(br, sHeader); // Req: planes & texinfos & light & displacemtn
            LoadLeafBrushes(br, sHeader);
            LoadBrushes(br, sHeader);
            LoadLeafFaces(br, sHeader);
            LoadNodesAndLeafs(br, sHeader); // Req: planes
            LoadGameAndProps(br, sHeader); // Req: leafs
            LoadModels(br, sHeader);
            LoadEntities(br, sHeader);
            LoadVisibility(br, sHeader);

            DispTreeLeafnum(world);
            SourceMap map = new SourceMap(world);
            map.Init();
            Renderer.Instance.SourceMap = map;
            long now = HighResolutionTimer.Ticks;
            for (int i = 0; i < world.sourceProps.Count; i++)
            {
                world.sourceProps[i].UpdateMesh();
            }
            float propLightingTime = (float)(HighResolutionTimer.Ticks - now)  / HighResolutionTimer.Frequency;

            Common.Instance.WriteLine("Finished prop lighting: {0:0.000}s", propLightingTime);
        }
예제 #5
0
        static void DispTreeLeafnum_r(World world, int faceid, int collId, int nodeIndex)
        {
            while (true)
            {
                //
                // leaf
                //
                if (nodeIndex < 0)
                {
                    //
                    // get leaf node
                    //
                    int leadIndex = -1 - nodeIndex;
                    dleaf_t pLeaf = world.leafs[leadIndex];

                    if (pLeaf.DisplacementIndexes != null)
                    {
                        KeyValuePair<int, int>[] indexes = pLeaf.DisplacementIndexes;
                        KeyValuePair<int, int>[] newid = new KeyValuePair<int, int>[indexes.Length + 1];
                        indexes.CopyTo(newid, 0);
                        newid[newid.Length - 1] = new KeyValuePair<int,int>(faceid, collId);
                        pLeaf.DisplacementIndexes = newid;
                    }
                    else
                    {
                        pLeaf.DisplacementIndexes = new KeyValuePair<int,int>[] { new KeyValuePair<int,int>(faceid, collId) };
                    }

                    return;
                }

                //
                // choose side(s) to traverse
                //
                dnode_t pNode =  world.nodes[nodeIndex];
                cplane_t pPlane = pNode.plane;

                // get box position relative to the plane
                Vector3 min = world.faces[faceid].BBox[0];
                Vector3 max = world.faces[faceid].BBox[1];
                int sideResult = Common.Instance.BoxOnPlaneSide(ref min, ref max, pPlane);

                // front side
                if (sideResult == 1)
                {
                    nodeIndex = pNode.children[0];
                }
                // back side
                else if (sideResult == 2)
                {
                    nodeIndex = pNode.children[1];
                }
                // split
                else
                {
                    DispTreeLeafnum_r(world, faceid, collId, pNode.children[0]);
                    nodeIndex = pNode.children[1];
                }

            }
        }