Problem rendering Quake 3 BSP files

Started by
14 comments, last by industrialgrok 11 years ago

Ok, so for the past week ive been working on a Quake 3 bsp veiwer this is what I have finished already


//standard librarys 
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <sstream>

#include "sys_mem.h"
using namespace std;

#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP    32

#define MAX_FACES  10000
#define MAX_VERTS  100000

struct bspface
{
 int textureID;           // The index into the texture array 
 int effect;              // The index for the effects (or -1 = n/a) 
 int type;                // 1=polygon, 2=patch, 3=mesh, 4=billboard 
 int vertexIndex;         // The index into this face's first vertex 
 int numOfVerts;          // The number of vertices for this face 
 int meshVertIndex;       // The index into the first meshvertex 
 int numMeshVerts;        // The number of mesh vertices 
 int lightmapID;          // The texture index for the lightmap 
 int lMapCorner[1];       // The face's lightmap corner in the image 
 int lMapSize[1];         // The size of the lightmap section 
 float lMapPos[2];        // The 3D origin of lightmap. 
 float lMapBitsets[1][2]; // The 3D space for s and t unit vectors. 
 float vNormal[2];        // The face normal. 
 int size[1];             // The bezier patch dimensions. 
};

//

struct bspvertex
{
 float position[2];      //x y z 
 float texturecoord[1];  //u, v texture coordinate
 float lightmapcoord[1]; //u, v lightmap coordinate
 float normal[2];        //x, y, z normalized vector
 char  color[3];         //RGBA color for the vertex //char = byte?
};

struct bsplump
{
 int offset;
 int length;
};

struct bsp
{
 bsplump   lumps[16];
 bspvertex vertices[MAX_VERTS];
 bspface   faces[MAX_FACES];
};

bsp bspbuffer;

bool running = true;  //if renderer is running 
bool lightmaps;

void loadbsp(string);    //prototype

void init()
{
 glClearColor(0.0,0.0,0.0,1.0);            //Background color
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();                         //Reset 
 gluPerspective(45,640.0/480.0,1.0,500.0); //Perspective 
 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_CULL_FACE);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 glEnable( GL_BLEND );
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHT1); 
 glEnable(GL_COLOR_MATERIAL);

float light_0_amb[] = {0.2f, 0.2, 0.2};
glLightfv(GL_LIGHT0,GL_AMBIENT, light_0_amb);

float light_0_pos[] = {1.0,3.0,1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_0_pos);

float light_0_dif[] = {1.0,1.0,1.0,0.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_dif);

float light_0_spec[] = {1.0, 1.0, 1.0, 0.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_spec);
} 

void display()
{
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 glFlush();
 glLoadIdentity();   

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //OpenGL's texture parameters 
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

 //RENDERLOOP

 SDL_GL_SwapBuffers();
}

int main(int argc, char *argv[])
{
 if(argv[1] == NULL)
   cout << "ERROR: No bsp file used as an argument example \"./bsploader.x86 -map.bsp\"" << endl;
 else
     {
      /*tolkenize argument*/
      istringstream namebuffer(argv[1]);  //zero is ./bsploader
      while (!namebuffer.eof())
           {
            string tolken;                      //tolken buffer
            getline(namebuffer, tolken, '-' );  //split and store in tolken buffer
            if(tolken != "")
              {
               loadbsp(tolken);
              }
           }
     do
       {
        SDL_Surface* screen=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE|SDL_OPENGL);
                           //Window           //Tab
        SDL_WM_SetCaption( "BSPloader","BSPloader");
        Uint32 start;
        init();
        display(); 
        SDL_Delay(1000/30);
       }while(running);
      
     }

 return 0;
}

