I am writing a set of classes to read a Quake3 .bsp map into usable C# objects. My first goal is to get the geometry visible. I have already parsed much of the .bsp, all of the data that pertains to faces is available to me. Faces in a Quake 3 map are defined as a face with vertexes, each vertex has a normal, and each face has texture coords, along with other things. These faces are arranged into models, with all of the faces that make up the world geometry in one model. I’m not sure how to composite these faces into a single model, I’m trying to render them on their own just to see something on the screen.
Currently I’m trying to create gameobjects that will render the map for me, and I’m not sure how would be best to do this.
I tried to make one gameobject per face (inefficient, I’m sure) just to get something on the screen and confirm that my data was at least good, but no matter what I do the mesh is not visible. I have set the normals array, uv array, vertex, and triangles up, and I did them in the order recommended in the Mesh script reference. I have logs of the data from the .bsp, and it seems to be good. The vertexes/face data all looks sensible. The classes that pull this data from the .bsp are pretty large, but the problem is likely how I’m constructing the object.
I have a very strong feeling that making one object/mesh perfect is causing my problem, but I’d like to ask the community for a little guidance before I chase a wild goose guessing at a better way. And before somebody asks why I’m parsing Quake3 .bsp, the answer is just for fun. I’m not asking for free code, just some suggestions or pointers as to how to jump this last hurdle.
GameObject GenerateModel(Face face)
{
GameObject faceObject = new GameObject("BSPface");
Mesh worldFace = new Mesh();
worldFace.name = "BSPfacemesh";
// Rip verts, uvs, and normals
List<Vector3> verts = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<Vector3> normals = new List<Vector3>();
int vstep = face.vertex;
for (int i = 0; i < face.n_vertexes; i++)
{
verts.Add(map.vertexLump.verts[vstep].position);
uvs.Add(map.vertexLump.verts[vstep].texcoord);
normals.Add(map.vertexLump.verts[vstep].normal);
vstep++;
}
// add the verts, uvs, and normals we ripped to the gameobjects mesh filter
worldFace.vertices = verts.ToArray();
worldFace.normals = normals.ToArray();
// I honestly don't know what these three uv arrays are for, so just put the same data in all of them
worldFace.uv = uvs.ToArray();
worldFace.uv1 = uvs.ToArray();
worldFace.uv2 = uvs.ToArray();
// Rip meshverts / triangles
List<int> mverts = new List<int>();
int mstep = face.meshvert;
for (int i = 0; i < face.n_meshverts; i++)
{
mverts.Add(map.meshvertLump.meshVerts[mstep]);
}
// add the meshverts to the object being built
worldFace.triangles = mverts.ToArray();
// bring it all together
faceObject.AddComponent<MeshFilter>();
faceObject.GetComponent<MeshFilter>().mesh = worldFace;
faceObject.GetComponent<MeshFilter>().mesh.RecalculateBounds();
faceObject.AddComponent<MeshRenderer>();
faceObject.renderer.material.shader = Shader.Find("Diffuse");
faceObject.renderer.material.color = Color.blue;
return faceObject;
}