Tutorial: Rotating Brush Models for QuakeWorld

Post tutorials on how to do certain tasks within game or engine code here.
avirox
Posts: 137
Joined: Wed Aug 16, 2006 3:25 pm

Post by avirox »

I have an update for the rotating brush code which will allow brush models to simultaneously spin and move at the same time. The code is taken from FTE and implemented into qw/nq. I'll post it when I get the chance..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

I have something almost done that transparently supports origin brushes in the Worldcraft 3.3 Quake Adapter package without compiler support. :D

The preprocessing "nomapversion.exe" that strips out the "mapversion" field is being altered to locate origin brushes in entities and strip them out and substitute them with an origin field ("origin" "x y z").

This will make origin brushes with existing compilers available for playing around with in a quick way.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Image

Image

Image

The preprocessor is done.

A couple of slight annoyances: txqbsp isn't, in fact, compatible even with the doors as-is. I think I had a super coincidence with the one time that it worked, I might have had the actual center @ 0,0,0 which is the only spot on the map that it may actually work with txqbsp.

And hmap2 doesn't like the texture alignments in Worldcraft 3.x (Valve 220 format) and some surfaces the textures aren't the same as in the editor. It also somehow crashes the editor upon compile (but I can work around that ;) Still I'd like to find out why ...).

Haven't played around with the Half-Life compile tools yet, which already support all of this stuff anyway. I don't have whatever version of Visual Studio that is requierd to compile Zoner Tool's ... but since Zoner Tool's appears to support compiling via gcc and I have Cygwin all figured out now (I want to change some defaults and holy texture names and the hull size, of course ;) )
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

I've done some more experimentation and it appears that hmap2 only messes up the texture alignment with "rotate_" brushes and otherwise so far appears to work completely fine with Valve 220 format.
Note about Worldcraft 3.3 and hmap2 wrote:Something about hmap2 does crash Worldcraft 3.3 [probably something silly about Worldcraft], but that's fine for my purposes, I just wrote a little something to "encase" it to avoid the problem.

Besides, this little "encaser" is important because Worldcraft 3.3 doesn't support WAD2 and hmap2 doesn't support WAD3, but fortunately the Quake Adapter converts WAD2 to WAD3 so the "encaser" also changes .hlwad to .wad in worldspawn so I can transparently go about my business ...
And since I now have defacto origin brush support, but it needs testing, I have a hilarious idea ...

I think I'm going to rapidly do something I said I'd never do in order to give it the kind of test it needs.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Code note for NetQuake adaptations of this.

I ran into an annoying problem where after implementing Avirox's rotation support, backpacks from Enforcers and such would fall through the floor.

