News | Forum | People | FAQ | Links | Search | Register | Log in
Coding Help
This is a counterpart to the "Mapping Help" thread. If you need help with QuakeC coding, or questions about how to do some engine modification, this is the place for you! We've got a few coders here on the forum and hopefully someone knows the answer.
First | Previous | Next | Last
Necros 
Can that physics issue happen in DirectQ or the RMQ Engine? Both those engines have very intricate physics fixes that essentially make sure that the physics always run at Quake normal speed.

I ask because it is an engine physics issue, that isn't something you should worry about too much because MH has the cure that needs to get into other engines. 
Sheesh Missing Word ... 
"I ask because IF it is an engine physics issue" ... [basically can you reproduce the problem in the RMQ engine or DirectQ with that lift? If not, maybe mentally mark that problem off the proverbial list ...] 
 
you can test to see if it's happening by going loading ne_ruins, turning on dev mode to 1 and riding the lift up.
It's very random and may or may not happen, but you will see "corrected bmodel collision bug." if the qc detects a block that shouldn't happen.

it doesn't happen in DP, so if the collision fixes are as extensive as it is in DP, then it probably doesn't. The collision in DP is really sweet. 
 
That's enough info then. Yeah, DarkPlaces is fixed up in that way as well (and has been for ages and ages).

I wouldn't spend any time worrying about this one.

I intend to extract the fixes from RMQ/DirectQ and more or less document how to implement them.

[I just haven't done it yet because of the things on my list, well, it's kinda boring and tedious ... ] 
Bsp Format Question 
I'd like to check something with people who are familiar with the BSP file format. Suppose we have a very simple map with one room containing a func_wall. The room has 20 faces and the func_wall has 6. Is it correct that there is just one list of 26 faces in the bsp:

0
...
19
20
...
25

then the model headers go
"world: I own 20 faces starting at face 0"
"wall: I own 6 faces starting at face 20"

The same then goes for vertices, nodes etc, that the bsp file collects all alike data types into a single list and each model in the file operates on a subset of that same list? (with exceptions like textures which are instead shared).

Why? I was thinking about the external bsp models trick - initially I was just trying to write a tool to pack them back into a single bsp for release. However, if the above is correct, it might also mean that the external file gets a new lease of life - as a limited way to help maps which exceed bsp limits  
 
interesting...

rezTarget.think =
rezTarget.nextthink = time + 0.1;


compiles fine with fteqcc, but flat out crashes quake. :P 
Is It Correct That There Is Just One List Of 26 Faces 
Yes, that's the way everything is stored, but there are subtleties.

"Faces" as you understand them in a map have little relationship to surfaces in the generated BSP file. QBSP will remove faces (facing out, never visible, overlapped, etc) and generate more from splits, so you can't really use the map file as any kind of guideline to what the BSP will contain.

Regarding use of external BSP models, you can use them to go through BSP limits, but lighting will be wrong for them. Lighting for an external BSP model doesn't take account of any geometry in the world that might occlude those lights, and they fail to get dynamic lights. That might be OK with you, but it might not be OK with someone playing your map. 
It's My Lighting Aand I'll Cry If I Want 
That's good to know.

On lighting: Although losing dynamic lights is a shame, I don't think that the static lighting is much of a obstacle.

Although I've been talking external bsps in general, the best use-case for external models is for objects that rotate or move. Static lighting of course can't get these right, so there's less worry they might be lit "wrong". Along the axis of rotation it makes more sense for the lighting to be uniform, instead of baking in a shadow which will be wrong as soon as the object moves.

For statics moved outside the BSP for limit reasons only, I suppose it's not impossible to write a version of light that applies occlusion from a base map onto an external bsp (using the code-path from the light executable which occludes lights on models 1-n based on the geometry from model 0, except loading model 0 from a different file to model 1). Think I'll stick to the bsp packer for now though... 
 
Dynamic lights can be fixed in-engine; there's a (slight) performance cost but the visual consistency is more than worth it. I have it in my current (unreleased) codebase, but I don't believe any other engine has implemented it yet (aside from those with fully real-time solutions).

Along the axis of rotation it makes more sense for the lighting to be uniform, instead of baking in a shadow which will be wrong as soon as the object moves

Definitely agree with that.

I suppose it's not impossible to write a version of light that applies occlusion from a base map onto an external bsp

It's an interesting idea. It would break if more than one entity used the same BSP model (an example would be a generic door modelled as a BSP) but for limited special cases it should work. 
 
would it be possible to make an 'fake ambient occlusion' mode in light.exe such that, when enabling it, it creates an array of suns like it does with sunlight2, except that these suns do not require sky textured brushes?

that way we could make some external brushwork and get some nice shadows that look good from all rotation angles.

heh, maybe I should do that... I'll see if I can puzzle it out. 
 
http://necros.slipgateconstruct.com/temp/sillygi.jpg

hmm, seems like it was easier than I thought it would be. o.0 
If Anyone's Interested: 
http://necros.slipgateconstruct.com/downloads/ne_ag_LightMHColourR2.zip

This is based off of mh's coloured light/multicore tweak of aguirre's light utility, so it has all the good stuff.

Two new command switches are added:

-fakeGISun2
Makes sunlight2 cast additive light in a full sphere (as opposed to a dome).

-fakeGIMode
Makes sunlight2 not require skybrushes (ie: the light comes from the void)
NOTE: REQUIRES -fakeGISun2

Also note you need to set the worldspawn keys 'sunlight' to '1' otherwise it's not activated at all and the 'sunlight2' settings should be low, 2 or 3. 4 is pretty bright.

I basically just turn off the check that requires sunlight to pass through a skybrush first, so with -fakeGIMode, the sunlight comes from the void.

Source included. Some small changes to LoadEntities() and TestSky() and maybe one or two other tiny things I've forgotten. 
Good Stuff 
The spherical illumination might also be handy for coagula style maps. 
 
not bad results on space maps with only the fake gi light enabled: http://necros.slipgateconstruct.com/temp/nesp10GI.jpg

Might be cool to do another space map one day with this lighting. The only thing is that exposed faces tend to look flat. The above screenshot is only interesting because of those high walls. 
 
That actually looks pretty cool; kinda radiosity-like. 
 
Dunno if anyone has mentioned this before (Preach maybe?) but I've been using a lot of multi-entity setups these days and cleaning up after them has become rather annoying so I used this trick to simplify things:

void(entity e) remove_builtin = #15;
.void() removeFunction;
void(entity e) remove =
{
local void() _removeFunction;
entity tempSelf;

if (e.removeFunction)
{
_removeFunction = e.removeFunction;
e.removeFunction = SUB_Null;
tempSelf = self;
self = e;
_removeFunction();
self = tempSelf;
}

remove_builtin(e);
};

Create a wrapper for the remove builtin that first checks if a .removeFunction is set, and if so, run it.
Then, I just create a unique function for each multi-entity that takes care of any child entities.

Note how we first save a reference to the .removeFunction() before clearing it. This is to prevent some recursive removeFunction running where (if you are not careful) you remove a child entity that then removes the parent, that then removes the child... etc...
This makes sure it only runs once.

ps, sorry about formatting. 
Destructive 
Works like a destructor in C++ (*), I like the recursion guard you put in there, I don't remember seeing that before.

Another place where this can be helpful is if you have some kind of linked-list structure, where removing an entity would break the chain. You can set a removeFunction which repairs the list before and after the entity which is getting removed.

* How long can it be before we get a QC++ compiler bringing the full power of object orientation and inheritance to our favourite game? 
Loading MDL Files 
Trying to load .mdl files with java following this: http://tfc.duke.free.fr/coding/mdl-specs-en.html
For the most part, I got the data in fine, but for some reason, there seems to be a few extra bytes AFTER the frames that I don't know what to do with.
The number of bytes isn't consistent either, sometimes it's 10 bytes, other times it's 9 or 8.
Obviously, this screws up the next frame from loading properly because all the bytes are offset by however many were left over.

I tried just doing the dumb thing and skipping over these extra bytes after loading a frame, but the number of extra bytes can change within the same model.

Is this a real thing (extra bytes between frames) or am I just messing something up? 
 
Extra bytes between frames isn't normal. Possible that your struct sizes are being padded out to some alignment? I don't know Java so I'm not certain if it even does that, but it's the only off-the-top-o-me-head explanation I can think of. 
 
Thanks, I was just looking for confirmation that there are no extra bytes. :)

Java doesn't have structs or any of that, so I'm just reading everything in byte and byte and converting things to big endian ints and such.
I'm sure I'm just reading something in wrong or I missed something. 
Gotchas 
One of the things to watch out for is where there are mdl_vertex_t being loaded to define the bounding boxes of the frames and the like. Make sure you're reading the vertex normal in all of those places, even though it's not used. 
 
For the first frame, the data seems to be fine up to (at least that I can easily check) the frame name.
I parse each byte as a char until I get to the first byte that is 0, then I start loading vertex objects.

The problem seems to be somewhere during the vertex loading.

I'm using a 5 frame model with 5 verts.
Looking at the file itself, I see 48 bytes between one frame name and the next, so it looks like each frame is 48 bytes long. (the frame data actually starts 12 bytes before the name, there's one int (4 bytes) and 2 mdl_vertex_t (2 * 4bytes))

The mdl_vertex_t struct has an array of 3 unsigned chars and then a single uchar, so that means each vertex should be 4 bytes long.
So with 5 verts, that should mean that all the vertex info should be 5 * 4 = 20 bytes.
Take those 12 bytes mentioned above and we have 32 bytes. The name is "POLY1" so that should be 6 bytes for the name (including \0).
So in total that's 38 bytes and then 10 bytes left over. 
 
hm.. ok, seems like typing it out helped me see the problem...

Looks like the String for the frame name is ALWAYS 16 bytes, not until the next 0 value. It loads in some junk characters but that explains the 10 byte offset (16 - 6).

That's really bizarre. 
 
actually, I guess it sort of makes sense.
c just stops reading strings when it reaches the first \0, but I guess they didn't want to bother with a dynamically allocated char array so those junk bytes are actually whatever was on the guy's memory when he saved the file... 
Yup 
You have permission to zero all of that out nicely when you export though! Also, don't forget to test your code with grouped frames and grouped skins before you're through - it always seems to be going so well until that point... 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.