예제 #1
0
        /// <summary>
        /// Compile the map into a stream of OpenGL-compatible data
        /// </summary>
        public static void CompileMap(List <Vertex> verts,
                                      List <Face> faces,
                                      List <int> meshVerts,
                                      List <lightmap_rect_t> lightmaps,
                                      List <shader_p> shaders,
                                      int tesselationLevel)
        {
            Vertex vert;

            BspCompiler.faces = faces;

            q3bsp.onMessage(new MessageParams()
            {
                type    = "status",
                message = "Map geometry parsed, compiling shaders..."
            });

            // Find associated shaders for all clusters

            // Per-face operations
            for (int i = 0; i < faces.Count; ++i)
            {
                Face face = faces[i];

                if (face.type == 1 || face.type == 2 || face.type == 3)
                {
                    // Add face to the appropriate texture face list
                    shader_p shader = shaders[(int)face.shader];
                    shader.faces.Add(face);
                    lightmap_rect_t lightmap = face.lightmap > 0 ? lightmaps[(int)face.lightmap] : null;

                    if (lightmap == null)
                    {
                        lightmap = lightmaps[0];
                    }

                    if (face.type == 1 || face.type == 3)
                    {
                        shader.geomType = face.type;
                        // Transform lightmap coords to match position in combined texture
                        for (int j = 0; j < face.meshVertCount; ++j)
                        {
                            vert = verts[(int)face.vertex + (int)meshVerts[(int)face.meshVert + j]];

                            vert.lmNewCoord.X = (vert.lmCoord.X * lightmap.xScale) + lightmap.x;
                            vert.lmNewCoord.Y = (vert.lmCoord.Y * lightmap.yScale) + lightmap.y;
                        }
                    }
                    else
                    {
                        q3bsp.onMessage(new MessageParams()
                        {
                            type    = "status",
                            message = "Tesselating face " + i.ToString() + " of " + faces.Count.ToString()
                        });

                        // Build Bezier curve
                        BspTess.Tesselate(face, verts, meshVerts, tesselationLevel);

                        for (int j = 0; j < face.vertCount; ++j)
                        {
                            vert = verts[(int)face.vertex + j];

                            vert.lmNewCoord.X = (vert.lmCoord.X * lightmap.xScale) + lightmap.x;
                            vert.lmNewCoord.Y = (vert.lmCoord.Y * lightmap.yScale) + lightmap.y;
                        }
                    }
                }
            }

            // Compile vert list INTERLEAVE
            float[] vertices;

            vertices = Interleave(verts);


            // Compile index list
            List <ushort> lst_indices = new List <ushort>();

            for (int i = 0; i < shaders.Count; ++i)
            {
                shader_p shader = shaders[i];

                if (shader.faces.Count > 0)
                {
                    shader.indexOffset = lst_indices.Count * 2;                     // Offset is in bytes

                    for (int j = 0; j < shader.faces.Count; ++j)
                    {
                        Face face = shader.faces[j];
                        face.indexOffset = lst_indices.Count * 2;

                        for (int k = 0; k < face.meshVertCount; ++k)
                        {
                            lst_indices.Add((ushort)(face.vertex + meshVerts[face.meshVert + k]));
                        }
                        shader.elementCount += (int)face.meshVertCount;
                    }
                }
                shader.faces = null;                 // Don't need to send this to the render thread.
            }

            ushort[] indices = lst_indices.ToArray();


            // Send the compiled vertex/index data back to the render thread
            q3bsp.onMessage(new MessageParams()
            {
                type     = "geometry",
                vertices = vertices,
                indices  = indices,
                surfaces = shaders
            });
        }
예제 #2
0
        /// <summary>
        /// Read all lightmaps
        /// </summary>
        private static List <lightmap_rect_t> ReadLightmaps(bsp_header_lump_t lump, BinaryStreamReader src)
        {
            int lightmapSize = 128 * 128;
            int count        = (int)lump.length / (lightmapSize * 3);

            var gridSize = 2;

            while (gridSize * gridSize < count)
            {
                gridSize *= 2;
            }

            var textureSize = gridSize * 128;

            int xOffset = 0;
            int yOffset = 0;

            List <lightmap_t>      lightmaps     = new List <lightmap_t>();
            List <lightmap_rect_t> lightmapRects = new List <lightmap_rect_t>();
            Vector3 rgb = Vector3.Zero;

            src.Seek(lump.offset);
            for (int i = 0; i < count; ++i)
            {
                byte[] elements = new byte[lightmapSize * 4];

                for (int j = 0; j < lightmapSize * 4; j += 4)
                {
                    rgb.X = src.ReadUByte();
                    rgb.Y = src.ReadUByte();
                    rgb.Z = src.ReadUByte();

                    rgb = BspHelpers.brightnessAdjust(rgb, 4.0f);

                    elements[j]     = (byte)rgb.X;
                    elements[j + 1] = (byte)rgb.Y;
                    elements[j + 2] = (byte)rgb.Z;
                    elements[j + 3] = 255;
                }

                lightmap_t l = new lightmap_t();
                l.x      = xOffset;
                l.y      = yOffset;
                l.width  = 128;
                l.height = 128;
                l.bytes  = elements;
                lightmaps.Add(l);

                lightmap_rect_t r = new lightmap_rect_t();
                r.x      = (float)xOffset / (float)textureSize;
                r.y      = (float)yOffset / (float)textureSize;
                r.xScale = 128f / (float)textureSize;
                r.yScale = 128f / (float)textureSize;
                lightmapRects.Add(r);

                xOffset += 128;

                if (xOffset >= textureSize)
                {
                    yOffset += 128;
                    xOffset  = 0;
                }
            }

            // Send the lightmap data back to the render thread
            q3bsp.onMessage(new MessageParams()
            {
                type      = "lightmap",
                size      = textureSize,
                lightmaps = lightmaps
            });

            return(lightmapRects);
        }