After examining the code, I have a have a small change that might even apply to the Quakeworld version.
// ROTATE START
// rotate endpos back to world frame of reference
if (ent->v.solid == SOLID_BSP &&
(ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
{
vec3_t a;
vec3_t forward, right, up;
vec3_t temp;

// Baker: note ... A couple of lines of this still needs done for non SOLID_BSP and SOLID_BSP without avelocity. At least in NetQuake for sure.
if (trace.fraction != 1)
{
VectorSubtract (vec3_origin, ent->v.angles, a);
AngleVectors (a, forward, right, up);

VectorCopy (trace.endpos, temp);
trace.endpos[0] = DotProduct (temp, forward);
trace.endpos[1] = -DotProduct (temp, right);
trace.endpos[2] = DotProduct (temp, up);

VectorCopy (trace.plane.normal, temp);
trace.plane.normal[0] = DotProduct (temp, forward);
trace.plane.normal[1] = -DotProduct (temp, right);
trace.plane.normal[2] = DotProduct (temp, up);
}
}
#if 1
// Non-Solid BSP and cases without avelocity.
else {
if (trace.fraction != 1)
VectorAdd (trace.endpos, offset, trace.endpos);

}
#endif


// ROTATE END
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Rotating doors ...

In Half-Life maps ...

Code: Select all

{
"model" "*42"
"origin" "983 214 -64"
"healthvalue" "0"
"health" "0"
"lip" "0"
"wait" "-1"
"stopsnd" "0"
"movesnd" "0"
"dmg" "0"
"rendercolor" "0"
"renderamt" "0"
"rendermode" "0"
"renderfx" "0"
"_minlight" "0"
"distance" "60"
"speed" "180"
"targetname" "sine1"
"spawnflags" "98"
"classname" "func_door_rotating"
}
Spawn flags appear to indicate the axis of rotation as such from hl_doors.qc from Avirox's QuakeLife.

Code: Select all

	if (self.spawnflags & DOOR_X_AXIS)
		self.movedir_z = 1.0;
	else if (self.spawnflags & DOOR_Y_AXIS)
		self.movedir_x = 1.0;
	else // Z_AXIS
		self.movedir_y = 1.0;

	// check for reverse rotation
	if (self.spawnflags & DOOR_REVERSE)
		self.movedir = '0 0 0' - self.movedir;

Code: Select all

float DOOR_REVERSE		= 2;
float DOOR_X_AXIS		= 64;
float DOOR_Y_AXIS		= 128;
Distance is maybe the degrees it opens it would seem.

Code: Select all

	self.pos1 = self.angles;
	self.pos2 = self.angles + self.movedir * self.distance;
Avirox has "hl_use" in the QuakeC quite a bit in the doors area, which appears to be for the "use" key in Half-Life.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Almost anti-climatically, I have rotating doors written in QuakeC.

Errr ... um ... well I ripped it from Avirox's work in QuakeLife but anyway the full implementation is now in hand.

1. entity definition
2. origin brush preprocessor (rips out origin brushes and substitutes origin coordinates into entity)
3. map compiler
4. the engine
5. the QuakeC

Maybe I can mellow out now. In the last 3-4 days, I've managed to successfully get a lot of things done. Only now do I realize being ripped away from all my projects back in February really affected my attitude. I had all these things I was in the middle of doing and then from out of nowhere .... SLAM ... zero time for months.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

Very true. Remember when we used to actually only play Quake?
Chip
Posts: 575
Joined: Wed Jan 21, 2009 9:12 am
Location: Dublin, Ireland
Contact:

Post by Chip »

r00k wrote:Very true. Remember when we used to actually only play Quake?
I did this 2 days ago. Played several mods for hours. I just couldn't stop. That's why I love Quake.
QuakeWiki
getButterfly - WordPress Support Services
Roo Holidays

Fear not the dark, but what the dark hides.
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

Baker:

I looked back through world.c in Qrack and i'm using LordHavoc's early DP code,

Code: Select all

trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
{
	trace_t	trace;
	vec3_t	offset, start_l, end_l;
	hull_t	*hull;

// fill in a default trace
	memset (&trace, 0, sizeof(trace_t));
	trace.fraction = 1;
	trace.allsolid = true;
	VectorCopy (end, trace.endpos);

// get the clipping hull
	hull = SV_HullForEntity (ent, mins, maxs, offset);

	VectorSubtract (start, offset, start_l);
	VectorSubtract (end, offset, end_l);

// LordHavoc: enabling rotating bmodels
// rotate start and end into the models frame of reference
	if (ent->v.solid == SOLID_BSP && (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]))
	{
		vec3_t	forward, right, up;
		vec3_t	temp;

		AngleVectors (ent->v.angles, forward, right, up);

		VectorCopy (start_l, temp);
		start_l[0] = DotProduct (temp, forward);
		start_l[1] = -DotProduct (temp, right);
		start_l[2] = DotProduct (temp, up);

		VectorCopy (end_l, temp);
		end_l[0] = DotProduct (temp, forward);
		end_l[1] = -DotProduct (temp, right);
		end_l[2] = DotProduct (temp, up);
	}

// trace a line through the apropriate clipping hull
	SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);

// LordHavoc: enabling rotating bmodels
// rotate endpos back to world frame of reference
	if (ent->v.solid == SOLID_BSP && (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]))
	{
		vec3_t	a;
		vec3_t	forward, right, up;
		vec3_t	temp;

		if (trace.fraction != 1)
		{
			VectorNegate (ent->v.angles, a);
			AngleVectors (a, forward, right, up);

			VectorCopy (trace.endpos, temp);
			trace.endpos[0] = DotProduct (temp, forward);
			trace.endpos[1] = -DotProduct (temp, right);
			trace.endpos[2] = DotProduct (temp, up);

			VectorCopy (trace.plane.normal, temp);
			trace.plane.normal[0] = DotProduct (temp, forward);
			trace.plane.normal[1] = -DotProduct (temp, right);
			trace.plane.normal[2] = DotProduct (temp, up);
		}
	}

// fix trace up by the offset
	if (trace.fraction != 1)
		VectorAdd (trace.endpos, offset, trace.endpos);

// did we clip the move?
	if (trace.fraction < 1 || trace.startsolid)
		trace.ent = ent;

	return trace;
}
if I place an ELSE before "//fix trace up by offset", as you have in your code:

Code: Select all

#if 1
// Non-Solid BSP and cases without avelocity.
else {
if (trace.fraction != 1)
VectorAdd (trace.endpos, offset, trace.endpos);

}
#endif 
then if I touch the backside of the door when its open I can walk through it and I am pushed out of it's radius. :|
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

you need correct absmin/absmax too (SV_LinkEdict).
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

exactly

Code: Select all

// set the abs box
// LordHavoc: enabling rotating bmodels
	if (ent->v.solid == SOLID_BSP && (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]))
	{
		// expand for rotation
		float		max, v;
		int			i;

		max = DotProduct(ent->v.mins, ent->v.mins);
		v = DotProduct(ent->v.maxs, ent->v.maxs);

		if (max < v)
			max = v;
		max = sqrt(max);

		for (i=0 ; i<3 ; i++)
		{
			ent->v.absmin[i] = ent->v.origin[i] - max;
			ent->v.absmax[i] = ent->v.origin[i] + max;
		}
	}
	else
	{
		VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
		VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
	}	
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

My test implementation of rotation + rotation.qc I *can* walk through doors in DarkPlaces but not in an Avirox tutorial-modified engine (with or without that small extra modification I posted that keeps backpacks from falling through floors in NQ).

I'll see if I can finish a complete "package" this week for scrutiny.

R00k, I'm not quite sure what you are getting at (maybe I'm missing it) but adapting the Avirox-tutorial to NQ it was missing the original code (at least for NQ) for non-solid BSP which is all I added in with the ELSE clause.

I could post a before and after.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

I downloaded your test map and qc in your .rar file
gamedir rotate
map rotate_example

the bridge is fine but the doors, ill open them go inside, turn left behind the door face back towards the starting spawn point then walk into the door, no clipping but then i get a big push in origin*forward. All because I put an ELSE in the code as you have.
using the SV_ClipMoveToEntity code (i posted earlier) without the ELSE in the last part
and your example works perfectly for me. I wasnt sure if that ELSE should actually be there.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

r00k, you don't want to do VectorAdd (trace.endpos, offset, trace.endpos); twice, if I understand what you're doing. Which I probably don't.
Post Reply