Sign in to follow this  

Rendering Quake 3 Map

This topic is 4392 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need some help rendering Models in Lumps in Quake 3. I read some where that we only use the first model for rendering. Why is it so ? I myself loaded the models data from Quake 3 Lump. It gave my 15 models but I cud render only the faces of first one. Moreover, I have confusion. Whats the differences b/w the faces in Faces Lump and indexes of faces in Model Lump. I personally found no difference. If thats true then whats the use ?. One thing more, how can I load the characters ? Any help on it. Plus, can some1 give me links of good tutorial of Rendering Quake Maps. I shall be very grateful to him/her.

Share this post


Link to post
Share on other sites
okay when you say

I need some help rendering Models in Lumps in Quake 3. I read some where that we only use the first model for rendering. Why is it so ? I myself loaded the models data from Quake 3 Lump. It gave my 15 models but I cud render only the faces of first one.

im not to sure what you mean with lump, it was a long time ago i worked with the q3 format.

Do you mean the lump in the .bsp map file?

Md3 Model loading is rather simple , drop ur email and ill send you source code for basic loading & there are alot of articles going around anyways.

----------------------------
Perhaps when you say models from the quake 3 lump you refer to those moving platforms and that stuff? The stuff you need to apply transformations on?

Share this post


Link to post
Share on other sites
Yeah I mean the lump in .BSP File. OK If say the Model Lump in BSP how do I load them ?.

One thing more is there any relation b/w MD3 Model loading and Model Lump. I personally feel there is no relation b/w them. Any comments.

Share this post


Link to post
Share on other sites
By lump I am certain he is also meaning chunk or hunk.

Its been a long time, however, if i do remember correctly, the md3 chunk can be rendered the same way as a ibsp polygon soup chunk. The md3 embedded in the ibsp file are not animated so you can count on them only having a single frame with no tags.

Share this post


Link to post
Share on other sites
reference 2 http://graphics.stanford.edu/~kekoa/q3/#Models

it reads [quote]"The models lump describes rigid groups of world geometry. The first model correponds to the base portion of the map while the remaining models correspond to movable portions of the map, such as the map's doors, platforms, and buttons. Each model has a list of faces and list of brushes; these are especially important for the movable parts of the map, which (unlike the base portion of the map) do not have BSP trees associated with them. There are a total of length / sizeof(models) records in the lump, where length is the size of the lump itself, as specified in the lump directory."[\quote]

Now you are lucky i can help you since i made my own bsp loader and i did render these models Correctly with their animations/transformations, specifically the ones on the space maps with platforms that move.

NOW MOST IMPORTANTLY the model's animation is defined in the ENTITIES LUMP

[quote]
Entities

The entities lump stores game-related map information, including information about the map name, weapons, health, armor, triggers, spawn points, lights, and .md3 models to be placed in the map. The lump contains only one record, a string that describes all of the entities:

entities
string[length] ents Entity descriptions, stored as a string.
[\quote]
Here is a typical MODEL ENTITY


Now the model's faces are defined by
int face First face for model.
int n_faces Number of faces for model.

Where face is the index into your GLOBAL BSP face list and n_faces defines how many consecutive faces there are

