Beispiel #1
0
        public static string CreateMtlFileForBsp(BspTag tag)
        {
            var sb = new StringBuilder();

            var alreadyGenerated = new HashSet <uint>();

            for (var i = 0; i < tag.RenderChunks.Length; i++)
            {
                var model = tag.RenderChunks[i].Model;

                foreach (var mesh in model.Meshes)
                {
                    var matId = mesh.Shader.Id + 1;

                    if (alreadyGenerated.Contains(matId))
                    {
                        continue;
                    }

                    var color = GenerateRandomColor();

                    sb.AppendLine($"newmtl {matId}");
                    sb.AppendLine($"Kd {(color.R / 255f).ToString("0.000000")} {(color.G / 255f).ToString("0.000000")} {(color.B / 255f).ToString("0.000000")}");
                    sb.AppendLine($"Ka {(color.R / 255f).ToString("0.000000")} {(color.G / 255f).ToString("0.000000")} {(color.B / 255f).ToString("0.000000")}");
                    sb.AppendLine("Ks 1.000 1.000 1.000");
                    sb.AppendLine("Ns 10.000");
                    sb.AppendLine("");

                    alreadyGenerated.Add(matId);
                }
            }


            return(sb.ToString());
        }
        private static void ProcessRenderChunks(BspTag bsp, BspTagData tagData)
        {
            tagData.RenderModels = new BspTagData.RenderModel[bsp.RenderChunks.Length];

            for (var c = 0; c < bsp.RenderChunks.Length; c++)
            {
                var chunk = bsp.RenderChunks[c];

                if (chunk.Resources.Length < 9)
                {
                    // TODO investigate when differing amount of resources
                    // Skip if we don't have the right data setup
                    var skipModel = new BspTagData.RenderModel();
                    skipModel.Meshes        = new List <Mesh>();
                    tagData.RenderModels[c] = skipModel;
                    continue;
                }

                var verts = ProcessVerticies(chunk);

                var partResource = chunk.Resources[0];
                var partData     = partResource.Data.Span;
                var partCount    = partData.Length / 72;

                // Process face data
                var faceResource = chunk.Resources[2];
                var faceData     = faceResource.Data.Span;

                var meshes = new List <Mesh>(partCount);

                for (var i = 0; i < partCount; i++)
                {
                    var start = i * 72;

                    var matId       = partData.ReadUInt16At(start + 4);
                    var indexStart  = partData.ReadUInt16At(start + 6);
                    var indexCount  = partData.ReadUInt16At(start + 8);
                    var elementType = (MeshElementType)partData.ReadUInt16At(start + 2);

                    var mesh = new Mesh();
                    mesh.Verticies          = verts;
                    mesh.Indicies           = new int[indexCount];
                    mesh.MaterialIdentifier = bsp.ModelShaderReferences[matId].ShaderId;
                    mesh.ElementType        = elementType;

                    for (var j = 0; j < indexCount; j++)
                    {
                        var byteStart = (indexStart + j) * 2;

                        mesh.Indicies[j] = faceData.ReadUInt16At(byteStart);
                    }

                    meshes.Add(mesh);
                }

                var model = new BspTagData.RenderModel();
                model.Meshes            = meshes;
                tagData.RenderModels[c] = model;
            }
        }
        public BspTagData ProcessCollisionGeometry(BspTag bsp, BspTagData tagData)
        {
            var block = bsp.CollisionInfos.First();

            var faces = new List <int[]>();

            for (var i = 0; i < block.Faces.Length; i++)
            {
                var face = block.Faces[i];

                var faceVerts = new List <int>(8);

                var currentEdge = block.HalfEdges[face.FirstEdge];

                while (true)
                {
                    int fromVert;
                    int toVert;
                    int nextEdge;

                    if (currentEdge.Face0 == i)
                    {
                        fromVert = currentEdge.Vertex0;
                        toVert   = currentEdge.Vertex1;
                        nextEdge = currentEdge.NextEdge;
                    }
                    else
                    {
                        fromVert = currentEdge.Vertex1;
                        toVert   = currentEdge.Vertex0;
                        nextEdge = currentEdge.PrevEdge;
                    }

                    if (faceVerts.Count == 0)
                    {
                        faceVerts.Add(fromVert);
                    }

                    if (faceVerts[0] == toVert)
                    {
                        break;
                    }

                    faceVerts.Add(toVert);

                    currentEdge = block.HalfEdges[nextEdge];
                }

                faces.Add(faceVerts.ToArray());
            }

            //tagData.Faces = faces.ToArray();

            //tagData.Verticies = block.Verticies
            //    .Select(r => new Vector3(r.x, r.y, r.z))
            //    .Select(v => new Vertex() { Position = v })
            //    .ToArray();

            return(tagData);
        }