void loadbsp(string name)
{
 cout << "Loading BSP \"" << name << "\"" << endl; 
 ifstream bspfile;
 bspfile.open (name.c_str(),ios::in|ios::binary);//Load BSP file into memory
 if(bspfile == NULL)
   cout << "ERROR: No file named \""<< name <<"\" found" << endl;
 else
     {
      char magic[64];           //Number used in BSP header	
      bspfile.read(magic, 4);   //Read the magic number in the header of the BSP file it should be "IBSP"
      if((magic[0] != 'I')||(magic[1] != 'B')||(magic[2] != 'S')||(magic[3] != 'P'))
        {
         cout << "ERROR: Not a valid Quake 3 BSP file" << endl;
        }
      else
          {
           int version;
           version = readInt(bspfile);
           if(version != 46)//46 = 0x2e in hexidecimal
             cout << "ERROR: Unknown version of Quake 3 BSP" << endl;
           else
               {
                for (int i = 0; i <= 16; i++)
                   {                 
                    bspbuffer.lumps[i].offset = readInt(bspfile);
                    bspbuffer.lumps[i].length = readInt(bspfile);
                    cout << "Lump " << i << " offset is " << bspbuffer.lumps[i].offset << endl
                         << "Lump " << i << " length is " << bspbuffer.lumps[i].length << endl << endl;                   
                   }
                //Load vertices
                bspfile.seekg (bspbuffer.lumps[10].offset, ios::beg); //Load vertex data from vertex lump (10)
                long readmemory = 0;
                cout << "Loading";

                for (int j = 0; readmemory <= bspbuffer.lumps[10].length; j++)//Read until end of lump
                   { 
                    //Actual vertexes
                    bspbuffer.vertices[j].position[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[1] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[2] = readFloat(bspfile);

                    //U,V coordinates
                    bspbuffer.vertices[j].texturecoord[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].texturecoord[1] = readFloat(bspfile);

                    //Lightmap U,V coordinates
                    bspbuffer.vertices[j].lightmapcoord[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].lightmapcoord[1] = readFloat(bspfile);

                    //Normalized vertex coordinates
                    bspbuffer.vertices[j].position[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[1] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[2] = readFloat(bspfile);

                    char buffer[64];           	
                    bspfile.read(buffer, 4); //Read RGBA color index
                    bspbuffer.vertices[j].color[0] = buffer[0];
                    bspbuffer.vertices[j].color[1] = buffer[1];
                    bspbuffer.vertices[j].color[2] = buffer[2];
                    bspbuffer.vertices[j].color[3] = buffer[3];
                    //10 floats 4 char so 10(4) + 4(1)
                    readmemory = readmemory + 44;  
                    cout << ".";       
                   }

                bspfile.seekg (bspbuffer.lumps[13].offset, ios::beg); //Load face data from vertex lump (13)
                long readmemory2 = 0;
                cout << "Loading";
                for (int b = 0; readmemory2 <= bspbuffer.lumps[13].length; b++)//Read until end of lump
                   { 
                    bspbuffer.faces[b].textureID     = readInt(bspfile); // The index into the texture array 
                    bspbuffer.faces[b].effect        = readInt(bspfile); // The index for the effects (or -1 = n/a) 
                    bspbuffer.faces[b].type          = readInt(bspfile); // 1=polygon, 2=patch, 3=mesh, 4=billboard 
                    bspbuffer.faces[b].vertexIndex   = readInt(bspfile); // The index into this face's first vertex
                    cout << bspbuffer.faces[b].vertexIndex << endl;
                    bspbuffer.faces[b].numOfVerts    = readInt(bspfile); // The number of vertices for this face 
                    bspbuffer.faces[b].meshVertIndex = readInt(bspfile); // The index into the first meshvertex 
                    bspbuffer.faces[b].numMeshVerts  = readInt(bspfile); // The number of mesh vertices 
                    bspbuffer.faces[b].lightmapID    = readInt(bspfile); // The texture index for the lightmap 

                    bspbuffer.faces[b].lMapCorner[0] = readInt(bspfile); // The face's lightmap corner in the image 
                    bspbuffer.faces[b].lMapCorner[1] = readInt(bspfile); // The face's lightmap corner in the image 

                    bspbuffer.faces[b].lMapSize[0]   = readInt(bspfile); // The size of the lightmap section 
                    bspbuffer.faces[b].lMapSize[1]   = readInt(bspfile); // The size of the lightmap section 

                    bspbuffer.faces[b].lMapPos[0]    = readFloat(bspfile); // The 3D origin of lightmap. 
                    bspbuffer.faces[b].lMapPos[1]    = readFloat(bspfile); // The 3D origin of lightmap. 
                    bspbuffer.faces[b].lMapPos[2]    = readFloat(bspfile); // The 3D origin of lightmap. 

                    bspbuffer.faces[b].lMapBitsets[0][0]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[0][1]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[0][2]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 

                    bspbuffer.faces[b].lMapBitsets[1][0]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[1][1]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[1][2]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
             
                    bspbuffer.faces[b].vNormal[0]    = readFloat(bspfile); // The face normal. 
                    bspbuffer.faces[b].vNormal[1]    = readFloat(bspfile); // The face normal. 
                    bspbuffer.faces[b].vNormal[2]    = readFloat(bspfile); // The face normal. 

                    bspbuffer.faces[b].size[0] = readInt(bspfile);            // The bezier patch dimensions. 
                    bspbuffer.faces[b].size[1] = readInt(bspfile);             // The bezier patch dimensions. 
                    //26(4)
                    readmemory2 = readmemory2 + 104;       
                   }
                
                cout << "Loaded" << endl;
               }
          }

     }
}

the vertex information is mostly gibberish (as that two of the values are zero) Im aware that you have to use vertexIndex for the first vertex and put them into a triangle fan, but how?

Advertisement
me:
looks at struct definitions... "WTF?".

check array sizes.

Instead of using triangle fans, you're better off using indexed triangles. Not every Quake3 map will render properly if you use triangle fans. I made the same mistake for ages and that's how I fixed my bogus vertex data problem. My renderer is Direct3D based so it might not help much. If you want it anyway, I can upload it and hopefully it will help.

Shogun.

You have buffer overflow in your structure.

blueshogun96 that would be aprecciated. BornToCode how would I fix that? here is my updated code

//standard librarys 
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <sstream>

#include "sys_mem.h"
using namespace std;

#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP    32

#define MAX_FACES  10000
#define MAX_VERTS  100000

struct bspface
{
 int textureID;           // The index into the texture array 
 int effect;              // The index for the effects (or -1 = n/a) 
 int type;                // 1=polygon, 2=patch, 3=mesh, 4=billboard 
 int vertexIndex;         // The index into this face's first vertex 
 int numOfVerts;          // The number of vertices for this face 
 int meshVertIndex;       // The index into the first meshvertex 
 int numMeshVerts;        // The number of mesh vertices 
 int lightmapID;          // The texture index for the lightmap 
 int lMapCorner[1];       // The face's lightmap corner in the image 
 int lMapSize[1];         // The size of the lightmap section 
 float lMapPos[2];        // The 3D origin of lightmap. 
 float lMapBitsets[1][2]; // The 3D space for s and t unit vectors. 
 float vNormal[2];        // The face normal. 
 int size[1];             // The bezier patch dimensions. 
};

//

struct bspvertex
{
 float position[3];      //x y z 
 float texturecoord[2];  //u, v texture coordinate
 float lightmapcoord[2]; //u, v lightmap coordinate
 float normal[3];        //x, y, z normalized vector
 char  color[4];         //RGBA color for the vertex //char = byte?
};

struct bsplump
{
 int offset;
 int length;
};

struct bsp
{
 bsplump   lumps[16];
 bspvertex vertices[MAX_VERTS];
 bspface   faces[MAX_FACES];
};

bsp bspbuffer;

bool running = true;  //if renderer is running 
bool lightmaps;

void loadbsp(string);    //prototype

void init()
{
 glClearColor(0.0,0.0,0.0,1.0);            //Background color
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();                         //Reset 
 gluPerspective(45,640.0/480.0,1.0,500.0); //Perspective 
 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_CULL_FACE);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 glEnable( GL_BLEND );
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHT1); 
 glEnable(GL_COLOR_MATERIAL);

float light_0_amb[] = {0.2f, 0.2, 0.2};
glLightfv(GL_LIGHT0,GL_AMBIENT, light_0_amb);

float light_0_pos[] = {1.0,3.0,1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_0_pos);

float light_0_dif[] = {1.0,1.0,1.0,0.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_dif);

float light_0_spec[] = {1.0, 1.0, 1.0, 0.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_spec);
} 