So to render bobing the model go
glTranslatef(0,0,sin(Time * BobingFactor);
for (int i=0;i < n_faces;i++)
RenderFace(i+face);

----------------------------------------
OFFTOPIC : You will soon want to load the quake3 shaders, give me pm and ill email you a working standalone exe loader with source.. it simple demonstrates the basic functions

Share this post


Link to post
Share on other sites
Quote:
Here is a typical MODEL ENTITY


Now the model's faces are defined by
int face First face for model.
int n_faces Number of faces for model.

Where face is the index into your GLOBAL BSP face list and n_faces defines how many consecutive faces there are

So to render bobing the model go
glTranslatef(0,0,sin(Time * BobingFactor);
for (int i=0;i < n_faces;i++)
RenderFace(i+face);

----------------------------------------
OFFTOPIC : You will soon want to load the quake3 shaders, give me pm and ill email you a working standalone exe loader with source.. it simple demonstrates the basic functions


I did exactly what u mentioned. But I cud only render the first model, whereas 15 models were loaded. The rest were giving me simply black screen. I read somewhere that first model data is the static one while the rest one of data is related to characters, bla bla... One thing more how do I apply Frustum Culling for those models. .. How do I evaluate the normals and things like that ...
How do I read the Entities and use it for loading Model Lumps.

Plus I PM u and drop my address. I hope u help me in it.

Thanx alot

Share this post


Link to post
Share on other sites
Lets start with the easy one.

"How do I read the Entities and use it for loading Model Lumps"

Read the ENTITES lump using fread function and then simple dump it to a text file and you will see for yourself how to take it appart.

"I did exactly what u mentioned. But I cud only render the first model, whereas 15 models were loaded"---> The first model correponds to the base portion of the map while the remaining models correspond to movable portions of the map---> Thus true the first model will always be used, it indexes the entire world.

Firstly you dont traverse the model list loading it, (*some of these are not used*) you use the ENTITY LUMP which describes which models should be loaded and the effect applied to the model.

So in the entities we find 2 things of interest
We get entities who call them selves
{
"classname" "misc_model" and entities
"model" "models/mapobjects/gratelamp/gratetorchbig.md3"
"origin" "288 1538 118"
}

And as we can see that this is obviously an external md3 file to be loaded.
And then the second one is
{
"model" "*1"
"angle" "360"
"classname" "func_door"
"team" "stephanie"
}
As you see the CLASSNAME which is how we recognise the thing describes the function, the *1 indicates an index into the model lump and the angle obviously has to do with how the door opens/closes

My Basic Entity Class
[Source]
/*************************************************/
/* Robust CEntity Class */
/* Used to Capture all entities in */
/*************************************************/
class CEntity
{
public:
bool Active; // Do we process this entity
char classname[64]; // Name of this Entity
CVector3 origin; // Origin or Position of this Entity

int Type; // Check the Enum
int Class; // Check the Entity Class Enum --> EC_AMMO
int ClassType; // enum --> at_Slugs

float Angle; // Of Rotation
// Thats all we need for now

};
[\Source]

How to parse the entities is upto you but here is a basic one which extracts the Ammo/Weapons/Health and so on
[Source]
void BSPMap::ParseEntities()
{
// Dump Entity file
FILE *f = fopen("EntitiesParser.txt","w");
fputs(rawEntities,f); // Put the entities
fclose(f);

// Now we must count the Number of Entities
numEntities = 0;
for (unsigned int g=0;g < strlen(rawEntities);g++)
if (rawEntities[g] == '{') numEntities++;

// We can now free that memory
delete [] rawEntities;

// Create Real Entities
entity = new CEntity[numEntities];
entityDraw = new bool[numEntities];

// Open Entity Parser for REad
f = fopen("EntitiesParser.txt","rb");
char buffer[255],att[255],data[255];

// Not in an entity yet
int CurrentEntity = 0;
CEntity *c = NULL;

do
{
readln(f,buffer); // Read Very First Line
if (strchr(buffer,'{') != NULL)
{// Start with Entity
c = &entity[CurrentEntity]; // Grab Entity
c->Angle = 0.0f;
readln(f,buffer);
while (strchr(buffer,'}') == NULL) // While its not the end of the entity
{
// Parse Font
strSeperateTerms(buffer,att,data);
if (strstr(att,"classname")) strcpy(c->classname,data);
if (strstr(att,"origin"))
{
sscanf(data,"%f %f %f",&c->origin.x,&c->origin.y,&c->origin.z);
c->Active = true;
}
//...
readln(f,buffer);
}
c->Type = et_Other; // Set to unknown entity type
if (strstr(c->classname,"ammo") || strstr(c->classname,"weapon")|| strstr(c->classname,"item"))
{
c->Type = et_Item; // Of Item Tyoe
if (strstr(c->classname,"ammo"))
{
c->Class = ec_Ammo; // Ammo Class
c->ClassType = 10;
if (strstr(c->classname,"bullets")) c->ClassType = at_Bullets;
if (strstr(c->classname,"shells")) c->ClassType = at_Shells;
if (strstr(c->classname,"cells")) c->ClassType = at_Rifle_Rounds;
if (strstr(c->classname,"rockets")) c->ClassType = at_Rockets;
}
if (strstr(c->classname,"weapon"))
{
c->Class = ec_Weapon; // Ammo Class
c->ClassType = 10;
if (strstr(c->classname,"machinegun")) c->ClassType = wt_Chaingun;
if (strstr(c->classname,"shotgun")) c->ClassType = wt_Shotgun;
if (strstr(c->classname,"railgun")) c->ClassType = wt_Rifle;
if (strstr(c->classname,"rocketlauncher")) c->ClassType = wt_Rocket_Launcher;
}
if (strstr(c->classname,"item"))
{
c->Class = ec_Item; // Ammo Class
c->ClassType = 10;
if (strstr(c->classname,"health_mega")) c->ClassType = it_Boost;
else if (strstr(c->classname,"health")) c->ClassType = it_Health;
if (strstr(c->classname,"armor_body")) c->ClassType = it_Armour50;
if (strstr(c->classname,"armor_combat")) c->ClassType= it_Armour100;
if (strstr(c->classname,"quad")) c->ClassType = it_Quad;
}
}

}// Finished with Entity
CurrentEntity++; // Move On To Next Entity
} while ((CurrentEntity < numEntities) && (feof(f) == false));

// Close the File Again
fclose(f);

};
[\Source]

And here is how to load the ENTITES from the lump:
[Source]
rawEntities = new char[lumps[kEntities].length / sizeof(char)];
fseek(fp, lumps[kEntities].offset, SEEK_SET); // Seek the Entities Pos
fread(rawEntities, lumps[kEntities].length / sizeof(char),sizeof(char), fp); // Read entities data
ParseEntities();
[\Source]

MY PROJECT total stands at 4mb so i can send it 2 you if you want, it is quite complete actually but its by no means user friendly and you will need to download GLEE which handles openGL extensions, multitexturing in this case.


Share this post


Link to post
Share on other sites
If I am not mistaken ebikhan is after a way to render from the models lump inside the binary ibsp file. Not to render the external md3's referenced inside the entities list.

There is an ENTITIES lump which has all the information dawidjoubert wrote about referencing external resources, and there are embedded models within the MODELS lump.

Share this post


Link to post
Share on other sites
Well my long-term goal is both one. But I guess the information of MD3 loading is store in Entities Lump.

Anyways, any sort of help on loading entites lump and rendering them effectively using the Frustum Culling on it and Collision detection on them. and again then how wud I load the MD3 Model and render it using Frustum Culling and wat abt its Collision Detection. Any generic method or any method watsoever regarding it.

Share this post


Link to post
Share on other sites
Quote:
Original post by ebikhan
Well my long-term goal is both one. But I guess the information of MD3 loading is store in Entities Lump.

Anyways, any sort of help on loading entites lump and rendering them effectively using the Frustum Culling on it and Collision detection on them. and again then how wud I load the MD3 Model and render it using Frustum Culling and wat abt its Collision Detection. Any generic method or any method watsoever regarding it.


dawidjoubert was all over this with some helpfull advice. Give his post another read.

Share this post


Link to post
Share on other sites
I would say you are best of starting at the most important things first.
-----------------------------------------------------------------------
Can you render all 4 types of Faces EXCEPT the beizer (NURBS)?
Did you implement the Visiblity Set & Binary tree in rendering?
Do you have a collision algorith allowing for Sphere->World & Ray->World & AABB->World Collision?

If you dont have those three it doesnt matter how good your graphics is.

Second tip! Load q3dm1&2&3..6 and so on which have 0 world interactive objects (doors/platforms)

Once you have done all the top then move on to loading and parsing the entity lump.

You could use spheres for entity items, Cubes to show the presence of an external md3 model (which you dont load yet), Pyramids for spawn locations and so you get the idea.

THEN AT THIS PHASE only consider world models (ie interactive models), now the problem with these are they dont exist on the Binary Tree and you have to create there binary tree self and ANIMATE (as a door moves) it self aswell which is why i never did get to far.


NOW I WOULD love to give you my source but i cant find an ftp to put it!!

Share this post


Link to post
Share on other sites

This topic is 4392 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this