Beispiel #4
0
        public static string CreatObjFileForBsp(BspTag tag)
        {
            var sb = new StringBuilder();

            var vertsWritten = 1;

            for (var i = 0; i < tag.RenderChunks.Length; i++)
            {
                var model = tag.RenderChunks[i].Model;
                sb.AppendLine($"o BspChunk.{i}");

                var verts = model.Meshes.First().Verticies;

                foreach (var vert in verts)
                {
                    sb.AppendLine($"v {vert.Position.X.ToString("0.000000")} {vert.Position.Y.ToString("0.000000")} {vert.Position.Z.ToString("0.000000")}");
                }

                foreach (var vert in verts)
                {
                    sb.AppendLine($"vt {vert.TexCoords.X.ToString("0.000000")} {vert.TexCoords.Y.ToString("0.000000")}");
                }

                foreach (var vert in verts)
                {
                    sb.AppendLine($"vn {vert.Normal.X.ToString("0.000000")} {vert.Normal.Y.ToString("0.000000")} {vert.Normal.Z.ToString("0.000000")}");
                }


                foreach (var mesh in model.Meshes)
                {
                    var matId = mesh.Shader.Id + 1;

                    sb.AppendLine($"g BspChunk.{i}.{matId}");
                    sb.AppendLine($"usemtl {matId}");

                    for (var j = 0; j < mesh.Indices.Length; j += 3)
                    {
                        var indicies = (mesh.Indices[j], mesh.Indices[j + 1], mesh.Indices[j + 2]);

                        sb.Append("f");
                        sb.Append($" {indicies.Item1 + vertsWritten}/{indicies.Item1 + vertsWritten}/{indicies.Item1 + vertsWritten}");
                        sb.Append($" {indicies.Item2 + vertsWritten}/{indicies.Item2 + vertsWritten}/{indicies.Item2 + vertsWritten}");
                        sb.Append($" {indicies.Item3 + vertsWritten}/{indicies.Item3 + vertsWritten}/{indicies.Item3 + vertsWritten}");

                        sb.AppendLine("");
                    }
                }

                sb.AppendLine();

                vertsWritten += verts.Length;
            }

            return(sb.ToString());
        }
Beispiel #5
0
        public static string CreatePlanesObj(BspTag tag)
        {
            var sb         = new StringBuilder();
            var vertsAdded = 0;

            Console.WriteLine($"CollisionInfo lengths: {tag.CollisionInfos.Length}");

            sb.AppendLine("o CollisionPlanes");

            foreach (var col in tag.CollisionInfos)
            {
                foreach (var plane in col.Planes)
                {
                    var centroid = plane.Normal * plane.Distance;

                    // Use arbitrary vector to get tangent vector to normal
                    var tempVec   = Vector3.Normalize(new Vector3(plane.Normal.X + 1, plane.Normal.Y, plane.Normal.Z));
                    var tangent   = Vector3.Normalize(Vector3.Cross(plane.Normal, tempVec));
                    var bitangent = Vector3.Cross(plane.Normal, tangent);

                    var upperRight = centroid + tangent + bitangent;
                    var lowerRight = centroid - tangent + bitangent;
                    var upperLeft  = centroid + tangent - bitangent;
                    var lowerLeft  = centroid - tangent - bitangent;

                    sb.AppendLine($"v {upperRight.X.ToString("0.000000")} {upperRight.Y.ToString("0.000000")} {upperRight.Z.ToString("0.000000")}");
                    sb.AppendLine($"v {lowerRight.X.ToString("0.000000")} {lowerRight.Y.ToString("0.000000")} {lowerRight.Z.ToString("0.000000")}");
                    sb.AppendLine($"v {lowerLeft.X.ToString("0.000000")} {lowerLeft.Y.ToString("0.000000")} {lowerLeft.Z.ToString("0.000000")}");
                    sb.AppendLine($"v {upperLeft.X.ToString("0.000000")} {upperLeft.Y.ToString("0.000000")} {upperLeft.Z.ToString("0.000000")}");

                    sb.AppendLine($"f {++vertsAdded} {++vertsAdded} {++vertsAdded} {++vertsAdded}");
                }
            }


            return(sb.ToString());
        }
