Tutorial: Visible bboxes

Discuss programming in the QuakeC language.
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Tutorial: Visible bboxes

Post by behind_you »

Tutorial: Visible bounding boxes

ello! I am about to explain the technique for getting your bounding boxes to be visible with only quakec. I am pretty sure that just about every quakec modder will find this very useful! NOT A BAD CREATION FOR SOMEONE AS NOOBY AS MYSELF, NO?

Picture paints a thousand words:

Image

First I must explain a few things. This code utilizes TE_TEI_G3. It's an odd, undocumented extension in DP and probably FTE that draws a line (if a targa named nexbeam.tga is found in the particles folder (Here is an example), it will draw that instead) between two vectors, AKA sort of like a laser. That means that this will only work with engines that support this extension. Another thing is that this code can dramatically slow down the fps when updated frequently and/or used on many entities, so don’t go nuts with it. Lastly, this code reveals the many flaws with quake’s bounding box system; mainly you will notice that bounding boxes cannot change angles with the player, which is downright ridiculous.

So, onto the juicy code, shall we? Add the TE_TEI_G3 extension found below to either defs.qc or where it should’ve been, dpextensions.qc:

Code: Select all

void(vector start, vector end) te_tei_g3 =
{
	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, 76);
	WriteCoord (MSG_BROADCAST, start_x);
	WriteCoord (MSG_BROADCAST, start_y);
	WriteCoord (MSG_BROADCAST, start_z);
	WriteCoord (MSG_BROADCAST, end_x);
	WriteCoord (MSG_BROADCAST, end_y);
	WriteCoord (MSG_BROADCAST, end_z);
	WriteCoord (MSG_BROADCAST, 0);
	WriteCoord (MSG_BROADCAST, 0);
	WriteCoord (MSG_BROADCAST, 0);
};
Ok, now to add my clever little code (best to add right below the te_tei_g3 code):

Code: Select all

void() viewbbox = //behind_you's visible bbox code
{
	local vector minnx, minny, minnz, maxxx, maxxy, maxxz;// bunch of definitions for use
	
	minnx_x = self.mins_x;
	minny_y = self.mins_y;
	minnz_z = self.mins_z;
	maxxx_x = self.maxs_x;
	maxxy_y = self.maxs_y;
	maxxz_z = self.maxs_z;
	
	//the code below connects all the points to form the bbox, using the fantabulous te_tei_g3 extension:
	
	te_tei_g3 (self.origin + minnx + minny + minnz, self.origin + minnx + minny + maxxz);
	te_tei_g3 (self.origin + maxxx + maxxy + minnz, self.origin + maxxx + maxxy + maxxz);
	te_tei_g3 (self.origin + maxxx + minny + minnz, self.origin + maxxx + minny + maxxz);
	te_tei_g3 (self.origin + minnx + maxxy + minnz, self.origin + minnx + maxxy + maxxz);
	
	te_tei_g3 (self.origin + minnx + maxxy + maxxz, self.origin + maxxx + maxxy + maxxz);
	te_tei_g3 (self.origin + minnx + minny + maxxz, self.origin + maxxx + minny + maxxz);
	te_tei_g3 (self.origin + minnx + minny + maxxz, self.origin + minnx + maxxy + maxxz);
	te_tei_g3 (self.origin + maxxx + minny + maxxz, self.origin + maxxx + maxxy + maxxz);
	
	te_tei_g3 (self.origin + minnx + maxxy + minnz, self.origin + maxxx + maxxy + minnz);
	te_tei_g3 (self.origin + minnx + minny + minnz, self.origin + maxxx + minny + minnz);
	te_tei_g3 (self.origin + minnx + minny + minnz, self.origin + minnx + maxxy + minnz);
	te_tei_g3 (self.origin + maxxx + minny + minnz, self.origin + maxxx + maxxy + minnz);
	//there are 12 line codes above, and 12 edges in a cube.
	
	self.nextthink = time + 0.1;//if game slows down too much, try increasing the 0.1
};
Ok, if you want to see a particular entity’s bbox, add one of these codes to the entity's spawn function (NOT before setsize is called):

Code: Select all

viewbbox();
OR

Code: Select all

self.think = viewbbox;
self.nextthink = time + 0.1;
If one doesn’t work, the other probably will.