void display()
{
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 glFlush();
 glLoadIdentity();   

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //OpenGL's texture parameters 
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

 //RENDERLOOP

 SDL_GL_SwapBuffers();
}

int main(int argc, char *argv[])
{
 if(argv[1] == NULL)
   cout << "ERROR: No bsp file used as an argument example \"./bsploader.x86 -map.bsp\"" << endl;
 else
     {
      /*tolkenize argument*/
      istringstream namebuffer(argv[1]);  //zero is ./bsploader
      while (!namebuffer.eof())
           {
            string tolken;                      //tolken buffer
            getline(namebuffer, tolken, '-' );  //split and store in tolken buffer
            if(tolken != "")
              {
               loadbsp(tolken);
              }
           }
     do
       {
        SDL_Surface* screen=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE|SDL_OPENGL);
                           //Window           //Tab
        SDL_WM_SetCaption( "BSPloader","BSPloader");
        Uint32 start;
        init();
        display(); 
        SDL_Delay(1000/30);
       }while(running);
      
     }

 return 0;
}

void loadbsp(string name)
{
 cout << "Loading BSP \"" << name << "\"" << endl; 
 ifstream bspfile;
 bspfile.open (name.c_str(),ios::in|ios::binary);//Load BSP file into memory
 if(bspfile == NULL)
   cout << "ERROR: No file named \""<< name <<"\" found" << endl;
 else
     {
      char magic[64];           //Number used in BSP header	
      bspfile.read(magic, 4);   //Read the magic number in the header of the BSP file it should be "IBSP"
      if((magic[0] != 'I')||(magic[1] != 'B')||(magic[2] != 'S')||(magic[3] != 'P'))
        {
         cout << "ERROR: Not a valid Quake 3 BSP file" << endl;
        }
      else
          {
           int version;
           version = readInt(bspfile);
           if(version != 46)//46 = 0x2e in hexidecimal
             cout << "ERROR: Unknown version of Quake 3 BSP" << endl;
           else
               {
                for (int i = 0; i <= 16; i++)
                   {                 
                    bspbuffer.lumps[i].offset = readInt(bspfile);
                    bspbuffer.lumps[i].length = readInt(bspfile);
                    cout << "Lump " << i << " offset is " << bspbuffer.lumps[i].offset << endl
                         << "Lump " << i << " length is " << bspbuffer.lumps[i].length << endl << endl;                   
                   }
                //Load vertices
                bspfile.seekg (bspbuffer.lumps[10].offset, ios::beg); //Load vertex data from vertex lump (10)
                long readmemory = 0;
                cout << "Loading";

                for (int j = 0; j <= bspbuffer.lumps[10].length/sizeof(bspvertex); j++)//Read until end of lump
                   { 
                    //Actual vertexes
                    bspbuffer.vertices[j].position[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[1] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[2] = readFloat(bspfile);

                    //U,V coordinates
                    bspbuffer.vertices[j].texturecoord[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].texturecoord[1] = readFloat(bspfile);

                    //Lightmap U,V coordinates
                    bspbuffer.vertices[j].lightmapcoord[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].lightmapcoord[1] = readFloat(bspfile);

                    //Normalized vertex coordinates
                    bspbuffer.vertices[j].position[0] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[1] = readFloat(bspfile);
                    bspbuffer.vertices[j].position[2] = readFloat(bspfile);

                    char buffer[64];           	
                    bspfile.read(buffer, 4); //Read RGBA color index
                    bspbuffer.vertices[j].color[0] = buffer[0];
                    bspbuffer.vertices[j].color[1] = buffer[1];
                    bspbuffer.vertices[j].color[2] = buffer[2];
                    bspbuffer.vertices[j].color[3] = buffer[3];
                    //10 floats 4 char so 10(4) + 4(1) 
                    cout << bspbuffer.vertices[j].position[0] << bspbuffer.vertices[j].position[1] << bspbuffer.vertices[j].position[2] << endl;
                   }
                cout << "Lump 10 loaded" << endl;
                bspfile.seekg (bspbuffer.lumps[13].offset, ios::beg); //Load face data from vertex lump (13)
                long readmemory2 = 0;
                cout << "Loading";
                for (int b = 0; readmemory2 <= bspbuffer.lumps[13].length; b++)//Read until end of lump
                   { 
                    bspbuffer.faces[b].textureID     = readInt(bspfile); // The index into the texture array 
                    bspbuffer.faces[b].effect        = readInt(bspfile); // The index for the effects (or -1 = n/a) 
                    bspbuffer.faces[b].type          = readInt(bspfile); // 1=polygon, 2=patch, 3=mesh, 4=billboard 
                    bspbuffer.faces[b].vertexIndex   = readInt(bspfile); // The index into this face's first vertex
                    bspbuffer.faces[b].numOfVerts    = readInt(bspfile); // The number of vertices for this face 
                    bspbuffer.faces[b].meshVertIndex = readInt(bspfile); // The index into the first meshvertex 
                    bspbuffer.faces[b].numMeshVerts  = readInt(bspfile); // The number of mesh vertices 
                    bspbuffer.faces[b].lightmapID    = readInt(bspfile); // The texture index for the lightmap 

                    bspbuffer.faces[b].lMapCorner[0] = readInt(bspfile); // The face's lightmap corner in the image 
                    bspbuffer.faces[b].lMapCorner[1] = readInt(bspfile); // The face's lightmap corner in the image 

                    bspbuffer.faces[b].lMapSize[0]   = readInt(bspfile); // The size of the lightmap section 
                    bspbuffer.faces[b].lMapSize[1]   = readInt(bspfile); // The size of the lightmap section 

                    bspbuffer.faces[b].lMapPos[0]    = readFloat(bspfile); // The 3D origin of lightmap. 
                    bspbuffer.faces[b].lMapPos[1]    = readFloat(bspfile); // The 3D origin of lightmap. 
                    bspbuffer.faces[b].lMapPos[2]    = readFloat(bspfile); // The 3D origin of lightmap. 

                    bspbuffer.faces[b].lMapBitsets[0][0]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[0][1]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[0][2]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 

                    bspbuffer.faces[b].lMapBitsets[1][0]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[1][1]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
                    bspbuffer.faces[b].lMapBitsets[1][2]  = readFloat(bspfile); // The 3D space for s and t unit vectors. 
             
                    bspbuffer.faces[b].vNormal[0]    = readFloat(bspfile); // The face normal. 
                    bspbuffer.faces[b].vNormal[1]    = readFloat(bspfile); // The face normal. 
                    bspbuffer.faces[b].vNormal[2]    = readFloat(bspfile); // The face normal. 

                    bspbuffer.faces[b].size[0] = readInt(bspfile);            // The bezier patch dimensions. 
                    bspbuffer.faces[b].size[1] = readInt(bspfile);             // The bezier patch dimensions. 
                    //26(4)
                    readmemory2 = readmemory2 + 104; 
                    cout << ".";        
                   }
                cout << "Lump 13 loaded" << endl;
               }
          }

     }
}


Maybe have a look at the Quake 3 code itself? https://github.com/id-Software/Quake-III-Arena

Going through the BSP loading and drawing code may give you a few hints and save you a whole heap of pain and frustration.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

blueshogun96 that would be aprecciated.


Sorry for the slow response, my regular job has me working nights so I find myself sleeping all day... (I'm at work now) \/_\/

I'll upload it when I get home, but it wasn't until I found this link it made sense (Direct3D wise): http://www.xbdev.net/3dformats/quake3bsp/index.php

IIRC, this one also renders BSPs the proper way and uses OpenGL, but it's a bit more complex: http://www.paulsprojects.net/opengl/q3bsp/q3bsp.html

Hope this helps,

Shogun.

What i mean is that in your structure for normal for example. Normal cosist of xyz which is 3 elements but your array is using 2 elements for bspface.

blueshogun96 thanks, BornToCode an array starts at zero so 0,1,2. mhagain ok, I will start reading Idtech 3's source code, I have read quake, and quake2's have a fairly good understanding of them

blueshogun96 thanks, BornToCode an array starts at zero so 0,1,2. mhagain ok, I will start reading Idtech 3's source code, I have read quake, and quake2's have a fairly good understanding of them

That is what your index needs to say 3 index 0 1 and 2 are used. When you create an array with one element you do not say int Array[0] you say int Array[1] and you use only used index 0. So if you have x y and z then your Array needs to be defined as int Array[3] not int Array[2]. Look at your code in your bspface you have float vNormal[2];

vNormal supposed to have xyz which means vNormal needs to be [3] not [2]

This topic is closed to new replies.

Advertisement