Beispiel #6
0
 public Entity FromInstancedGeometry(BspTag bsp, BspTag.InstancedGeometryInstance instance)
 {
     return(SceneryFactory.FromInstancedGeometry(this.Map, bsp, instance));
 }
Beispiel #7
0
 public Entity FromBsp(BspTag bsp)
 {
     return(TerrainFactory.FromBspData(this.Map, bsp));
 }
Beispiel #8
0
 public BspTagData(BspTag tag) : base(tag)
 {
 }
Beispiel #9
0
        public static Scenery FromInstancedGeometry(H2vMap map, BspTag bsp, BspTag.InstancedGeometryInstance instance)
        {
            var scenery = new Scenery();

            scenery.FriendlyName = "Geom";

            if (instance.Index >= bsp.InstancedGeometryDefinitions.Length)
            {
                return(scenery);
            }

            var def = bsp.InstancedGeometryDefinitions[instance.Index];

            var transparentMeshes = new List <Mesh <BitmapTag> >(def.Model.Meshes.Length);
            var renderModelMeshes = new List <Mesh <BitmapTag> >(def.Model.Meshes.Length);

            foreach (var mesh in def.Model.Meshes)
            {
                var mat = map.CreateMaterial(mesh);

                var renderMesh = new Mesh <BitmapTag>()
                {
                    Compressed  = mesh.Compressed,
                    ElementType = mesh.ElementType,
                    Indicies    = mesh.Indices,
                    Note        = mesh.Note,
                    RawData     = mesh.RawData,
                    Verticies   = mesh.Verticies,

                    Material = mat
                };

                if (mat.AlphaMap == null)
                {
                    renderModelMeshes.Add(renderMesh);
                }
                else
                {
                    transparentMeshes.Add(renderMesh);
                }
            }

            var comps = new List <Component>();

            comps.Add(new RenderModelComponent(scenery, new Model <BitmapTag>
            {
                Note   = $"[{bsp.Id}] {bsp.Name}//instanced//{instance.Index}",
                Meshes = renderModelMeshes.ToArray(),
                Flags  = ModelFlags.Diffuse | ModelFlags.ReceivesShadows | ModelFlags.IsStatic
            }));

            foreach (var mesh in transparentMeshes)
            {
                comps.Add(new RenderModelComponent(scenery, new Model <BitmapTag>
                {
                    Note   = $"[{bsp.Id}] {bsp.Name}//instanced//{instance.Index}",
                    Meshes = new[] { mesh },
                    Flags  = ModelFlags.IsTransparent | ModelFlags.IsStatic
                }));
            }

            var xform = new TransformComponent(scenery, instance.Position, QuaternionExtensions.From3x3Mat(instance.RotationMatrix))
            {
                Scale = new Vector3(instance.Scale),
            };

            comps.Add(xform);

            if (def.Vertices.Length > 0)
            {
                var geom = PhysicsComponentFactory.CreateStaticGeometry(scenery, xform, def, bsp.Shaders);
                comps.Add(geom);

                comps.Add(new RenderModelComponent(scenery, new Model <BitmapTag>
                {
                    Note        = $"[{bsp.Id}] {bsp.Name}//instanced//{instance.Index}-collision",
                    Meshes      = MeshFactory.GetRenderModel(geom.Collider, new Vector4(0f, 1f, 1f, 1f)),
                    Flags       = ModelFlags.Wireframe | ModelFlags.IsStatic,
                    RenderLayer = RenderLayers.Collision
                }));
            }

            xform.UpdateDerivedData();

            scenery.SetComponents(comps);

            return(scenery);
        }