Because I love helping coders learn and I really do not want this to be yet another copy paste code, I will explain the above code in detail for those who don't understand. Whenever you setsize a code, you do something similar to this: setsize (self, '-5 -5 -5', '5 5 5');. You are giving the entity two vectors, a minimum and a maximum (setsize (self, SELF.MINS, SELF.MAXS);)

Now, above you see the line that reads:
minnx_x = self.mins_x;

The vector 'minnx' is getting it's 'x' variable equal to the entity's self.mins_x variable. In the end, the vector minnx becomes equal to 'self.mins_x 0 0'. Same thing with:

maxxx_x = self.maxs_x;

This time you are doing this, maxxx = 'self.maxs_x 0 0'. By giving each vector only one variable, adding them becomes less of a hassle because if you did this: self.origin + self.maxs_x, you would get a type mismatch error since you cannot add a vector and a float.

same case here:

minny_y = self.mins_y;
AKA:
minny = '0 self.mins_y 0';

maxxy_y = self.maxs_y;
AKA:
maxxy = '0 self.maxs_y 0';

and here:

minnz_z = self.mins_z;
AKA:
minnz = '0 0 self.mins_z';

maxxz_z = self.maxs_z;
AKA:
maxxz = '0 0 self.maxs_z';

Why add all these variables in the first place? Because of the following.

Quakec quirks make life hard sometimes. This is one case. Directly using an entity's mins or maxs vectors doesn't work for some strange reason, I don't know if it's quakec's fault or just my luck.

So, now how do i connect all the lines that form our bbox? Bear with this explanation:

minnx means backwards
maxxx means forwards
minny means to the left
maxxy means to the right
minnz means down
maxxz means up

remember this!

now:
te_tei_g3 (self.origin + minnx + minny + minnz, self.origin + minnx + minny + maxxz);

"self.origin + minnx + minny + minnz"

this translates into: start at the origin. go as backwards as you can, then go as left as you can, and then go as down as you can. You will be at the bottom left corner of your bbox, first point of line.

start again:

"self.origin + minnx + minny + maxxz"

this means: start at origin, go as backwards as you can, then go as left as you can, then go as UP as you can, you will be at the top left corner of your bbox! second point of line.

connect these points and you will have your first line that connects the bottom left corner and top left corner of your bbox!

The rest of it does the same. Since there are 12 edges in a cube, you find 12 variations of this code!

comprende?
===================================================

Compile and run! ;D

Hope you like it!

BONUS: DP’s other undocumented extensions:

Code: Select all

void(vector pos, vector dir, float howmuch) te_tei_smoke = //makes smoke effect, best when you edit effectinfo.txt as well
{
	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, 77);
	WriteCoord (MSG_BROADCAST, pos_x);
	WriteCoord (MSG_BROADCAST, pos_y);
	WriteCoord (MSG_BROADCAST, pos_z);
	WriteCoord (MSG_BROADCAST, dir_x);
	WriteCoord (MSG_BROADCAST, dir_y);
	WriteCoord (MSG_BROADCAST, dir_z);
	WriteByte (MSG_BROADCAST, howmuch);
};

void(vector pos) te_tei_bigexplosion = //bigger explosion
{
	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, 78);
	WriteCoord (MSG_BROADCAST, pos_x);
	WriteCoord (MSG_BROADCAST, pos_y);
	WriteCoord (MSG_BROADCAST, pos_z);
};

void(vector pos, vector dir, float howmuch) te_tei_plasmahit =// cool little plasma effect
{
	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, 79);
	WriteCoord (MSG_BROADCAST, pos_x);
	WriteCoord (MSG_BROADCAST, pos_y);
	WriteCoord (MSG_BROADCAST, pos_z);
	WriteCoord (MSG_BROADCAST, dir_x);
	WriteCoord (MSG_BROADCAST, dir_y);
	WriteCoord (MSG_BROADCAST, dir_z);
	WriteByte (MSG_BROADCAST, howmuch);
};
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

note that hull positions are not identical to bbox positions - anything clipping against world has a different bbox, which is a function of its absmin, the size of its bbox, and the hard-coded hull sizes of the qbsp+engine.
GiffE
Posts: 170
Joined: Sun Oct 08, 2006 3:39 pm
Location: USA, CT
Contact:

Post by GiffE »

OR! You could reduce that to 1 line of code:

Code: Select all

r_showbboxes 1
daemonicky
Posts: 185
Joined: Wed Apr 13, 2011 1:34 pm

Post by daemonicky »

I thought it could be achieved by having some simple cube spawned 12 times (4 for top, 4 for bottom and 4 for sides) and stretched so, that they reates lines of bounding box.

Not sure if it is possible in Quake by either alias model or brush model. If it is possible it should work in vanilla Quake I guess.
Think, touch, movetype, solid, traceline ...
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

GiffE wrote:OR! You could reduce that to 1 line of code:

Code: Select all

r_showbboxes 1
doesn't work in DP for me
dreadlorde
Posts: 268
Joined: Tue Nov 24, 2009 2:20 am
Contact:

Post by dreadlorde »

GiffE wrote:OR! You could reduce that to 1 line of code:

Code: Select all

r_showbboxes 1
That's specific to fitzquake iirc.
Ken Thompson wrote:One of my most productive days was throwing away 1000 lines of code.
Get off my lawn!
GiffE
Posts: 170
Joined: Sun Oct 08, 2006 3:39 pm
Location: USA, CT
Contact:

Post by GiffE »

behind_you wrote:
GiffE wrote:OR! You could reduce that to 1 line of code:

Code: Select all

r_showbboxes 1
doesn't work in DP for me
:?
Image
(Jan. 18th 2011 Build of DP)
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

As Spike said, there are two different types of bounding boxes in use in the engine - server-side and client-side (or more specifically, renderer-side).

Regarding the size of the server-side bounding-boxes, assuming you don't want gameplay changes, the golden rule is - don't mess with them.

Client-side you can do what you want. Adapt MDL bounding boxes to per-frame, derive brush model bounding boxes from the actual surface vertex positions, rotate and scale them, whatever you want. They're only used for view frustum culling and so long as the resulting box is still valid for use with that, they're your's to play with.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

mh wrote:As Spike said, there are two different types of bounding boxes in use in the engine - server-side and client-side (or more specifically, renderer-side).

Regarding the size of the server-side bounding-boxes, assuming you don't want gameplay changes, the golden rule is - don't mess with them.

Client-side you can do what you want. Adapt MDL bounding boxes to per-frame, derive brush model bounding boxes from the actual surface vertex positions, rotate and scale them, whatever you want. They're only used for view frustum culling and so long as the resulting box is still valid for use with that, they're your's to play with.
Ok but why shouldn't you mess with them server side? And is it possible to actually rotate bboxes in csqc? how do u do that?

I figured out that r_showbboxes works in DP. Wow, there goes my efforts :P .
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

behind_you wrote:Ok but why shouldn't you mess with them server side?
Because it's a gameplay change.
behind_you wrote:And is it possible to actually rotate bboxes in csqc? how do u do that?
No idea, sorry. I rotate them engine-side and it works quite fine; I've posted a tutorial somewhere here containing C code for it which might be translatable to CSQC. Ask me anything you want about the C side, but I really know virtually nothing about QC of any kind.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

mh wrote: Because it's a gameplay change.
Ok, but modding is changing gameplay, so it's okay to rotate them server side? or am i misunderstanding?
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

behind_you wrote:
mh wrote: Because it's a gameplay change.
Ok, but modding is changing gameplay, so it's okay to rotate them server side? or am i misunderstanding?
Not in the engine, because a change in the engine is going to affect all mods, including ID1.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

mh wrote:
behind_you wrote:
mh wrote: Because it's a gameplay change.
Ok, but modding is changing gameplay, so it's okay to rotate them server side? or am i misunderstanding?
Not in the engine, because a change in the engine is going to affect all mods, including ID1.

I c. well I'm not modding engine, just qc. So I'll mess with them :D.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

i dont think changing your bboxes for mapping purposes will matter. if you cant fit through a hole you wont be able to no matter what, that's all dependent on something in the mapping side of things, i think.

(just assuming that's your reasoning)
metlslime
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Post by metlslime »

1. you can't rotate bboxes in quakec; if you rotate the entity the box will stay un-rotated. They are literally "axis-aligned bounding boxes" which means they are always axis-aligned.

2. if you resize bboxes in quakec, it will work for entity-v-entity and traceline-v-entity collision, but entity-vs-world collision will still use one of the standard collision hull sizes.
Post Reply