From 47c401f4ecd9e344f8d9b68bc5ba307d5836b60c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 19 Jan 2007 02:00:39 +0000 Subject: [PATCH] - Replaced the vector math routines with the ones I developed for the FP code. SVN r454 (trunk) --- docs/rh-log.txt | 3 + src/b_func.cpp | 4 +- src/empty.cpp | 2 +- src/g_strife/a_loremaster.cpp | 18 +- src/nodebuild_gl.cpp | 8 +- src/p_buildmap.cpp | 22 +- src/p_effect.cpp | 143 ++-- src/p_effect.h | 3 +- src/p_map.cpp | 16 +- src/p_mobj.cpp | 17 +- src/p_setup.cpp | 61 +- src/p_things.cpp | 53 +- src/r_plane.cpp | 26 +- src/sdl/i_main.cpp | 498 ++++++------- src/tarray.h | 6 +- src/thingdef_codeptr.cpp | 8 +- src/vectors.cpp | 253 ------- src/vectors.h | 1261 +++++++++++++++++++++++++++++++- src/win32/i_main.cpp | 2 +- zdoom.vcproj | 1270 ++++++++++++++++----------------- 20 files changed, 2279 insertions(+), 1395 deletions(-) delete mode 100644 src/vectors.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 88ba2cd72..0339f0545 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +January 18, 2007 +- Replaced the vector math routines with the ones I developed for the FP code. + January 15, 2007 - Added a summonfoe CCMD, which is analagous to summonfriend but forces the summoned creature to be hostile instead. diff --git a/src/b_func.cpp b/src/b_func.cpp index 27d33af96..c86f42205 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -482,13 +482,13 @@ fixed_t DCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd) th->target = source; // where it came from - vec3_t velocity; float speed = (float)th->Speed; + FVector3 velocity; velocity[0] = FIXED2FLOAT(dest->x - source->x); velocity[1] = FIXED2FLOAT(dest->y - source->y); velocity[2] = FIXED2FLOAT(dest->z - source->z); - VectorNormalize (velocity); + velocity.MakeUnit(); th->momx = FLOAT2FIXED(velocity[0] * speed); th->momy = FLOAT2FIXED(velocity[1] * speed); th->momz = FLOAT2FIXED(velocity[2] * speed); diff --git a/src/empty.cpp b/src/empty.cpp index 4c07e6072..87773c6b7 100644 --- a/src/empty.cpp +++ b/src/empty.cpp @@ -3,7 +3,7 @@ ** ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index 21e54f524..de3b12a83 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -148,18 +148,18 @@ END_DEFAULTS int ALoreShot::DoSpecialDamage (AActor *target, int damage) { - vec3_t thrust; + FVector3 thrust; - thrust[0] = float(this->target->x - target->x); - thrust[1] = float(this->target->y - target->y); - thrust[2] = float(this->target->z - target->z); + thrust.X = float(this->target->x - target->x); + thrust.Y = float(this->target->y - target->y); + thrust.Z = float(this->target->z - target->z); - VectorNormalize (thrust); - VectorScale (thrust, float((255*50*FRACUNIT) / (target->Mass ? target->Mass : 1)), thrust); + thrust.MakeUnit(); + thrust *= float((255*50*FRACUNIT) / (target->Mass ? target->Mass : 1)); - target->momx += fixed_t(thrust[0]); - target->momy += fixed_t(thrust[1]); - target->momz += fixed_t(thrust[2]); + target->momx += fixed_t(thrust.X); + target->momy += fixed_t(thrust.Y); + target->momz += fixed_t(thrust.Z); return damage; } diff --git a/src/nodebuild_gl.cpp b/src/nodebuild_gl.cpp index 501ecdf16..475bccd21 100644 --- a/src/nodebuild_gl.cpp +++ b/src/nodebuild_gl.cpp @@ -231,10 +231,10 @@ DWORD FNodeBuilder::AddMiniseg (int v1, int v2, DWORD partner, DWORD seg1, DWORD newseg.linedef = -1; newseg.loopnum = 0; newseg.next = DWORD_MAX; - newseg.planefront = true; - newseg.hashnext = NULL; - newseg.storedseg = NULL; - newseg.frontsector = NULL; + newseg.planefront = true; + newseg.hashnext = NULL; + newseg.storedseg = DWORD_MAX; + newseg.frontsector = NULL; newseg.backsector = NULL; if (splitseg != DWORD_MAX) diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index eb9a7652b..8671b2833 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -692,7 +692,7 @@ static void CreateStartSpot (fixed_t *pos, mapthing2_t *start) static void CalcPlane (SlopeWork &slope, secplane_t &plane) { - vec3_t pt[3]; + FVector3 pt[3]; long j; slope.x[0] = slope.wal->x; slope.y[0] = slope.wal->y; @@ -711,23 +711,13 @@ static void CalcPlane (SlopeWork &slope, secplane_t &plane) -slope.dy, slope.x[2]-slope.wal->x); slope.z[2] += Scale (slope.heinum, j, slope.i); - pt[0][0] = float(slope.dx); - pt[0][1] = float(-slope.dy); - pt[0][2] = 0.f; + pt[0] = FVector3(slope.dx, -slope.dy, 0); + pt[1] = FVector3(slope.x[2] - slope.x[0], slope.y[0] - slope.y[2], (slope.z[2] - slope.z[0]) / 16); + pt[2] = (pt[0] ^ pt[1]).Unit(); - pt[1][0] = float(slope.x[2] - slope.x[0]); - pt[1][1] = float(slope.y[0] - slope.y[2]); - pt[1][2] = float(slope.z[2] - slope.z[0]) / 16.f; - - CrossProduct (pt[0], pt[1], pt[2]); - VectorNormalize (pt[2]); - - if ((pt[2][2] < 0 && plane.c > 0) || - (pt[2][2] > 0 && plane.c < 0)) + if ((pt[2][2] < 0 && plane.c > 0) || (pt[2][2] > 0 && plane.c < 0)) { - pt[2][0] = -pt[2][0]; - pt[2][1] = -pt[2][1]; - pt[2][2] = -pt[2][2]; + pt[2] = -pt[2]; } plane.a = fixed_t(pt[2][0]*65536.f); diff --git a/src/p_effect.cpp b/src/p_effect.cpp index de88f3a84..c66d198c5 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -423,21 +423,20 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i } } -void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int color2, float maxdiff, bool silent) +void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff, bool silent) { - float length; + double length, lengthsquared; int steps, i; - float deg; - vec3_t step, dir, pos, extend; + FAngle deg; + FVector3 step, dir, pos, extend; - VectorSubtract (end, start, dir); - length = VectorLength (dir); - steps = (int)(length*0.3333f); + dir = end - start; + lengthsquared = dir | dir; + length = sqrt(lengthsquared); + steps = int(length / 3); - if (length) + if (steps) { - length = 1 / length; - if (!silent) { int sound; @@ -451,27 +450,27 @@ void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int // The railgun's sound is special. It gets played from the // point on the slug's trail that is closest to the hearing player. AActor *mo = players[consoleplayer].camera; - vec3_t point; - float r; + FVector3 point; + double r; float dirz; - if (abs(mo->x - FLOAT2FIXED(start[0])) < 20 * FRACUNIT - && (mo->y - FLOAT2FIXED(start[1])) < 20 * FRACUNIT) + if (abs(mo->x - FLOAT2FIXED(start.X)) < 20 * FRACUNIT + && (mo->y - FLOAT2FIXED(start.Y)) < 20 * FRACUNIT) { // This player (probably) fired the railgun S_SoundID (mo, CHAN_WEAPON, sound, 1, ATTN_NORM); } else { // Only consider sound in 2D (for now, anyway) - r = ((start[1] - FIXED2FLOAT(mo->y)) * (-dir[1]) - - (start[0] - FIXED2FLOAT(mo->x)) * (dir[0])) * length * length; + r = ((start.Y - FIXED2FLOAT(mo->y)) * (-dir.Y) - + (start.X - FIXED2FLOAT(mo->x)) * (dir.X)) * length * length; - dirz = dir[2]; - dir[2] = 0; - VectorMA (start, r, dir, point); - dir[2] = dirz; + dirz = dir.Z; + dir.Z = 0; + point = start + r * dir; + dir.Z = dirz; - S_SoundID (FLOAT2FIXED(point[0]), FLOAT2FIXED(point[1]), mo->z, + S_SoundID (FLOAT2FIXED(point.X), FLOAT2FIXED(point.Y), mo->z, CHAN_WEAPON, sound, 1, ATTN_NORM); } } @@ -482,20 +481,37 @@ void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int return; } - VectorScale2 (dir, length); - PerpendicularVector (extend, dir); - VectorScale2 (extend, 3); - VectorScale (dir, 3, step); + dir /= length; + //Calculate PerpendicularVector (extend, dir): + double minelem = 1; + int epos; + for (epos = 0, i = 0; i < 3; ++i) + { + if (fabs(dir[i]) < minelem) + { + epos = i; + minelem = fabs(dir[i]); + } + } + FVector3 tempvec(0,0,0); + tempvec[epos] = 1; + extend = tempvec - (dir | tempvec) * dir; + // + + extend *= 3; + step = dir * 3; + + // Create the outer spiral. if (color1 != -1) { - color1 = color1==0? -1: ColorMatcher.Pick(RPART(color1), GPART(color1), BPART(color1)); - VectorCopy (start, pos); - deg = 270; + color1 = color1 == 0 ? -1 : ColorMatcher.Pick(RPART(color1), GPART(color1), BPART(color1)); + pos = start; + deg = FAngle(270); for (i = steps; i; i--) { particle_t *p = NewParticle (); - vec3_t tempvec; + FVector3 tempvec; if (!p) return; @@ -505,20 +521,18 @@ void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int p->fade = FADEFROMTTL(35); p->size = 3; - RotatePointAroundVector (tempvec, dir, extend, deg); - p->velx = FLOAT2FIXED(tempvec[0])>>4; - p->vely = FLOAT2FIXED(tempvec[1])>>4; - p->velz = FLOAT2FIXED(tempvec[2])>>4; - VectorAdd (tempvec, pos, tempvec); - deg += 14; - if (deg >= 360) - deg -= 360; - p->x = FLOAT2FIXED(tempvec[0]); - p->y = FLOAT2FIXED(tempvec[1]); - p->z = FLOAT2FIXED(tempvec[2]); - VectorAdd (pos, step, pos); + tempvec = FMatrix3x3(dir, deg) * extend; + p->velx = FLOAT2FIXED(tempvec.X)>>4; + p->vely = FLOAT2FIXED(tempvec.Y)>>4; + p->velz = FLOAT2FIXED(tempvec.Z)>>4; + tempvec += pos; + p->x = FLOAT2FIXED(tempvec.X); + p->y = FLOAT2FIXED(tempvec.Y); + p->z = FLOAT2FIXED(tempvec.Z); + pos += step; + deg += FAngle(14); - if (color1==-1) + if (color1 == -1) { int rand = M_Random(); @@ -538,13 +552,13 @@ void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int } } + // Create the inner trail. if (color2 != -1) { - color2 = color2==0? -1: ColorMatcher.Pick(RPART(color2), GPART(color2), BPART(color2)); - vec3_t diff; - VectorSet (diff, 0, 0, 0); + color2 = color2 == 0 ? -1 : ColorMatcher.Pick(RPART(color2), GPART(color2), BPART(color2)); + FVector3 diff(0, 0, 0); - VectorCopy (start, pos); + pos = start; for (i = steps; i; i--) { particle_t *p = JitterParticle (33); @@ -556,38 +570,33 @@ void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int { int rnd = M_Random (); if (rnd & 1) - diff[0] = clamp (diff[0] + ((rnd & 8) ? 1 : -1), -maxdiff, maxdiff); + diff.X = clamp (diff.X + ((rnd & 8) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 2) - diff[1] = clamp (diff[1] + ((rnd & 16) ? 1 : -1), -maxdiff, maxdiff); + diff.Y = clamp (diff.Y + ((rnd & 16) ? 1 : -1), -maxdiff, maxdiff); if (rnd & 4) - diff[2] = clamp (diff[2] + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff); + diff.Z = clamp (diff.Z + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff); } - vec3_t postmp; - VectorCopy (pos, postmp); - VectorAdd (postmp, diff, postmp); + FVector3 postmp = pos + diff; p->size = 2; - p->x = FLOAT2FIXED(postmp[0]); - p->y = FLOAT2FIXED(postmp[1]); - p->z = FLOAT2FIXED(postmp[2]); + p->x = FLOAT2FIXED(postmp.X); + p->y = FLOAT2FIXED(postmp.Y); + p->z = FLOAT2FIXED(postmp.Z); if (color1 != -1) p->accz -= FRACUNIT/4096; - VectorAdd (pos, step, pos); + pos += step; - if (color2==-1) + if (color2 == -1) { - { - int rand = M_Random(); + int rand = M_Random(); - if (rand < 85) - p->color = grey4; - else if (rand < 170) - p->color = grey2; - else - p->color = grey1; - } - p->color = white; + if (rand < 85) + p->color = grey4; + else if (rand < 170) + p->color = grey2; + else + p->color = grey1; } else { diff --git a/src/p_effect.h b/src/p_effect.h index 57afdc810..4f1dbf0d8 100644 --- a/src/p_effect.h +++ b/src/p_effect.h @@ -32,6 +32,7 @@ */ #include "vectors.h" +#include "tables.h" #define FX_ROCKET 0x00000001 #define FX_GRENADE 0x00000002 @@ -58,7 +59,7 @@ void P_RunEffects (void); void P_RunEffect (AActor *actor, int effects); -void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int color2, float maxdiff = 0, bool silent = false); +void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff = 0, bool silent = false); void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind); void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind); void P_DisconnectEffect (AActor *actor); diff --git a/src/p_map.cpp b/src/p_map.cpp index 7cbdf4973..9a7c1beb7 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3081,7 +3081,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color fixed_t vx, vy, vz; angle_t angle, pitch; fixed_t x1, y1; - vec3_t start, end; + FVector3 start, end; FTraceResults trace; pitch = (angle_t)(-source->pitch) >> ANGLETOFINESHIFT; @@ -3100,7 +3100,9 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color y1 += offset*finesine[angle]; RailHits.Clear (); - VectorFixedSet (start, x1, y1, shootz); + start.X = FIXED2FLOAT(x1); + start.Y = FIXED2FLOAT(y1); + start.Z = FIXED2FLOAT(shootz); Trace (x1, y1, shootz, source->Sector, vx, vy, vz, 8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, @@ -3179,7 +3181,9 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color P_TraceBleed (damage, x, y, z, RailHits[i].HitActor, angle, pitch); } - VectorFixedSet (end, trace.X, trace.Y, trace.Z); + end.X = FIXED2FLOAT(trace.X); + end.Y = FIXED2FLOAT(trace.Y); + end.Z = FIXED2FLOAT(trace.Z); P_DrawRailTrail (source, start, end, color1, color2, maxdiff, silent); } @@ -3508,7 +3512,7 @@ int bombdistance; float bombdistancefloat; bool DamageSource; FName bombmod; -vec3_t bombvec; +FVector3 bombvec; bool bombdodamage; //============================================================================= @@ -3710,7 +3714,9 @@ void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FNa bombdamagefloat = (float)damage; bombmod = damageType; bombdodamage = dodamage; - VectorPosition (spot, bombvec); + bombvec.X = FIXED2FLOAT(spot->x); + bombvec.Y = FIXED2FLOAT(spot->y); + bombvec.Z = FIXED2FLOAT(spot->z); radbt.Clear(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5849d816e..fa957e25e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4402,7 +4402,6 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, P_PlaySpawnSound(th, source); th->target = source; // record missile's originator - vec3_t velocity; float speed = (float)(th->Speed); // [RH] @@ -4411,23 +4410,21 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, // missile? I'll leave it like this for now. // Answer. No, because this way, you can set up sets of parallel missiles. - velocity[0] = (float)(dest->x - source->x); - velocity[1] = (float)(dest->y - source->y); - velocity[2] = (float)(dest->z - source->z); + FVector3 velocity(dest->x - source->x, dest->y - source->y, dest->z - source->z); // Floor and ceiling huggers should never have a vertical component to their velocity if (defflags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)) { - velocity[2] = 0.f; + velocity.Z = 0; } // [RH] Adjust the trajectory if the missile will go over the player's head. else if (z - source->z >= dest->height) { - velocity[2] += (float)(dest->height - z + source->z); + velocity.Z += dest->height - z + source->z; } - VectorNormalize (velocity); - th->momx = (fixed_t)(velocity[0] * speed); - th->momy = (fixed_t)(velocity[1] * speed); - th->momz = (fixed_t)(velocity[2] * speed); + velocity.Resize (speed); + th->momx = (fixed_t)(velocity.X); + th->momy = (fixed_t)(velocity.Y); + th->momz = (fixed_t)(velocity.Z); // invisible target: rotate velocity vector in 2D if (dest->flags & MF_SHADOW) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index b6ec9c309..4ef85a4b1 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1299,7 +1299,7 @@ static void P_SlopeLineToPoint (int lineid, fixed_t x, fixed_t y, fixed_t z, boo plane = &sec->floorplane; } - vec3_t p, v1, v2, cross; + FVector3 p, v1, v2, cross; p[0] = FIXED2FLOAT (line->v1->x); p[1] = FIXED2FLOAT (line->v1->y); @@ -1311,19 +1311,18 @@ static void P_SlopeLineToPoint (int lineid, fixed_t x, fixed_t y, fixed_t z, boo v2[1] = FIXED2FLOAT (y - line->v1->y); v2[2] = FIXED2FLOAT (z) - p[2]; - CrossProduct (v1, v2, cross); - if (VectorLength (cross) == 0) + cross = v1 ^ v2; + double len = cross.Length(); + if (len == 0) { Printf ("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16)); return; } - VectorNormalize (cross); + cross /= len; // Fix backward normals - if ((cross[2] < 0 && !slopeCeil) || (cross[2] > 0 && slopeCeil)) + if ((cross.Z < 0 && !slopeCeil) || (cross.Z > 0 && slopeCeil)) { - cross[0] = -cross[0]; - cross[1] = -cross[1]; - cross[2] = -cross[2]; + cross = -cross; } plane->a = FLOAT2FIXED (cross[0]); @@ -1401,12 +1400,12 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, xyang = (angle_t)Scale (xyangi, ANGLE_90, 90 << ANGLETOFINESHIFT); - vec3_t norm; + FVector3 norm; norm[0] = float(finecosine[zang]) * float(finecosine[xyang]); norm[1] = float(finecosine[zang]) * float(finesine[xyang]); norm[2] = float(finesine[zang]) * 65536.f; - VectorNormalize (norm); + norm.MakeUnit(); plane->a = (int)(norm[0] * 65536.f); plane->b = (int)(norm[1] * 65536.f); plane->c = (int)(norm[2] * 65536.f); @@ -1432,7 +1431,7 @@ void P_VavoomSlope(sector_t * sec, int id, fixed_t x, fixed_t y, fixed_t z, int if (l->args[0]==id) { - vec3_t v1, v2, cross; + FVector3 v1, v2, cross; secplane_t *srcplane = (which == 0) ? &sec->floorplane : &sec->ceilingplane; fixed_t srcheight = (which == 0) ? sec->floortexz : sec->ceilingtexz; @@ -1444,15 +1443,19 @@ void P_VavoomSlope(sector_t * sec, int id, fixed_t x, fixed_t y, fixed_t z, int v2[1] = FIXED2FLOAT (y - l->v1->y); v2[2] = FIXED2FLOAT (z - srcheight); - CrossProduct (v1, v2, cross); - VectorNormalize (cross); + cross = v1 ^ v2; + double len = cross.Length(); + if (len == 0) + { + Printf ("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16)); + return; + } + cross /= len; // Fix backward normals - if ((cross[2] < 0 && which == 0) || (cross[2] > 0 && which == 1)) + if ((cross.Z < 0 && which == 0) || (cross.Z > 0 && which == 1)) { - cross[0] = -cross[0]; - cross[1] = -cross[1]; - cross[2] = -cross[2]; + cross = -cross; } @@ -2322,14 +2325,7 @@ static void P_AlignPlane (sector_t *sec, line_t *line, int which) refsec = line->frontsector == sec ? line->backsector : line->frontsector; - vec3_t p, v1, v2, cross; - - p[0] = FIXED2FLOAT (line->v1->x); - p[1] = FIXED2FLOAT (line->v1->y); - v1[0] = FIXED2FLOAT (line->dx); - v1[1] = FIXED2FLOAT (line->dy); - v2[0] = FIXED2FLOAT (refvert->x - line->v1->x); - v2[1] = FIXED2FLOAT (refvert->y - line->v1->y); + FVector3 p, v1, v2, cross; const secplane_t *refplane; secplane_t *srcplane; @@ -2340,19 +2336,22 @@ static void P_AlignPlane (sector_t *sec, line_t *line, int which) srcheight = (which == 0) ? sec->floortexz : sec->ceilingtexz; destheight = (which == 0) ? refsec->floortexz : refsec->ceilingtexz; + p[0] = FIXED2FLOAT (line->v1->x); + p[1] = FIXED2FLOAT (line->v1->y); p[2] = FIXED2FLOAT (destheight); + v1[0] = FIXED2FLOAT (line->dx); + v1[1] = FIXED2FLOAT (line->dy); v1[2] = 0; + v2[0] = FIXED2FLOAT (refvert->x - line->v1->x); + v2[1] = FIXED2FLOAT (refvert->y - line->v1->y); v2[2] = FIXED2FLOAT (srcheight - destheight); - CrossProduct (v1, v2, cross); - VectorNormalize (cross); + cross = (v1 ^ v2).Unit(); // Fix backward normals - if ((cross[2] < 0 && which == 0) || (cross[2] > 0 && which == 1)) + if ((cross.Z < 0 && which == 0) || (cross.Z > 0 && which == 1)) { - cross[0] = -cross[0]; - cross[1] = -cross[1]; - cross[2] = -cross[2]; + cross = -cross; } srcplane->a = FLOAT2FIXED (cross[0]); diff --git a/src/p_things.cpp b/src/p_things.cpp index d08b72f27..5469ac026 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -259,12 +259,7 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_na if (targ != NULL) { fixed_t spot[3] = { targ->x, targ->y, targ->z+targ->height/2 }; - vec3_t aim = - { - float(spot[0] - mobj->x), - float(spot[1] - mobj->y), - float(spot[2] - mobj->z) - }; + FVector3 aim(float(spot[0] - mobj->x), float(spot[1] - mobj->y), float(spot[2] - mobj->z)); if (leadTarget && speed > 0 && (targ->momx | targ->momy | targ->momz)) { @@ -275,55 +270,35 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_na // with the math. I don't think I would have thought of using // trig alone had I been left to solve it by myself. - double tvel[3] = { double(targ->momx), double(targ->momy), double(targ->momz) }; + FVector3 tvel(targ->momx, targ->momy, targ->momz); if (!(targ->flags & MF_NOGRAVITY) && targ->waterlevel < 3) { // If the target is subject to gravity and not underwater, // assume that it isn't moving vertically. Thanks to gravity, // even if we did consider the vertical component of the target's // velocity, we would still miss more often than not. - tvel[2] = 0.0; + tvel.Z = 0.0; if ((targ->momx | targ->momy) == 0) { goto nolead; } } - double dist = sqrt (aim[0]*aim[0] + aim[1]*aim[1] + aim[2]*aim[2]); - double targspeed = sqrt (tvel[0]*tvel[0] + tvel[1]*tvel[1] + tvel[2]*tvel[2]); - double ydotx = -aim[0]*tvel[0] - aim[1]*tvel[1] - aim[2]*tvel[2]; + double dist = aim | aim; + double targspeed = tvel.Length(); + double ydotx = -aim | tvel; double a = acos (clamp (ydotx / targspeed / dist, -1.0, 1.0)); double multiplier = double(pr_leadtarget.Random2())*0.1/255+1.1; double sinb = clamp (targspeed*multiplier * sin(a) / fspeed, -1.0, 1.0); - double cosb = cos (asin (sinb)); // Use the cross product of two of the triangle's sides to get a // rotation vector. - double rv[3] = - { - tvel[1]*aim[2] - tvel[2]*aim[1], - tvel[2]*aim[0] - tvel[0]*aim[2], - tvel[0]*aim[1] - tvel[1]*aim[0] - }; + FVector3 rv(tvel ^ aim); // The vector must be normalized. - double irvlen = 1.0 / sqrt(rv[0]*rv[0] + rv[1]*rv[1] + rv[2]*rv[2]); - rv[0] *= irvlen; - rv[1] *= irvlen; - rv[2] *= irvlen; + rv.MakeUnit(); // Now combine the rotation vector with angle b to get a rotation matrix. - double t = 1.0 - cosb; - double rm[3][3] = - { - {t*rv[0]*rv[0]+cosb, t*rv[0]*rv[1]-sinb*rv[2], t*rv[0]*rv[2]+sinb*rv[1]}, - {t*rv[0]*rv[1]+sinb*rv[2], t*rv[1]*rv[1]+cosb, t*rv[1]*rv[2]-sinb*rv[0]}, - {t*rv[0]*rv[2]-sinb*rv[1], t*rv[1]*rv[2]+sinb*rv[0], t*rv[2]*rv[2]+cosb} - }; + FMatrix3x3 rm(rv, cos(asin(sinb)), sinb); // And multiply the original aim vector with the matrix to get a // new aim vector that leads the target. - double aimvec[3] = - { - rm[0][0]*aim[0] + rm[1][0]*aim[1] + rm[2][0]*aim[2], - rm[0][1]*aim[0] + rm[1][1]*aim[1] + rm[2][1]*aim[2], - rm[0][2]*aim[0] + rm[1][2]*aim[1] + rm[2][2]*aim[2] - }; + FVector3 aimvec = rm * aim; // And make the projectile follow that vector at the desired speed. double aimscale = fspeed / dist; mobj->momx = fixed_t (aimvec[0] * aimscale); @@ -335,10 +310,10 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_na { nolead: mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y); - VectorNormalize (aim); - mobj->momx = fixed_t(aim[0] * fspeed); - mobj->momy = fixed_t(aim[1] * fspeed); - mobj->momz = fixed_t(aim[2] * fspeed); + aim.Resize (fspeed); + mobj->momx = fixed_t(aim[0]); + mobj->momy = fixed_t(aim[1]); + mobj->momz = fixed_t(aim[2]); } if (mobj->flags2 & MF2_SEEKERMISSILE) { diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 8f850b365..20e4fa025 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -121,7 +121,7 @@ short spanend[MAXHEIGHT]; BYTE *tiltlighting[MAXWIDTH]; int planeshade; -vec3_t plane_sz, plane_su, plane_sv; +FVector3 plane_sz, plane_su, plane_sv; float planelightfloat; bool plane_shade; fixed_t pviewx, pviewy; @@ -1446,7 +1446,7 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool masked) float xscale, yscale; fixed_t ixscale, iyscale; angle_t ang; - vec3_t p, m, n; + FVector3 p, m, n; fixed_t zeroheight; if (alpha <= 0) @@ -1503,21 +1503,21 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool masked) viewx + MulScale16 (ixscale, finesine[ang]), viewy + MulScale16 (ixscale, finecosine[ang])) - zeroheight); - CrossProduct (p, m, plane_su); - CrossProduct (p, n, plane_sv); - CrossProduct (m, n, plane_sz); + plane_su = p ^ m; + plane_sv = p ^ n; + plane_sz = m ^ n; - plane_su[2] *= FocalLengthXfloat; - plane_sv[2] *= FocalLengthXfloat; - plane_sz[2] *= FocalLengthXfloat; + plane_su.Z *= FocalLengthXfloat; + plane_sv.Z *= FocalLengthXfloat; + plane_sz.Z *= FocalLengthXfloat; - plane_su[1] *= iyaspectmulfloat; - plane_sv[1] *= iyaspectmulfloat; - plane_sz[1] *= iyaspectmulfloat; + plane_su.Y *= iyaspectmulfloat; + plane_sv.Y *= iyaspectmulfloat; + plane_sz.Y *= iyaspectmulfloat; // Premultiply the texture vectors with the scale factors - VectorScale2 (plane_su, 4294967296.f); - VectorScale2 (plane_sv, 4294967296.f); + plane_su *= 4294967296.f; + plane_sv *= 4294967296.f; if (MirrorFlags & RF_XFLIP) { diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index de0b43611..daac9a0e4 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -1,250 +1,250 @@ -/* -** i_main.cpp -** System-specific startup code. Eventually calls D_DoomMain. -** -**--------------------------------------------------------------------------- -** Copyright 1998-2007 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -// HEADER FILES ------------------------------------------------------------ - -#include -#include -#include -#include -#include -#include -#include - -#include "doomerrors.h" -#include "m_argv.h" -#include "d_main.h" -#include "i_system.h" -#include "i_video.h" -#include "c_console.h" -#include "errors.h" -#include "version.h" -#include "w_wad.h" - -// MACROS ------------------------------------------------------------------ - -// The maximum number of functions that can be registered with atterm. -#define MAX_TERMS 32 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*)); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -bool GtkAvailable; - -// The command line arguments. -DArgs Args; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static void (*TermFuncs[MAX_TERMS]) (); -static const char *TermNames[MAX_TERMS]; -static int NumTerms; - -// CODE -------------------------------------------------------------------- - -void addterm (void (*func) (), const char *name) -{ - // Make sure this function wasn't already registered. - for (int i = 0; i < NumTerms; ++i) - { - if (TermFuncs[i] == func) - { - return; - } - } - if (NumTerms == MAX_TERMS) - { - func (); - I_FatalError ( - "Too many exit functions registered.\n" - "Increase MAX_TERMS in i_main.cpp"); - } - TermNames[NumTerms] = name; - TermFuncs[NumTerms++] = func; -} - -void popterm () -{ - if (NumTerms) - NumTerms--; -} - -void STACK_ARGS call_terms () -{ - while (NumTerms > 0) - { -// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]); - TermFuncs[--NumTerms] (); - } -} - -static void STACK_ARGS NewFailure () -{ - I_FatalError ("Failed to allocate memory from system heap"); -} - -static int DoomSpecificInfo (char *buffer, char *end) -{ - const char *arg; - int size = end-buffer; - int i, p; - - SDL_Quit(); - - p = 0; - p += snprintf (buffer+p, size-p, "ZDoom version " DOTVERSIONSTR " (" __DATE__ ")\n"); - p += snprintf (buffer+p, size-p, "\nCommand line:"); - for (i = 0; i < Args.NumArgs(); ++i) - { - p += snprintf (buffer+p, size-p, " %s", Args.GetArg(i)); - } - p += snprintf (buffer+p, size-p, "\n"); - - for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i) - { - p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg); - } - - if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) - { - p += snprintf (buffer+p, size-p, "\n\nNot in a level."); - } - else - { - char name[9]; - - strncpy (name, level.mapname, 8); - name[8] = 0; - p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name); - - if (!viewactive) - { - buffer += snprintf (buffer+p, size-p, "\n\nView not active."); - } - else - { - p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx); - p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy); - p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz); - p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle); - } - } - buffer[p++] = '\n'; - buffer[p++] = '\0'; - - return p; -} - -int main (int argc, char **argv) -{ - printf("ZDoom v%s - SVN revision %s - SDL version\nCompiled on %s\n\n", - DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__); - - { - int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS }; - cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo); - } - - seteuid (getuid ()); - std::set_new_handler (NewFailure); - - GtkAvailable = gtk_init_check (&argc, &argv); - - if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) == -1) - { - fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError()); - return -1; - } - atterm (SDL_Quit); - - SDL_WM_SetCaption (GAMESIG " " DOTVERSIONSTR " (" __DATE__ ")", NULL); - - try - { - Args.SetArgs (argc, argv); - - /* - killough 1/98: - - This fixes some problems with exit handling - during abnormal situations. - - The old code called I_Quit() to end program, - while now I_Quit() is installed as an exit - handler and exit() is called to exit, either - normally or abnormally. Seg faults are caught - and the error handler is used, to prevent - being left in graphics mode or having very - loud SFX noise because the sound card is - left in an unstable state. - */ - - atexit (call_terms); - atterm (I_Quit); - - if (realpath (argv[0], progdir) == NULL) - strcpy (progdir, argv[0]); - char *slash = strrchr (progdir, '/'); - if (slash) - *(slash + 1) = '\0'; - else - progdir[0] = '.', progdir[1] = '/', progdir[2] = '\0'; - - C_InitConsole (80*8, 25*8, false); - D_DoomMain (); - } - catch (class CDoomError &error) - { - if (error.GetMessage ()) - fprintf (stderr, "%s\n", error.GetMessage ()); - exit (-1); - } - catch (...) - { - call_terms (); - throw; - } - return 0; +/* +** i_main.cpp +** System-specific startup code. Eventually calls D_DoomMain. +** +**--------------------------------------------------------------------------- +** Copyright 1998-2007 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +// HEADER FILES ------------------------------------------------------------ + +#include +#include +#include +#include +#include +#include +#include + +#include "doomerrors.h" +#include "m_argv.h" +#include "d_main.h" +#include "i_system.h" +#include "i_video.h" +#include "c_console.h" +#include "errors.h" +#include "version.h" +#include "w_wad.h" + +// MACROS ------------------------------------------------------------------ + +// The maximum number of functions that can be registered with atterm. +#define MAX_TERMS 32 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*)); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +bool GtkAvailable; + +// The command line arguments. +DArgs Args; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static void (*TermFuncs[MAX_TERMS]) (); +static const char *TermNames[MAX_TERMS]; +static int NumTerms; + +// CODE -------------------------------------------------------------------- + +void addterm (void (*func) (), const char *name) +{ + // Make sure this function wasn't already registered. + for (int i = 0; i < NumTerms; ++i) + { + if (TermFuncs[i] == func) + { + return; + } + } + if (NumTerms == MAX_TERMS) + { + func (); + I_FatalError ( + "Too many exit functions registered.\n" + "Increase MAX_TERMS in i_main.cpp"); + } + TermNames[NumTerms] = name; + TermFuncs[NumTerms++] = func; +} + +void popterm () +{ + if (NumTerms) + NumTerms--; +} + +void STACK_ARGS call_terms () +{ + while (NumTerms > 0) + { +// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]); + TermFuncs[--NumTerms] (); + } +} + +static void STACK_ARGS NewFailure () +{ + I_FatalError ("Failed to allocate memory from system heap"); +} + +static int DoomSpecificInfo (char *buffer, char *end) +{ + const char *arg; + int size = end-buffer; + int i, p; + + SDL_Quit(); + + p = 0; + p += snprintf (buffer+p, size-p, "ZDoom version " DOTVERSIONSTR " (" __DATE__ ")\n"); + p += snprintf (buffer+p, size-p, "\nCommand line:"); + for (i = 0; i < Args.NumArgs(); ++i) + { + p += snprintf (buffer+p, size-p, " %s", Args.GetArg(i)); + } + p += snprintf (buffer+p, size-p, "\n"); + + for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i) + { + p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg); + } + + if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) + { + p += snprintf (buffer+p, size-p, "\n\nNot in a level."); + } + else + { + char name[9]; + + strncpy (name, level.mapname, 8); + name[8] = 0; + p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name); + + if (!viewactive) + { + buffer += snprintf (buffer+p, size-p, "\n\nView not active."); + } + else + { + p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx); + p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy); + p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz); + p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle); + } + } + buffer[p++] = '\n'; + buffer[p++] = '\0'; + + return p; +} + +int main (int argc, char **argv) +{ + printf("ZDoom v%s - SVN revision %s - SDL version\nCompiled on %s\n\n", + DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__); + + { + int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS }; + cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo); + } + + seteuid (getuid ()); + std::set_new_handler (NewFailure); + + GtkAvailable = gtk_init_check (&argc, &argv); + + if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) == -1) + { + fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError()); + return -1; + } + atterm (SDL_Quit); + + SDL_WM_SetCaption (GAMESIG " " DOTVERSIONSTR " (" __DATE__ ")", NULL); + + try + { + Args.SetArgs (argc, argv); + + /* + killough 1/98: + + This fixes some problems with exit handling + during abnormal situations. + + The old code called I_Quit() to end program, + while now I_Quit() is installed as an exit + handler and exit() is called to exit, either + normally or abnormally. Seg faults are caught + and the error handler is used, to prevent + being left in graphics mode or having very + loud SFX noise because the sound card is + left in an unstable state. + */ + + atexit (call_terms); + atterm (I_Quit); + + if (realpath (argv[0], progdir) == NULL) + strcpy (progdir, argv[0]); + char *slash = strrchr (progdir, '/'); + if (slash) + *(slash + 1) = '\0'; + else + progdir[0] = '.', progdir[1] = '/', progdir[2] = '\0'; + + C_InitConsole (80*8, 25*8, false); + D_DoomMain (); + } + catch (class CDoomError &error) + { + if (error.GetMessage ()) + fprintf (stderr, "%s\n", error.GetMessage ()); + exit (-1); + } + catch (...) + { + call_terms (); + throw; + } + return 0; } diff --git a/src/tarray.h b/src/tarray.h index 45d96ca2b..3037cf78d 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -122,9 +122,9 @@ public: item = Array[--Count]; Array[Count].~T(); return true; - } - return false; - } + } + return false; + } void Delete (unsigned int index) { if (index < Count) diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index c4e9650ca..bb86b3c29 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -736,9 +736,9 @@ void A_CustomMissile(AActor * self) // Use the actual momentum instead of the missile's Speed property // so that this can handle missiles with a high vertical velocity // component properly. - vec3_t velocity = { missile->momx, missile->momy, 0 }; + FVector3 velocity (missile->momx, missile->momy, 0); - fixed_t missilespeed=(fixed_t)VectorLength(velocity); + fixed_t missilespeed = (fixed_t)velocity.Length(); missile->angle += Angle; ang = missile->angle >> ANGLETOFINESHIFT; @@ -1044,8 +1044,8 @@ void A_FireCustomMissile (AActor * self) { // This original implementation is to aim straight ahead and then offset // the angle from the resulting direction. - vec3_t velocity = { misl->momx, misl->momy, 0 }; - fixed_t missilespeed=(fixed_t)VectorLength(velocity); + FVector3 velocity(misl->momx, misl->momy, 0); + fixed_t missilespeed = (fixed_t)velocity.Length(); misl->angle += Angle; angle_t an = misl->angle >> ANGLETOFINESHIFT; misl->momx = FixedMul (missilespeed, finecosine[an]); diff --git a/src/vectors.cpp b/src/vectors.cpp deleted file mode 100644 index 455b97538..000000000 --- a/src/vectors.cpp +++ /dev/null @@ -1,253 +0,0 @@ -#include "vectors.h" -#include "actor.h" -#include "tables.h" - -#define DEG2RAD( a ) ( a * M_PI ) / 180.0F - - -// [RH] Convert a thing's position into a vec3_t -void VectorPosition (const AActor *thing, vec3_t out) -{ - out[0] = (float)thing->x / 65536.0f; - out[1] = (float)thing->y / 65536.0f; - out[2] = (float)thing->z / 65536.0f; -} - -void FixedAngleToVector (angle_t an, int pitch, vec3_t v) -{ - an >>= ANGLETOFINESHIFT; - v[0] = ((float)finecosine[an]) / 65536.0f; - v[1] = ((float)finesine[an]) / 65536.0f; - v[2] = ((float)finetangent[FINEANGLES/4-(pitch>>ANGLETOFINESHIFT)]) / 65536.0f; - VectorNormalize (v); -} - -// Taken from Q2 -vec_t VectorLength (const vec3_t v) -{ - float length; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrtf (length); - - return length; -} - -void VectorMA (const vec3_t a, float scale, const vec3_t b, vec3_t out) -{ - out[0] = a[0] + scale * b[0]; - out[1] = a[1] + scale * b[1]; - out[2] = a[2] + scale * b[2]; -} - -void VectorScale (const vec3_t v, float scale, vec3_t out) -{ - out[0] = v[0] * scale; - out[1] = v[1] * scale; - out[2] = v[2] * scale; -} - -void VectorScale2 (vec3_t v, float scale) -{ - v[0] = v[0] * scale; - v[1] = v[1] * scale; - v[2] = v[2] * scale; -} - -int VectorCompare (const vec3_t v1, const vec3_t v2) -{ - if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) - return 0; - - return 1; -} - -vec_t VectorNormalize (vec3_t v) -{ - double length, ilength; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrt (length); - - if (length) - { - ilength = 1/length; - v[0] = vec_t(v[0] * ilength); - v[1] = vec_t(v[1] * ilength); - v[2] = vec_t(v[2] * ilength); - } - - return vec_t(length); - -} - -vec_t VectorNormalize2 (const vec3_t v, vec3_t out) -{ - double length, ilength; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrt (length); - - if (length) - { - ilength = 1/length; - out[0] = vec_t(v[0] * ilength); - out[1] = vec_t(v[1] * ilength); - out[2] = vec_t(v[2] * ilength); - } - - return vec_t(length); - -} - -void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross) -{ - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -#ifdef _MSC_VER -#pragma optimize( "", off ) -#endif - -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) -{ - float m[3][3]; - float im[3][3]; - float zrot[3][3]; - float tmpmat[3][3]; - float rot[3][3]; - int i; - vec3_t vr, vup, vf; - - vf[0] = dir[0]; - vf[1] = dir[1]; - vf[2] = dir[2]; - - PerpendicularVector( vr, dir ); - CrossProduct( vr, vf, vup ); - - m[0][0] = vr[0]; - m[1][0] = vr[1]; - m[2][0] = vr[2]; - - m[0][1] = vup[0]; - m[1][1] = vup[1]; - m[2][1] = vup[2]; - - m[0][2] = vf[0]; - m[1][2] = vf[1]; - m[2][2] = vf[2]; - - memcpy( im, m, sizeof( im ) ); - - im[0][1] = m[1][0]; - im[0][2] = m[2][0]; - im[1][0] = m[0][1]; - im[1][2] = m[2][1]; - im[2][0] = m[0][2]; - im[2][1] = m[1][2]; - - memset( zrot, 0, sizeof( zrot ) ); - zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; - - zrot[0][0] = (float)cos( DEG2RAD( degrees ) ); - zrot[0][1] = (float)sin( DEG2RAD( degrees ) ); - zrot[1][0] = (float)-sin( DEG2RAD( degrees ) ); - zrot[1][1] = (float)cos( DEG2RAD( degrees ) ); - - R_ConcatRotations( m, zrot, tmpmat ); - R_ConcatRotations( tmpmat, im, rot ); - - for ( i = 0; i < 3; i++ ) - { - dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; - } -} - -#ifdef _MSC_VER -#pragma optimize( "", on ) -#endif - -void ProjectPointOnPlane (vec3_t dst, const vec3_t p, const vec3_t normal) -{ - float d; - vec3_t n; - float inv_denom; - - inv_denom = 1.0F / DotProduct( normal, normal ); - - d = DotProduct( normal, p ) * inv_denom; - - n[0] = normal[0] * inv_denom; - n[1] = normal[1] * inv_denom; - n[2] = normal[2] * inv_denom; - - dst[0] = p[0] - d * n[0]; - dst[1] = p[1] - d * n[1]; - dst[2] = p[2] - d * n[2]; -} - -/* -** assumes "src" is normalized -*/ -void PerpendicularVector (vec3_t dst, const vec3_t src) -{ - int pos; - int i; - float minelem = 1.0F; - vec3_t tempvec; - - /* - ** find the smallest magnitude axially aligned vector - */ - for ( pos = 0, i = 0; i < 3; i++ ) - { - if ( fabs( src[i] ) < minelem ) - { - pos = i; - minelem = (float)fabs( src[i] ); - } - } - tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; - tempvec[pos] = 1.0F; - - /* - ** project the point onto the plane defined by src - */ - ProjectPointOnPlane( dst, tempvec, src ); - - /* - ** normalize the result - */ - VectorNormalize( dst ); -} - -/* -================ -R_ConcatRotations -================ -*/ -void R_ConcatRotations (const float in1[3][3], const float in2[3][3], float out[3][3]) -{ - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; -} - diff --git a/src/vectors.h b/src/vectors.h index 168d23ca9..213afb505 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1,43 +1,1236 @@ -// Vector math routines which I took from Quake2's source since they -// make more sense than the way Doom does things. :-) +/* +** vectors.h +** Vector math routines. +** +**--------------------------------------------------------------------------- +** Copyright 2005-2007 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** Since C++ doesn't let me add completely new operators, the following two +** are overloaded for vectors: +** +** | dot product +** ^ cross product +*/ -#ifndef __VECTORS_H__ -#define __VECTORS_H__ +#ifndef VECTORS_H +#define VECTORS_H #include -#include "tables.h" +#include -typedef float vec_t; -typedef vec_t vec3_t[3]; +#ifndef PI +#define PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif -#define FIXED2FLOAT(f) ((float)(f) / (float)FRACUNIT) -#define FLOAT2FIXED(f) (fixed_t)((f) * (float)FRACUNIT) +#define EQUAL_EPSILON (1/65536.f) -#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) -#define VectorSubtract(a,b,c) (c[0]=a[0]-b[0],c[1]=a[1]-b[1],c[2]=a[2]-b[2]) -#define VectorAdd(a,b,c) (c[0]=a[0]+b[0],c[1]=a[1]+b[1],c[2]=a[2]+b[2]) -#define VectorCopy(a,b) (b[0]=a[0],b[1]=a[1],b[2]=a[2]) -#define VectorClear(a) (a[0]=a[1]=a[2]=0) -#define VectorNegate(a,b) (b[0]=-a[0],b[1]=-a[1],b[2]=-a[2]) -#define VectorSet(v, x, y, z) (v[0]=(x), v[1]=(y), v[2]=(z)) -#define VectorFixedSet(v,x,y,z) (v[0]=FIXED2FLOAT(x), v[1]=FIXED2FLOAT(y), v[2]=FIXED2FLOAT(z)) -#define VectorInverse(v) (v[0]=-v[0],v[1]=-v[1],v[2]=-v[2]) -class AActor; +#define DEG2RAD(d) ((d)*PI/180.f) +#define RAD2DEG(r) ((r)*180.f/PI) -void VectorPosition (const class AActor *thing, vec3_t out); -void FixedAngleToVector (angle_t an, fixed_t pitch, vec3_t v); -vec_t VectorLength (const vec3_t v); -void VectorMA (const vec3_t a, float scale, const vec3_t b, vec3_t out); -void VectorScale (const vec3_t v, float scale, vec3_t out); -void VectorScale2 (vec3_t v, float scale); -int VectorCompare (const vec3_t v1, const vec3_t v2); -vec_t VectorNormalize (vec3_t v); -vec_t VectorNormalize2 (const vec3_t v, vec3_t out); -void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross); -void ProjectPointOnPlane (vec3_t dst, const vec3_t p, const vec3_t normal); -void PerpendicularVector (vec3_t dst, const vec3_t src); -void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); -void R_ConcatRotations (const float in1[3][3], const float in2[3][3], float out[3][3]); +template struct TVector3; +template struct TRotator; +template struct TAngle; -#endif //__VECTORS_H__ +template +struct TVector2 +{ + vec_t X, Y; + + TVector2 () + { + } + + TVector2 (double a, double b) + : X(a), Y(b) + { + } + + TVector2 (const TVector2 &other) + : X(other.X), Y(other.Y) + { + } + + TVector2 (const TVector3 &other) // Copy the X and Y from the 3D vector and discard the Z + : X(other.X), Y(other.Y) + { + } + + void Zero() + { + Y = X = 0; + } + + TVector2 &operator= (const TVector2 &other) + { + // This might seem backwards, but this helps produce smaller code when a newly + // created vector is assigned, because the components can just be popped off + // the FPU stack in order without the need for fxch. For platforms with a + // more sensible registered-based FPU, of course, the order doesn't matter. + // (And, yes, I know fxch can improve performance in the right circumstances, + // but this isn't one of those times. Here, it's little more than a no-op that + // makes the exe 2 bytes larger whenever you assign one vector to another.) + Y = other.Y, X = other.X; + return *this; + } + + // Access X and Y as an array + vec_t &operator[] (int index) + { + return *(&X + index); + } + + const vec_t &operator[] (int index) const + { + return *(&X + index); + } + + // Test for equality + bool operator== (const TVector2 &other) const + { + return X == other.X && Y == other.Y; + } + + // Test for inequality + bool operator!= (const TVector2 &other) const + { + return X != other.X || Y != other.Y; + } + + // Test for approximate equality + bool ApproximatelyEquals (const TVector2 &other) const + { + return fabs(X - other.X) < EQUAL_EPSILON && fabs(Y - other.Y) < EQUAL_EPSILON; + } + + // Test for approximate inequality + bool DoesNotApproximatelyEqual (const TVector2 &other) const + { + return fabs(X - other.X) >= EQUAL_EPSILON || fabs(Y - other.Y) >= EQUAL_EPSILON; + } + + // Unary negation + TVector2 operator- () const + { + return TVector2(-X, -Y); + } + + // Scalar addition + TVector2 &operator+= (double scalar) + { + X += scalar, Y += scalar; + return *this; + } + + friend TVector2 operator+ (const TVector2 &v, double scalar) + { + return TVector2(v.X + scalar, v.Y + scalar); + } + + friend TVector2 operator+ (double scalar, const TVector2 &v) + { + return TVector2(v.X + scalar, v.Y + scalar); + } + + // Scalar subtraction + TVector2 &operator-= (double scalar) + { + X -= scalar, Y -= scalar; + return *this; + } + + TVector2 operator- (double scalar) const + { + return TVector2(X - scalar, Y - scalar); + } + + // Scalar multiplication + TVector2 &operator*= (double scalar) + { + X *= scalar, Y *= scalar; + return *this; + } + + friend TVector2 operator* (const TVector2 &v, double scalar) + { + return TVector2(v.X * scalar, v.Y * scalar); + } + + friend TVector2 operator* (double scalar, const TVector2 &v) + { + return TVector2(v.X * scalar, v.Y * scalar); + } + + // Scalar division + TVector2 &operator/= (double scalar) + { + scalar = 1 / scalar, X *= scalar, Y *= scalar; + return *this; + } + + TVector2 operator/ (double scalar) const + { + scalar = 1 / scalar; + return TVector2(X * scalar, Y * scalar); + } + + // Vector addition + TVector2 &operator+= (const TVector2 &other) + { + X += other.X, Y += other.Y; + return *this; + } + + TVector2 operator+ (const TVector2 &other) const + { + return TVector2(X + other.X, Y + other.Y); + } + + // Vector subtraction + TVector2 &operator-= (const TVector2 &other) + { + X -= other.X, Y -= other.Y; + return *this; + } + + TVector2 operator- (const TVector2 &other) const + { + return TVector2(X - other.X, Y - other.Y); + } + + // Vector length + double Length() const + { + return sqrt (X*X + Y*Y); + } + + double LengthSquared() const + { + return X*X + Y*Y; + } + + // Return a unit vector facing the same direction as this one + TVector2 Unit() const + { + double len = Length(); + if (len != 0) len = 1 / len; + return *this * len; + } + + // Scales this vector into a unit vector + void MakeUnit() + { + double len = Length(); + if (len != 0) len = 1 / len; + *this *= len; + } + + // Dot product + double operator | (const TVector2 &other) const + { + return X*other.X + Y*other.Y; + } + + // Returns the angle (in radians) that the ray (0,0)-(X,Y) faces + double Angle() const + { + return atan2 (X, Y); + } + + // Returns a rotated vector. TAngle is in radians. + TVector2 Rotated (double angle) + { + double cosval = cos (angle); + double sinval = sin (angle); + return TVector2(X*cosval - Y*sinval, Y*cosval + X*sinval); + } + + // Returns a vector rotated 90 degrees clockwise. + TVector2 Rotated90CW() + { + return TVector2(Y, -X); + } + + // Returns a vector rotated 90 degrees counterclockwise. + TVector2 Rotated90CCW() + { + return TVector2(-Y, X); + } +}; + +template +struct TVector3 +{ + typedef TVector2 Vector2; + + vec_t X, Y, Z; + + TVector3 () + { + } + + TVector3 (double a, double b, double c) + : X(vec_t(a)), Y(vec_t(b)), Z(vec_t(c)) + { + } + + TVector3 (const TVector3 &other) + : X(other.X), Y(other.Y), Z(other.Z) + { + } + + TVector3 (const Vector2 &xy, double z) + : X(xy.X), Y(xy.Y), Z(z) + { + } + + TVector3 (const TRotator &rot); + + void Zero() + { + Z = Y = X = 0; + } + + TVector3 &operator= (const TVector3 &other) + { + Z = other.Z, Y = other.Y, X = other.X; + return *this; + } + + // Access X and Y and Z as an array + vec_t &operator[] (int index) + { + return *(&X + index); + } + + const vec_t &operator[] (int index) const + { + return *(&X + index); + } + + // Test for equality + bool operator== (const TVector3 &other) const + { + return X == other.X && Y == other.Y && Z == other.Z; + } + + // Test for inequality + bool operator!= (const TVector3 &other) const + { + return X != other.X || Y != other.Y || Z != other.Z; + } + + // Test for approximate equality + bool ApproximatelyEquals (const TVector3 &other) const + { + return fabs(X - other.X) < EQUAL_EPSILON && fabs(Y - other.Y) < EQUAL_EPSILON && fabs(Z - other.Z) < EQUAL_EPSILON; + } + + // Test for approximate inequality + bool DoesNotApproximatelyEqual (const TVector3 &other) const + { + return fabs(X - other.X) >= EQUAL_EPSILON || fabs(Y - other.Y) >= EQUAL_EPSILON || fabs(Z - other.Z) >= EQUAL_EPSILON; + } + + // Unary negation + TVector3 operator- () const + { + return TVector3(-X, -Y, -Z); + } + + // Scalar addition + TVector3 &operator+= (double scalar) + { + X += scalar, Y += scalar, Z += scalar; + return *this; + } + + friend TVector3 operator+ (const TVector3 &v, double scalar) + { + return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); + } + + friend TVector3 operator+ (double scalar, const TVector3 &v) + { + return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); + } + + // Scalar subtraction + TVector3 &operator-= (double scalar) + { + X -= scalar, Y -= scalar, Z -= scalar; + return *this; + } + + TVector3 operator- (double scalar) const + { + return TVector3(X - scalar, Y - scalar, Z - scalar); + } + + // Scalar multiplication + TVector3 &operator*= (double scalar) + { + X = vec_t(X *scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); + return *this; + } + + friend TVector3 operator* (const TVector3 &v, double scalar) + { + return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); + } + + friend TVector3 operator* (double scalar, const TVector3 &v) + { + return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); + } + + // Scalar division + TVector3 &operator/= (double scalar) + { + scalar = 1 / scalar, X = vec_t(X * scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); + return *this; + } + + TVector3 operator/ (double scalar) const + { + scalar = 1 / scalar; + return TVector3(X * scalar, Y * scalar, Z * scalar); + } + + // Vector addition + TVector3 &operator+= (const TVector3 &other) + { + X += other.X, Y += other.Y, Z += other.Z; + return *this; + } + + TVector3 operator+ (const TVector3 &other) const + { + return TVector3(X + other.X, Y + other.Y, Z + other.Z); + } + + // Vector subtraction + TVector3 &operator-= (const TVector3 &other) + { + X -= other.X, Y -= other.Y, Z - other.Z; + return *this; + } + + TVector3 operator- (const TVector3 &other) const + { + return TVector3(X - other.X, Y - other.Y, Z - other.Z); + } + + // Add a 2D vector to this 3D vector, leaving Z unchanged. + TVector3 &operator+= (const Vector2 &other) + { + X += other.X, Y += other.Y; + return *this; + } + + // Subtract a 2D vector from this 3D vector, leaving Z unchanged. + TVector3 &operator-= (const Vector2 &other) + { + X -= other.X, Y -= other.Y; + return *this; + } + + // Add a 3D vector and a 2D vector. + // Discards the Z component of the 3D vector and returns a 2D vector. + friend Vector2 operator+ (const TVector3 &v3, const Vector2 &v2) + { + return Vector2(v3.X + v2.X, v3.Y + v2.Y); + } + + friend Vector2 operator+ (const Vector2 &v2, const TVector3 &v3) + { + return Vector2(v2.X + v3.X, v2.Y + v3.Y); + } + + // Subtract a 3D vector and a 2D vector. + // Discards the Z component of the 3D vector and returns a 2D vector. + friend Vector2 operator- (const TVector3 &v3, const Vector2 &v2) + { + return Vector2(v3.X - v2.X, v3.Y - v2.Y); + } + + friend Vector2 operator- (const TVector2 &v2, const TVector3 &v3) + { + return Vector2(v2.X - v3.X, v2.Y - v3.Y); + } + + // Vector length + double Length() const + { + return sqrt (X*X + Y*Y + Z*Z); + } + + double LengthSquared() const + { + return X*X + Y*Y + Z*Z; + } + + // Return a unit vector facing the same direction as this one + TVector3 Unit() const + { + double len = Length(); + if (len != 0) len = 1 / len; + return *this * len; + } + + // Scales this vector into a unit vector + void MakeUnit() + { + double len = Length(); + if (len != 0) len = 1 / len; + *this *= len; + } + + // Resizes this vector to be the specified length (if it is not 0) + TVector3 &Resize(double len) + { + double nowlen = Length(); + X = vec_t(X * (len /= nowlen)); + Y = vec_t(Y * len); + Z = vec_t(Z * len); + return *this; + } + + // Dot product + double operator | (const TVector3 &other) const + { + return X*other.X + Y*other.Y + Z*other.Z; + } + + // Cross product + TVector3 operator ^ (const TVector3 &other) const + { + return TVector3(Y*other.Z - Z*other.Y, + Z*other.X - X*other.Z, + X*other.Y - Y*other.X); + } + + TVector3 &operator ^= (const TVector3 &other) + { + *this = *this ^ other; + } +}; + +template +struct TMatrix3x3 +{ + typedef TVector3 Vector3; + + vec_t Cells[3][3]; + + TMatrix3x3() + { + } + + TMatrix3x3(const TMatrix3x3 &other) + { + (*this)[0] = other[0]; + (*this)[1] = other[1]; + (*this)[2] = other[2]; + } + + TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3) + { + (*this)[0] = row1; + (*this)[1] = row2; + (*this)[2] = row3; + } + + // Construct a rotation matrix about an arbitrary axis. + // (The axis vector must be normalized.) + TMatrix3x3(const Vector3 &axis, double radians) + { + double c = cos(radians), s = sin(radians), t = 1 - c; +/* In comments: A more readable version of the matrix setup. +This was found in Diana Gruber's article "The Mathematics of the +3D Rotation Matrix" at and is +attributed to Graphics Gems (Glassner, Academic Press, 1990). + + Cells[0][0] = t*axis.X*axis.X + c; + Cells[0][1] = t*axis.X*axis.Y - s*axis.Z; + Cells[0][2] = t*axis.X*axis.Z + s*axis.Y; + + Cells[1][0] = t*axis.Y*axis.X + s*axis.Z; + Cells[1][1] = t*axis.Y*axis.Y + c; + Cells[1][2] = t*axis.Y*axis.Z - s*axis.X; + + Cells[2][0] = t*axis.Z*axis.X - s*axis.Y; + Cells[2][1] = t*axis.Z*axis.Y + s*axis.X; + Cells[2][2] = t*axis.Z*axis.Z + c; + +Outside comments: A faster version with only 10 (not 24) multiplies. +*/ + double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; + double tx, ty, txx, tyy, u, v; + + tx = t*axis.X; + Cells[0][0] = vec_t( (txx=tx*axis.X) + c ); + Cells[0][1] = vec_t( (u=tx*axis.Y) - sz); + Cells[0][2] = vec_t( (v=tx*axis.Z) + sy); + + ty = t*axis.Y; + Cells[1][0] = vec_t( u + sz); + Cells[1][1] = vec_t( (tyy=ty*axis.Y) + c ); + Cells[1][2] = vec_t( (u=ty*axis.Z) - sx); + + Cells[2][0] = vec_t( v - sy); + Cells[2][1] = vec_t( u + sx); + Cells[2][2] = vec_t( (t-txx-tyy) + c ); + } + + TMatrix3x3(const Vector3 &axis, double c/*cosine*/, double s/*sine*/) + { + double t = 1 - c; + double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; + double tx, ty, txx, tyy, u, v; + + tx = t*axis.X; + Cells[0][0] = vec_t( (txx=tx*axis.X) + c ); + Cells[0][1] = vec_t( (u=tx*axis.Y) - sz); + Cells[0][2] = vec_t( (v=tx*axis.Z) + sy); + + ty = t*axis.Y; + Cells[1][0] = vec_t( u + sz); + Cells[1][1] = vec_t( (tyy=ty*axis.Y) + c ); + Cells[1][2] = vec_t( (u=ty*axis.Z) - sx); + + Cells[2][0] = vec_t( v - sy); + Cells[2][1] = vec_t( u + sx); + Cells[2][2] = vec_t( (t-txx-tyy) + c ); + } + + TMatrix3x3(const Vector3 &axis, TAngle degrees); + + void Zero() + { + memset (this, 0, sizeof *this); + } + + void Identity() + { + Cells[0][0] = 1; Cells[0][1] = 0; Cells[0][2] = 0; + Cells[1][0] = 0; Cells[1][1] = 1; Cells[1][2] = 0; + Cells[2][0] = 0; Cells[2][1] = 0; Cells[2][2] = 1; + } + + Vector3 &operator[] (int index) + { + return *((Vector3 *)&Cells[index]); + } + + const Vector3 &operator[] (int index) const + { + return *((Vector3 *)&Cells[index]); + } + + // Multiply a scalar + TMatrix3x3 &operator*= (double scalar) + { + (*this)[0] *= scalar; + (*this)[1] *= scalar; + (*this)[2] *= scalar; + return *this; + } + + friend TMatrix3x3 operator* (double s, const TMatrix3x3 &m) + { + return TMatrix3x3(m[0]*s, m[1]*s, m[2]*s); + } + + TMatrix3x3 operator* (double s) const + { + return TMatrix3x3((*this)[0]*s, (*this)[1]*s, (*this)[2]*s); + } + + // Divide a scalar + TMatrix3x3 &operator/= (double scalar) + { + return *this *= 1 / scalar; + } + + TMatrix3x3 operator/ (double s) const + { + return *this * (1 / s); + } + + // Add two 3x3 matrices together + TMatrix3x3 &operator+= (const TMatrix3x3 &o) + { + (*this)[0] += o[0]; + (*this)[1] += o[1]; + (*this)[2] += o[2]; + return *this; + } + + TMatrix3x3 operator+ (const TMatrix3x3 &o) const + { + return TMatrix3x3((*this)[0] + o[0], (*this)[1] + o[1], (*this)[2] + o[2]); + } + + // Subtract two 3x3 matrices + TMatrix3x3 &operator-= (const TMatrix3x3 &o) + { + (*this)[0] -= o[0]; + (*this)[1] -= o[1]; + (*this)[2] -= o[2]; + return *this; + } + + TMatrix3x3 operator- (const TMatrix3x3 &o) const + { + return TMatrix3x3((*this)[0] - o[0], (*this)[1] - o[1], (*this)[2] - o[2]); + } + + // Concatenate two 3x3 matrices + TMatrix3x3 &operator*= (const TMatrix3x3 &o) + { + return *this = *this * o; + } + + TMatrix3x3 operator* (const TMatrix3x3 &o) const + { + return TMatrix3x3( + Vector3(Cells[0][0]*o[0][0] + Cells[0][1]*o[1][0] + Cells[0][2]*o[2][0], + Cells[0][0]*o[0][1] + Cells[0][1]*o[1][1] + Cells[0][2]*o[2][1], + Cells[0][0]*o[0][2] + Cells[0][1]*o[1][2] + Cells[0][2]*o[2][2]), + Vector3(Cells[1][0]*o[0][0] + Cells[1][1]*o[1][0] + Cells[1][2]*o[2][0], + Cells[1][0]*o[0][1] + Cells[1][1]*o[1][1] + Cells[1][2]*o[2][1], + Cells[1][0]*o[0][2] + Cells[1][1]*o[1][2] + Cells[1][2]*o[2][2]), + Vector3(Cells[2][0]*o[0][0] + Cells[2][1]*o[1][0] + Cells[2][2]*o[2][0], + Cells[2][0]*o[0][1] + Cells[2][1]*o[1][1] + Cells[2][2]*o[2][1], + Cells[2][0]*o[0][2] + Cells[2][1]*o[1][2] + Cells[2][2]*o[2][2])); + } + + // Multiply a 3D vector by a rotation matrix + friend Vector3 operator* (const Vector3 &v, const TMatrix3x3 &m) + { + return Vector3(m[0] | v, m[1] | v, m[2] | v); + } + + friend Vector3 operator* (const TMatrix3x3 &m, const Vector3 &v) + { + return Vector3(m[0] | v, m[1] | v, m[2] | v); + } +}; + +template +struct TAngle +{ + vec_t Degrees; + + TAngle () + { + } + + TAngle (float amt) + : Degrees(amt) + { + } + + TAngle (double amt) + : Degrees(vec_t(amt)) + { + } + + TAngle (int amt) + : Degrees(vec_t(amt)) + { + } + + TAngle (const TAngle &other) + : Degrees(other.Degrees) + { + } + + TAngle &operator= (const TAngle &other) + { + Degrees = other.Degrees; + return *this; + } + + TAngle &operator= (double other) + { + Degrees = other; + return *this; + } + + operator float() const { return Degrees; } + operator double() const { return Degrees; } + + TAngle operator- () const + { + return TAngle(-Degrees); + } + + TAngle &operator+= (TAngle other) + { + Degrees += other.Degrees; + return *this; + } + + TAngle &operator-= (TAngle other) + { + Degrees -= other.Degrees; + return *this; + } + + TAngle &operator*= (TAngle other) + { + Degrees *= other.Degrees; + return *this; + } + + TAngle &operator/= (TAngle other) + { + Degrees /= other.Degrees; + return *this; + } + + TAngle operator+ (TAngle other) const + { + return Degrees + other.Degrees; + } + + TAngle operator- (TAngle other) const + { + return Degrees - other.Degrees; + } + + TAngle operator* (TAngle other) const + { + return Degrees * other.Degrees; + } + + TAngle operator/ (TAngle other) const + { + return Degrees / other.Degrees; + } + + TAngle &operator+= (double other) + { + Degrees = vec_t(Degrees + other); + return *this; + } + + TAngle &operator-= (double other) + { + Degrees = vec_t(Degrees - other); + return *this; + } + + TAngle &operator*= (double other) + { + Degrees = vec_t(Degrees * other); + return *this; + } + + TAngle &operator/= (double other) + { + Degrees = vec_t(Degrees / other); + return *this; + } + + TAngle operator+ (double other) const + { + return Degrees + other; + } + + TAngle operator- (double other) const + { + return Degrees - other; + } + + friend TAngle operator- (double o1, TAngle o2) + { + return TAngle(o1 - o2.Degrees); + } + + TAngle operator* (double other) const + { + return Degrees * vec_t(other); + } + + TAngle operator/ (double other) const + { + return Degrees / vec_t(other); + } + + // Should the comparisons consider an epsilon value? + bool operator< (TAngle other) const + { + return Degrees < other.Degrees; + } + + bool operator> (TAngle other) const + { + return Degrees > other.Degrees; + } + + bool operator<= (TAngle other) const + { + return Degrees <= other.Degrees; + } + + bool operator>= (TAngle other) const + { + return Degrees >= other.Degrees; + } + + bool operator== (TAngle other) const + { + return Degrees == other.Degrees; + } + + bool operator!= (TAngle other) const + { + return Degrees != other.Degrees; + } + + bool operator< (double other) const + { + return Degrees < other; + } + + bool operator> (double other) const + { + return Degrees > other; + } + + bool operator<= (double other) const + { + return Degrees <= other; + } + + bool operator>= (double other) const + { + return Degrees >= other; + } + + bool operator== (double other) const + { + return Degrees == other; + } + + bool operator!= (double other) const + { + return Degrees != other; + } + + // Ensure the angle is between [0.0,360.0) degrees + TAngle &Normalize360() + { + // Normalizing the angle converts it to a BAM, masks it, and converts it back to a float. + + // This could have been kept entirely in floating point using fmod(), but the MSVCRT has lots + // of overhead for that function, despite the x87 offering the FPREM instruction which does + // exactly what fmod() is supposed to do. So fmod ends up being an order of magnitude slower + // than casting to and from an int. + + // Casting Degrees to a volatile ensures that the compiler will not try to evaluate an expression + // such as "TAngle a(360*100+24); a.Normalize360();" at compile time. Normally, it would see that + // this expression is constant and attempt to remove the Normalize360() call entirely and store + // the result of the function in the TAngle directly. Unfortunately, it does not do the casting + // properly and will overflow, producing an incorrect result. So we need to make sure it always + // evaluates Normalize360 at run time and never at compile time. (This applies to VC++. I don't + // know if other compilers suffer similarly). + Degrees = vec_t((int(*(volatile vec_t *)&Degrees * ((1<<30)/360.0)) & ((1<<30)-1)) * (360.f/(1<<30))); + return *this; + } + + // Ensures the angle is between (-180.0,180.0] degrees + TAngle &Normalize180() + { + Degrees = vec_t((((int(*(volatile vec_t *)&Degrees * ((1<<30)/360.0))+(1<<29)-1) & ((1<<30)-1)) - (1<<29)+1) * (360.f/(1<<30))); + return *this; + } + + // Like Normalize360(), except the integer value is not converted back to a float. + // The steps parameter must be a power of 2. + int Quantize(int steps) + { + return int(*(volatile vec_t *)&Degrees * (steps/360.0)) & (steps-1); + } +}; + +template +inline double ToRadians (const TAngle °) +{ + return double(deg.Degrees * (PI / 180.0)); +} + +template +inline TAngle ToDegrees (double rad) +{ + return TAngle (double(rad * (180.0 / PI))); +} + +template +inline double cos (const TAngle °) +{ + return cos(ToRadians(deg)); +} + +template +inline double sin (const TAngle °) +{ + return sin(ToRadians(deg)); +} + +template +inline double tan (const TAngle °) +{ + return tan(ToRadians(deg)); +} + +template +inline TAngle fabs (const TAngle °) +{ + return TAngle(fabs(deg.Degrees)); +} + +template +inline TAngle vectoyaw (const TVector2 &vec) +{ + return atan2(vec.Y, vec.X) * (180.0 / PI); +} + +template +inline TAngle vectoyaw (const TVector3 &vec) +{ + return atan2(vec.Y, vec.X) * (180.0 / PI); +} + +// Much of this is copied from TVector3. Is all that functionality really appropriate? +template +struct TRotator +{ + typedef TAngle Angle; + + Angle Pitch; // up/down + Angle Yaw; // left/right + Angle Roll; // rotation about the forward axis + + TRotator () + { + } + + TRotator (const Angle &p, const Angle &y, const Angle &r) + : Pitch(p), Yaw(y), Roll(r) + { + } + + TRotator (const TRotator &other) + : Pitch(other.Pitch), Yaw(other.Yaw), Roll(other.Roll) + { + } + + TRotator &operator= (const TRotator &other) + { + Roll = other.Roll, Yaw = other.Yaw, Pitch = other.Pitch; + return *this; + } + + // Access angles as an array + Angle &operator[] (int index) + { + return *(&Pitch + index); + } + + const Angle &operator[] (int index) const + { + return *(&Pitch + index); + } + + // Test for equality + bool operator== (const TRotator &other) const + { + return fabs(Pitch - other.Pitch) < Angle(EQUAL_EPSILON) && fabs(Yaw - other.Yaw) < Angle(EQUAL_EPSILON) && fabs(Roll - other.Roll) < Angle(EQUAL_EPSILON); + } + + // Test for inequality + bool operator!= (const TRotator &other) const + { + return fabs(Pitch - other.Pitch) >= Angle(EQUAL_EPSILON) && fabs(Yaw - other.Yaw) >= Angle(EQUAL_EPSILON) && fabs(Roll - other.Roll) >= Angle(EQUAL_EPSILON); + } + + // Unary negation + TRotator operator- () const + { + return TRotator(-Pitch, -Yaw, -Roll); + } + + // Scalar addition + TRotator &operator+= (const Angle &scalar) + { + Pitch += scalar, Yaw += scalar, Roll += scalar; + return *this; + } + + friend TRotator operator+ (const TRotator &v, const Angle &scalar) + { + return TRotator(v.Pitch + scalar, v.Yaw + scalar, v.Roll + scalar); + } + + friend TRotator operator+ (const Angle &scalar, const TRotator &v) + { + return TRotator(v.Pitch + scalar, v.Yaw + scalar, v.Roll + scalar); + } + + // Scalar subtraction + TRotator &operator-= (const Angle &scalar) + { + Pitch -= scalar, Yaw -= scalar, Roll -= scalar; + return *this; + } + + TRotator operator- (const Angle &scalar) const + { + return TRotator(Pitch - scalar, Yaw - scalar, Roll - scalar); + } + + // Scalar multiplication + TRotator &operator*= (const Angle &scalar) + { + Pitch *= scalar, Yaw *= scalar, Roll *= scalar; + return *this; + } + + friend TRotator operator* (const TRotator &v, const Angle &scalar) + { + return TRotator(v.Pitch * scalar, v.Yaw * scalar, v.Roll * scalar); + } + + friend TRotator operator* (const Angle &scalar, const TRotator &v) + { + return TRotator(v.Pitch * scalar, v.Yaw * scalar, v.Roll * scalar); + } + + // Scalar division + TRotator &operator/= (const Angle &scalar) + { + Angle mul(1 / scalar.Degrees); + Pitch *= scalar, Yaw *= scalar, Roll *= scalar; + return *this; + } + + TRotator operator/ (const Angle &scalar) const + { + Angle mul(1 / scalar.Degrees); + return TRotator(Pitch * mul, Yaw * mul, Roll * mul); + } + + // Vector addition + TRotator &operator+= (const TRotator &other) + { + Pitch += other.Pitch, Yaw += other.Yaw, Roll += other.Roll; + return *this; + } + + TRotator operator+ (const TRotator &other) const + { + return TRotator(Pitch + other.Pitch, Yaw + other.Yaw, Roll + other.Roll); + } + + // Vector subtraction + TRotator &operator-= (const TRotator &other) + { + Pitch -= other.Pitch, Yaw -= other.Yaw, Roll - other.Roll; + return *this; + } + + TRotator operator- (const TRotator &other) const + { + return TRotator(Pitch - other.Pitch, Yaw - other.Yaw, Roll - other.Roll); + } + + // Normalize each component + TRotator &Normalize180 () + { + for (int i = -3; i; ++i) + { + (*this)[i+3].Normalize180(); + } + return *this; + } + + TRotator &Normalize360 () + { + for (int i = -3; i; ++i) + { + (*this)[i+3].Normalize360(); + } + return *this; + } +}; + +// Create a forward vector from a rotation (ignoring roll) + +template +inline TVector3::TVector3 (const TRotator &rot) +: X(cos(rot.Pitch)*cos(rot.Yaw)), Y(cos(rot.Pitch)*sin(rot.Yaw)), Z(-sin(rot.Pitch)) +{ +} + +template +inline TMatrix3x3::TMatrix3x3(const TVector3 &axis, TAngle degrees) +{ + double c = cos(degrees), s = sin(degrees), t = 1 - c; + double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; + double tx, ty, txx, tyy, u, v; + + tx = t*axis.X; + Cells[0][0] = T( (txx=tx*axis.X) + c ); + Cells[0][1] = T( (u=tx*axis.Y) - sz ); + Cells[0][2] = T( (v=tx*axis.Z) + sy ); + + ty = t*axis.Y; + Cells[1][0] = T( u + sz ); + Cells[1][1] = T( (tyy=ty*axis.Y) + c ); + Cells[1][2] = T( (u=ty*axis.Z) - sx ); + + Cells[2][0] = T( v - sy ); + Cells[2][1] = T( u + sx ); + Cells[2][2] = T( (t-txx-tyy) + c ); +} + + +typedef TVector2 FVector2; +typedef TVector3 FVector3; +typedef TRotator FRotator; +typedef TMatrix3x3 FMatrix3x3; +typedef TAngle FAngle; + +#define FLOAT2FIXED(f) fixed_t((f) * float(65536)) +#define FIXED2FLOAT(f) (float(f) / float(65536)) + +#endif diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index ee56b8f28..ad9916e9d 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -683,7 +683,7 @@ void ShowErrorPane(const char *text) { SetWindowLong (ErrorIcon, GWL_ID, IDC_ICONPIC); } - ErrorPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, NULL); + ErrorPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL); CHARRANGE end; CHARFORMAT2 oldformat, newformat; diff --git a/zdoom.vcproj b/zdoom.vcproj index 33df6a8d3..4c2984919 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -2717,14 +2725,6 @@ GeneratePreprocessedFile="0" /> - - - @@ -2747,7 +2747,7 @@ /> - - - @@ -4186,26 +4178,6 @@ AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /> - - - - - - - - @@ -4214,14 +4186,6 @@ AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /> - - - @@ -4243,7 +4207,7 @@ /> - - - @@ -4814,6 +4768,16 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -4838,16 +4802,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -4858,6 +4812,16 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -4882,16 +4846,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4902,6 +4856,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4926,16 +4890,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4946,6 +4900,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4970,16 +4934,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4990,6 +4944,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -5069,7 +5033,7 @@ /> + + + @@ -5408,14 +5380,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - - - - @@ -5650,6 +5606,14 @@ GeneratePreprocessedFile="0" /> + + + @@ -5671,7 +5635,7 @@ /> + + + @@ -9152,14 +9124,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -9334,7 +9298,7 @@ />