Beispiel #10
0
        public static Terrain FromBspData(H2vMap map, BspTag tag)
        {
            var terrain = new Terrain();

            terrain.FriendlyName = tag.Name;

            var meshes = new List <ModelMesh>();

            foreach (var chunk in tag.RenderChunks)
            {
                meshes.AddRange(chunk.Model.Meshes);
            }

            var transparentMeshes = new List <Mesh <BitmapTag> >(meshes.Count);
            var renderModelMeshes = new List <Mesh <BitmapTag> >(meshes.Count);

            foreach (var mesh in meshes)
            {
                var mat = map.CreateMaterial(mesh);

                var renderMesh = new Mesh <BitmapTag>()
                {
                    Compressed  = mesh.Compressed,
                    ElementType = mesh.ElementType,
                    Indicies    = mesh.Indices,
                    Note        = mesh.Note,
                    RawData     = mesh.RawData,
                    Verticies   = mesh.Verticies,

                    Material = mat
                };

                if (mat.AlphaMap == null)
                {
                    renderModelMeshes.Add(renderMesh);
                }
                else
                {
                    transparentMeshes.Add(renderMesh);
                }
            }

            var components = new List <Component>();

            components.Add(new RenderModelComponent(terrain, new Model <BitmapTag>
            {
                Meshes = renderModelMeshes.ToArray(),
                Flags  = ModelFlags.Diffuse | ModelFlags.ReceivesShadows | ModelFlags.IsStatic
            }));

            foreach (var mesh in transparentMeshes)
            {
                components.Add(new RenderModelComponent(terrain, new Model <BitmapTag>
                {
                    Meshes = new[] { mesh },
                    Flags  = ModelFlags.IsTransparent | ModelFlags.IsStatic
                }));
            }

            var collisionTerrain = PhysicsComponentFactory.CreateTerrain(terrain, tag.CollisionInfos, tag.Shaders);

            components.Add(collisionTerrain);

            components.Add(new RenderModelComponent(terrain, new Model <BitmapTag>
            {
                Meshes      = MeshFactory.GetRenderModel(collisionTerrain.Collider),
                Flags       = ModelFlags.Wireframe | ModelFlags.IsStatic,
                RenderLayer = RenderLayers.Collision
            }));

            components.Add(new TransformComponent(terrain, Vector3.Zero));

            terrain.SetComponents(components);

            return(terrain);
        }
Beispiel #11
0
        public static string CreateCollisionObj(BspTag tag)
        {
            var sb         = new StringBuilder();
            var vertsAdded = 0;

            Console.WriteLine($"CollisionInfo lengths: {tag.CollisionInfos.Length}");

            sb.AppendLine("o CollisionMesh");

            foreach (var col in tag.CollisionInfos)
            {
                var nextFaceSlot  = 0;
                var faceTexLookup = new Dictionary <int, int>();

                foreach (var face in col.Faces)
                {
                    if (faceTexLookup.ContainsKey(face.ShaderIndex))
                    {
                        continue;
                    }

                    faceTexLookup.Add(face.ShaderIndex, nextFaceSlot + 1);
                    nextFaceSlot++;
                }

                for (var i = 0; i < nextFaceSlot; i++)
                {
                    sb.AppendLine($"vt 0.5 {(i / (float)nextFaceSlot).ToString("0.000000")}");
                }


                var faceIndex = 0;
                for (; faceIndex < col.Faces.Length; faceIndex++)
                {
                    var face  = col.Faces[faceIndex];
                    var verts = new List <ushort>(8);

                    ushort edgeIndex = face.FirstEdge;
                    do
                    {
                        var edge = col.HalfEdges[edgeIndex];

                        verts.Add(edge.Face0 == faceIndex
                            ? edge.Vertex0
                            : edge.Vertex1);

                        edgeIndex = edge.Face0 == faceIndex
                            ? edge.NextEdge
                            : edge.PrevEdge;
                    } while (edgeIndex != face.FirstEdge);

                    var faceTexCoord = faceTexLookup[face.ShaderIndex];

                    foreach (var index in verts)
                    {
                        var vert = col.Vertices[index];
                        sb.AppendLine($"v {vert.x.ToString("0.000000")} {vert.y.ToString("0.000000")} {vert.z.ToString("0.000000")}");
                    }

                    sb.Append($"f");

                    foreach (var vert in verts)
                    {
                        sb.Append(" ");
                        sb.Append($"{++vertsAdded}/{faceTexCoord}");
                    }

                    sb.AppendLine();
                }
            }


            return(sb.ToString());
        }