/* * R_SetupFrustum */ void R_SetupFrustum( const refdef_t *rd, float farClip, cplane_t *frustum ) { int i; vec3_t forward, left, up; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip VectorCopy( &rd->viewaxis[AXIS_FORWARD], forward ); VectorCopy( &rd->viewaxis[AXIS_RIGHT], left ); VectorCopy( &rd->viewaxis[AXIS_UP], up ); if( rd->rdflags & RDF_USEORTHO ) { VectorNegate( left, frustum[0].normal ); VectorCopy( left, frustum[1].normal ); VectorNegate( up, frustum[2].normal ); VectorCopy( up, frustum[3].normal ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } frustum[0].dist -= rd->ortho_x; frustum[1].dist -= rd->ortho_x; frustum[2].dist -= rd->ortho_y; frustum[3].dist -= rd->ortho_y; } else { vec3_t right; VectorNegate( left, right ); // rotate rn.vpn right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, up, forward, -( 90-rd->fov_x / 2 ) ); // rotate rn.vpn left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, up, forward, 90-rd->fov_x / 2 ); // rotate rn.vpn up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, right, forward, 90-rd->fov_y / 2 ); // rotate rn.vpn down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, right, forward, -( 90 - rd->fov_y / 2 ) ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } } // farclip VectorNegate( forward, frustum[4].normal ); frustum[4].type = PLANE_NONAXIAL; frustum[4].dist = DotProduct( rd->vieworg, frustum[4].normal ) - farClip; frustum[4].signbits = SignbitsForPlane( &frustum[4] ); }
/* ============ TestAddPlane Adds the given plane to the brush description if all of the original brush vertexes can be put on the front side ============= */ void TestAddPlane (plane_t *plane) { int i, c; vec_t d; vec_t *corner; plane_t flip; vec3_t inv; int counts[3]; plane_t *pl; // see if the plane has allready been added for (i=0 ; i<numbrushfaces ; i++) { pl = &faces[i].plane; if (VectorCompare (plane->normal, pl->normal) && fabs(plane->dist - pl->dist) < ON_EPSILON) return; VectorNegate (plane->normal, inv); if (VectorCompare (inv, pl->normal) && fabs(plane->dist + pl->dist) < ON_EPSILON) return; } // check all the corner points counts[0] = counts[1] = counts[2] = 0; c = num_hull_points * 8; corner = hull_corners[0]; for (i=0 ; i<c ; i++, corner += 3) { d = DotProduct (corner, plane->normal) - plane->dist; if (d < -ON_EPSILON) { if (counts[0]) return; counts[1]++; } else if (d > ON_EPSILON) { if (counts[1]) return; counts[0]++; } else counts[2]++; } // the plane is a seperator if (counts[0]) { VectorNegate (plane->normal, flip.normal); flip.dist = -plane->dist; plane = &flip; } AddBrushPlane (plane); }
// Vic: changed this to qboolean bool CanonicalVector (vec3_t vec) { vec_t length; length = VectorLength (vec); // Vic: ignore degenerate edges if (length < 0.1) return false; length = (vec_t)1.0 / length; vec[0] *= length; vec[1] *= length; vec[2] *= length; if (vec[0] > pMath_EPSILON_EQUAL) return true; else if (vec[0] < -pMath_EPSILON_EQUAL) { VectorNegate (vec, vec); return true; } else vec[0] = 0; if (vec[1] > pMath_EPSILON_EQUAL) return true; else if (vec[1] < -pMath_EPSILON_EQUAL) { VectorNegate (vec, vec); return true; } else vec[1] = 0; if (vec[2] > pMath_EPSILON_EQUAL) return true; else if (vec[2] < -pMath_EPSILON_EQUAL) { VectorNegate (vec, vec); return true; } else vec[2] = 0; Error ("CanonicalVector: degenerate"); return false; }
/* * CG_ImpactSmokePuff */ void CG_ImpactSmokePuff( const vec3_t origin, const vec3_t dir, float radius, float alpha, int time, int speed ) { #define SMOKEPUFF_MAXVIEWDIST 700 lentity_t *le; struct shader_s *shader = CG_MediaShader( cgs.media.shaderSmokePuff ); vec3_t local_origin, local_dir; if( CG_PointContents( origin ) & MASK_WATER ) { return; } if( DistanceFast( origin, cg.view.origin ) * cg.view.fracDistFOV > SMOKEPUFF_MAXVIEWDIST ) return; if( !VectorLength( dir ) ) { VectorNegate( &cg.view.axis[AXIS_FORWARD], local_dir ); } else { VectorNormalize2( dir, local_dir ); } //offset the origin by half of the radius VectorMA( origin, radius*0.5f, local_dir, local_origin ); le = CG_AllocSprite( LE_SCALE_ALPHA_FADE, local_origin, radius + crandom(), time, 1, 1, 1, alpha, 0, 0, 0, 0, shader ); le->ent.rotation = rand() % 360; VectorScale( local_dir, speed, le->velocity ); }
/* =============== ChargeAttack =============== */ void ChargeAttack( gentity_t *ent, gentity_t *victim ) { gentity_t *tent; int damage; vec3_t forward, normal; if( level.time < victim->chargeRepeat ) return; victim->chargeRepeat = level.time + LEVEL4_CHARGE_REPEAT; VectorSubtract( victim->s.origin, ent->s.origin, forward ); VectorNormalize( forward ); VectorNegate( forward, normal ); if( victim->client ) { tent = G_TempEntity( victim->s.origin, EV_MISSILE_HIT ); tent->s.otherEntityNum = victim->s.number; tent->s.eventParm = DirToByte( normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( !victim->takedamage ) return; damage = (int)( ( (float)ent->client->ps.stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME ) * LEVEL4_CHARGE_DMG ); G_Damage( victim, ent, ent, forward, victim->s.origin, damage, 0, MOD_LEVEL4_CHARGE ); }
int CM_PlaneEqual( patchPlane_t *p, float plane[4], int *flipped ) { float invplane[4]; if ( fabs( p->plane[0] - plane[0] ) < NORMAL_EPSILON && fabs( p->plane[1] - plane[1] ) < NORMAL_EPSILON && fabs( p->plane[2] - plane[2] ) < NORMAL_EPSILON && fabs( p->plane[3] - plane[3] ) < DIST_EPSILON ) { *flipped = qfalse; return qtrue; } VectorNegate( plane, invplane ); invplane[3] = -plane[3]; if ( fabs( p->plane[0] - invplane[0] ) < NORMAL_EPSILON && fabs( p->plane[1] - invplane[1] ) < NORMAL_EPSILON && fabs( p->plane[2] - invplane[2] ) < NORMAL_EPSILON && fabs( p->plane[3] - invplane[3] ) < DIST_EPSILON ) { *flipped = qtrue; return qtrue; } return qfalse; }
/* ================ R_PlaneForMirror Get transformed mirrorplane and entity matrix ================ */ void R_PlaneForMirror( msurface_t *surf, mplane_t *out, matrix4x4 m ) { cl_entity_t *ent; ASSERT( out != NULL ); ent = RI.currententity; // setup mirror plane *out = *surf->plane; if( surf->flags & SURF_PLANEBACK ) { VectorNegate( out->normal, out->normal ); out->dist = -out->dist; } if( !VectorIsNull( ent->origin ) || !VectorIsNull( ent->angles )) { mplane_t tmp; if( !VectorIsNull( ent->angles )) Matrix4x4_CreateFromEntity( m, ent->angles, ent->origin, 1.0f ); else Matrix4x4_CreateFromEntity( m, vec3_origin, ent->origin, 1.0f ); tmp = *out; // transform mirror plane by entity matrix Matrix4x4_TransformPositivePlane( m, tmp.normal, tmp.dist, out->normal, &out->dist ); } else Matrix4x4_LoadIdentity( m ); }
/** * @param[in] tile Tile to check (normally 0 - except in assembled maps) * @param[in] start trace start vector * @param[in] end trace end vector * @param[in] mins box mins * @param[in] maxs box maxs * @param[in] headnode if < 0 we are in a leaf node * @param[in] contentmask content flags the trace should stop at (see MASK_*) * @param[in] brushrejects brushes the trace should ignore (see MASK_*) * @param[in] origin center for rotating objects * @param[in] angles current rotation status (in degrees) for rotating objects * @param[in] rmaShift how much the object was shifted by the RMA process (needed for doors) * @param[in] fraction The furthest distance needed to trace before we stop. * @brief Handles offseting and rotation of the end points for moving and rotating entities * @sa CM_BoxTrace */ trace_t CM_HintedTransformedBoxTrace (mapTile_t *tile, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const int headnode, const int contentmask, const int brushrejects, const vec3_t origin, const vec3_t angles, const vec3_t rmaShift, const float fraction) { trace_t trace; vec3_t start_l, end_l; vec3_t forward, right, up; vec3_t temp; bool rotated; /* subtract origin offset */ VectorSubtract(start, origin, start_l); VectorSubtract(end, origin, end_l); /* rotate start and end into the models frame of reference */ if (headnode != tile->box_headnode && VectorNotEmpty(angles)) { rotated = true; } else { rotated = false; } if (rotated) { AngleVectors(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); } /* When tracing through a model, we want to use the nodes, planes etc. as calculated by ufo2map. * But nodes and planes have been shifted in case of an RMA. At least for doors we need to undo the shift. */ if (VectorNotEmpty(origin)) { /* only doors seem to have their origin set */ VectorAdd(start_l, rmaShift, start_l); /* undo the shift */ VectorAdd(end_l, rmaShift, end_l); } /* sweep the box through the model */ trace = TR_BoxTrace(tile, start_l, end_l, mins, maxs, headnode, contentmask, brushrejects, fraction); trace.mapTile = tile->idx; if (rotated && trace.fraction != 1.0) { vec3_t a; /** @todo figure out how to do this with existing angles */ VectorNegate(angles, a); AngleVectors(a, forward, right, 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); } VectorInterpolation(start, end, trace.fraction, trace.endpos); return trace; }
/* * @brief */ static void BuildPatch(int32_t fn, winding_t *w) { patch_t *patch; d_bsp_plane_t *plane; patch = (patch_t *) Mem_Malloc(sizeof(*patch)); face_patches[fn] = patch; patch->face = &d_bsp.faces[fn]; patch->winding = w; // resolve the normal plane = &d_bsp.planes[patch->face->plane_num]; if (patch->face->side) VectorNegate(plane->normal, patch->normal); else VectorCopy(plane->normal, patch->normal); WindingCenter(w, patch->origin); // nudge the origin out along the normal VectorMA(patch->origin, 2.0, patch->normal, patch->origin); patch->area = WindingArea(w); if (patch->area < 1.0) // clamp area patch->area = 1.0; EmissiveLight(patch); // surface light }
/** * @brief Build a patch for a surface that emits light * @note This is called in the lighting stage * @param fn The face number of the surface that emits the light * @param w The winding * @sa BuildLights */ static void BuildPatch (int fn, winding_t* w) { patch_t* patch; dBspPlane_t* plane; patch = Mem_AllocType(patch_t); face_patches[fn] = patch; patch->face = &curTile->faces[fn]; patch->winding = w; /* resolve the normal */ plane = &curTile->planes[patch->face->planenum]; if (patch->face->side) VectorNegate(plane->normal, patch->normal); else VectorCopy(plane->normal, patch->normal); WindingCenter(w, patch->origin); /* nudge the origin out along the normal */ VectorMA(patch->origin, 2.0, patch->normal, patch->origin); patch->area = WindingArea(w); if (patch->area < 1.0) /* clamp area */ patch->area = 1.0; EmissiveLight(patch); /* surface light */ }
//=========================================================================== // returns the ground face the given point is above in the given area // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== aas_face_t *AAS_AreaGroundFace(int areanum, vec3_t point) { int i, facenum; vec3_t up = {0, 0, 1}; vec3_t normal; aas_area_t *area; aas_face_t *face; if (!aasworld.loaded) return NULL; area = &aasworld.areas[areanum]; for (i = 0; i < area->numfaces; i++) { facenum = aasworld.faceindex[area->firstface + i]; face = &aasworld.faces[abs(facenum)]; //if this is a ground face if (face->faceflags & FACE_GROUND) { //get the up or down normal if (aasworld.planes[face->planenum].normal[2] < 0) VectorNegate(up, normal); else VectorCopy(up, normal); //check if the point is in the face if (AAS_InsideFace(face, normal, point, 0.01f)) return face; } //end if } //end for return NULL; } //end of the function AAS_AreaGroundFace
bool BotAvoidObstacles( gentity_t *self, vec3_t dir ) { gentity_t *blocker; blocker = BotGetPathBlocker( self, dir ); if ( blocker ) { if ( BotShouldJump( self, blocker, dir ) ) { BotJump( self ); return false; } else if ( !BotFindSteerTarget( self, dir ) ) { vec3_t angles; vec3_t right; vectoangles( dir, angles ); AngleVectors( angles, dir, right, nullptr ); if ( ( self->client->time10000 % 2000 ) < 1000 ) { VectorCopy( right, dir ); } else { VectorNegate( right, dir ); } dir[ 2 ] = 0; VectorNormalize( dir ); } return true; } return false; }
/* ================= R_TraceAgainstSurface ================= */ static bool R_TraceAgainstSurface( msurface_t *surf ) { int i; mesh_t *mesh; elem_t *elem; vec4_t *verts; float old_frac = trace_fraction; if( !surf ) return false; mesh = surf->mesh; if( !mesh ) return false; elem = mesh->elems; if( !elem ) return false; verts = mesh->xyzArray; if( !verts ) return false; // clip each triangle individually for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) { R_TraceAgainstTriangle( verts[elem[0]], verts[elem[1]], verts[elem[2]] ); if( old_frac > trace_fraction ) { // flip normal is we are on the backside (does it really happen?)... if( surf->facetype == MST_PLANAR ) { if( DotProduct( trace_plane.normal, surf->plane->normal ) < 0 ) VectorNegate( trace_plane.normal, trace_plane.normal ); } return true; } } return false; }
/* * Handles offseting and rotation of the end points for moving and * rotating entities */ trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int headnode, int brushmask, vec3_t origin, vec3_t angles) { trace_t trace; vec3_t start_l, end_l; vec3_t a; vec3_t forward, right, up; vec3_t temp; qboolean rotated; /* subtract origin offset */ VectorSubtract (start, origin, start_l); VectorSubtract (end, origin, end_l); /* rotate start and end into the models frame of reference */ if (headnode != box_headnode && (angles[0] || angles[1] || angles[2]) ) rotated = true; else rotated = false; if (rotated) { AngleVectors (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); } /* sweep the box through the model */ trace = CM_BoxTrace (start_l, end_l, mins, maxs, headnode, brushmask); if (rotated && trace.fraction != 1.0) { VectorNegate (angles, a); AngleVectors (a, forward, right, 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); } trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]); trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]); trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]); return trace; }
/* * CG_CartoonHitEffect */ void CG_CartoonHitEffect( const vec3_t origin, const vec3_t dir, int damage ) { lentity_t *le; int time = 6; float radius = 11.0f, alpha = cg_bloodTrailAlpha->value; struct shader_s *shader = CG_MediaShader( cgs.media.shaderCartoonHit ); struct shader_s *shader2 = CG_MediaShader( cgs.media.shaderCartoonHit2 ); struct shader_s *shader3 = CG_MediaShader( cgs.media.shaderCartoonHit3 ); vec3_t local_origin, local_dir; if( !cg_cartoonHitEffect->integer ) return; if ( damage < 39 ) return; if( !VectorLength( dir ) ) { VectorNegate( &cg.view.axis[AXIS_FORWARD], local_dir ); } else { VectorNormalize2( dir, local_dir ); } // Move effect a bit up from player VectorCopy( origin, local_origin ); local_origin[2] += 65; // small buff if ( damage < 64 ) { if( damage < 50 ) { // SPLITZOW! radius = 7.0f; le = CG_AllocSprite( LE_SCALE_ALPHA_FADE, local_origin, radius, time, 1, 1, 1, alpha, 0, 0, 0, 0, shader2 ); } else { // POW! radius = 9.0f; le = CG_AllocSprite( LE_SCALE_ALPHA_FADE, local_origin, radius, time, 1, 1, 1, alpha, 0, 0, 0, 0, shader ); } } else // big buff { // OUCH! le = CG_AllocSprite( LE_SCALE_ALPHA_FADE, local_origin, radius, time, 1, 1, 1, alpha, 0, 0, 0, 0, shader3 ); } // randomize dir VectorSet( le->velocity, -local_dir[0] * 5 + crandom()*5, -local_dir[1] * 5 + crandom()*5, -local_dir[2] * 5 + crandom()*5 + 3); VectorMA( local_dir, 1, le->velocity, le->velocity ); }
/* =============== WideBloodSpurt Calculates the position of a blood spurt for wide traces and generates an event =============== */ static void WideBloodSpurt( gentity_t *attacker, gentity_t *victim, trace_t *tr ) { gentity_t *tent; vec3_t normal, origin; float mag, radius; if ( !attacker->client ) { return; } if ( victim->health <= 0 ) { return; } if ( tr ) { VectorSubtract( tr->endpos, victim->s.origin, normal ); } else { VectorSubtract( attacker->client->ps.origin, victim->s.origin, normal ); } // Normalize the horizontal components of the vector difference to the // "radius" of the bounding box mag = sqrt( normal[ 0 ] * normal[ 0 ] + normal[ 1 ] * normal[ 1 ] ); radius = victim->r.maxs[ 0 ] * 1.21f; if ( mag > radius ) { normal[ 0 ] = normal[ 0 ] / mag * radius; normal[ 1 ] = normal[ 1 ] / mag * radius; } // Clamp origin to be within bounding box vertically if ( normal[ 2 ] > victim->r.maxs[ 2 ] ) { normal[ 2 ] = victim->r.maxs[ 2 ]; } if ( normal[ 2 ] < victim->r.mins[ 2 ] ) { normal[ 2 ] = victim->r.mins[ 2 ]; } VectorAdd( victim->s.origin, normal, origin ); VectorNegate( normal, normal ); VectorNormalize( normal ); // Create the blood spurt effect entity tent = G_NewTempEntity( origin, EV_MISSILE_HIT ); tent->s.eventParm = DirToByte( normal ); tent->s.otherEntityNum = victim->s.number; tent->s.weapon = attacker->s.weapon; tent->s.generic1 = attacker->s.generic1; // weaponMode }
void FireCannon(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; float distance; int offset = (self->s.frame - 119) / 2; AngleVectors (self->s.angles, forward, right, NULL); G_ProjectSource (self->s.origin, cannonoffset[offset], forward, right, start); if(self->monsterinfo.aiflags & AI_ONESHOTTARGET) { VectorCopy( self->monsterinfo.shottarget, vec ); } else { VectorCopy (self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; } if(self->timeout) { if(self->seq) { VectorNegate(right, right); } VectorMA (vec, self->timeout, right, vec); } self->timeout -= 50; VectorSubtract (vec, start, dir); VectorNormalize (dir); VectorSubtract (self->enemy->s.origin, self->s.origin, vec); distance = VectorLength (vec); if(distance < 700) { distance = 700; } // ANIM_AIM(self, dir); if(skill->value < 2) { fire_plasmaCannon (self, start, dir, 90, 700, 2.5, 90+40, distance); } else if(skill->value < 3) { fire_plasmaCannon (self, start, dir, 90, (int)(distance * 1.2), 2.5, 90+40, distance); } else { fire_plasmaCannon (self, start, dir, 90, (int)(distance * 1.6), 2.5, 90+40, distance); } }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean AAS_GetPlane(vec3_t normal, vec_t dist, int *planenum) { aas_plane_t *plane, temp; //if (AAS_FindPlane(normal, dist, planenum)) return true; if (AAS_FindHashedPlane(normal, dist, planenum)) { return true; } if ((*aasworld).numplanes >= max_aas.max_planes - 1) { Error("AAS_MAX_PLANES = %d", max_aas.max_planes); } //end if #ifdef STOREPLANESDOUBLE plane = &(*aasworld).planes[(*aasworld).numplanes]; VectorCopy(normal, plane->normal); plane->dist = dist; plane->type = (plane + 1)->type = PlaneTypeForNormal(plane->normal); VectorCopy(normal, (plane + 1)->normal); VectorNegate((plane + 1)->normal, (plane + 1)->normal); (plane + 1)->dist = -dist; (*aasworld).numplanes += 2; //allways put axial planes facing positive first if (plane->type < 3) { if (plane->normal[0] < 0 || plane->normal[1] < 0 || plane->normal[2] < 0) { // flip order temp = *plane; *plane = *(plane + 1); *(plane + 1) = temp; *planenum = (*aasworld).numplanes - 1; return false; } //end if } //end if *planenum = (*aasworld).numplanes - 2; //add the planes to the hash AAS_AddPlaneToHash((*aasworld).numplanes - 1); AAS_AddPlaneToHash((*aasworld).numplanes - 2); return false; #else plane = &(*aasworld).planes[(*aasworld).numplanes]; VectorCopy(normal, plane->normal); plane->dist = dist; plane->type = AAS_PlaneTypeForNormal(normal); *planenum = (*aasworld).numplanes; (*aasworld).numplanes++; //add the plane to the hash AAS_AddPlaneToHash((*aasworld).numplanes - 1); return false; #endif //STOREPLANESDOUBLE } //end of the function AAS_GetPlane
TEST(DSPSingle, TestVectorNegate) { float out[10]; VectorNegate(out, ramp, 10); for (unsigned i = 0; i < 10; ++i) { ASSERT_FLOAT_EQ(-ramp[i], out[i]); } }
/* ================ CalcFaceVectors Fills in texorg, worldtotex. and textoworld ================ */ static void CalcFaceVectors (lightinfo_t *l) { texinfo_t *tex; int i, j; vec3_t texnormal; float distscale; vec_t dist, len; tex = &texinfo[l->face->texinfo]; // convert from float to vec_t for (i = 0 ; i < 2 ; i++) { for (j = 0 ; j < 3 ; j++) l->worldtotex[i][j] = tex->vecs[i][j]; } // calculate a normal to the texture axis. points can be moved along this // without changing their S/T texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2] - tex->vecs[1][2]*tex->vecs[0][1]; texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0] - tex->vecs[1][0]*tex->vecs[0][2]; texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1] - tex->vecs[1][1]*tex->vecs[0][0]; VectorNormalize (texnormal); // flip it towards plane normal distscale = DotProduct (texnormal, l->facenormal); if (!distscale) COM_Error ("Texture axis perpendicular to face"); if (distscale < 0) { distscale = -distscale; VectorNegate (texnormal, texnormal); } // distscale is the ratio of the distance along the texture normal to // the distance along the plane normal distscale = 1/distscale; for (i = 0 ; i < 2 ; i++) { len = VectorLength (l->worldtotex[i]); dist = DotProduct (l->worldtotex[i], l->facenormal); dist *= distscale; VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]); VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]); } // calculate texorg on the texture plane for (i = 0 ; i < 3 ; i++) l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i]; // project back to the face plane dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1; dist *= distscale; VectorMA (l->texorg, -dist, texnormal, l->texorg); }
/* =============== R_SetupFrustumOrtho =============== */ static void R_SetupFrustumOrtho( void ) { ref_overview_t *ov = &clgame.overView; float orgOffset; int i; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip // 5 - nearclip // setup the near and far planes. orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward ); VectorNegate( RI.cull_vforward, RI.frustum[4].normal ); RI.frustum[4].dist = -ov->zFar - orgOffset; VectorCopy( RI.cull_vforward, RI.frustum[5].normal ); RI.frustum[5].dist = ov->zNear + orgOffset; // left and right planes... orgOffset = DotProduct( RI.cullorigin, RI.cull_vright ); VectorCopy( RI.cull_vright, RI.frustum[0].normal ); RI.frustum[0].dist = ov->xLeft + orgOffset; VectorNegate( RI.cull_vright, RI.frustum[1].normal ); RI.frustum[1].dist = -ov->xRight - orgOffset; // top and buttom planes... orgOffset = DotProduct( RI.cullorigin, RI.cull_vup ); VectorCopy( RI.cull_vup, RI.frustum[3].normal ); RI.frustum[3].dist = ov->xTop + orgOffset; VectorNegate( RI.cull_vup, RI.frustum[2].normal ); RI.frustum[2].dist = -ov->xBottom - orgOffset; for( i = 0; i < 6; i++ ) { RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); } }
bool FConvexVolume::IntersectSphere(const FVector& Origin,const float& Radius, bool& bOutFullyContained) const { bool Result = true; //Assume fully contained bOutFullyContained = true; checkSlow(PermutedPlanes.Num() % 4 == 0); // Load the origin & radius VectorRegister Orig = VectorLoadFloat3(&Origin); VectorRegister VRadius = VectorLoadFloat1(&Radius); VectorRegister NegativeVRadius = VectorNegate(VRadius); // Splat origin into 3 vectors VectorRegister OrigX = VectorReplicate(Orig, 0); VectorRegister OrigY = VectorReplicate(Orig, 1); VectorRegister OrigZ = VectorReplicate(Orig, 2); // Since we are moving straight through get a pointer to the data const FPlane* RESTRICT PermutedPlanePtr = (FPlane*)PermutedPlanes.GetData(); // Process four planes at a time until we have < 4 left for (int32 Count = 0; Count < PermutedPlanes.Num(); Count += 4) { // Load 4 planes that are already all Xs, Ys, ... VectorRegister PlanesX = VectorLoadAligned(PermutedPlanePtr); PermutedPlanePtr++; VectorRegister PlanesY = VectorLoadAligned(PermutedPlanePtr); PermutedPlanePtr++; VectorRegister PlanesZ = VectorLoadAligned(PermutedPlanePtr); PermutedPlanePtr++; VectorRegister PlanesW = VectorLoadAligned(PermutedPlanePtr); PermutedPlanePtr++; // Calculate the distance (x * x) + (y * y) + (z * z) - w VectorRegister DistX = VectorMultiply(OrigX,PlanesX); VectorRegister DistY = VectorMultiplyAdd(OrigY,PlanesY,DistX); VectorRegister DistZ = VectorMultiplyAdd(OrigZ,PlanesZ,DistY); VectorRegister Distance = VectorSubtract(DistZ,PlanesW); // Check for completely outside int32 Mask = VectorAnyGreaterThan(Distance,VRadius); if (Mask) { Result = false; bOutFullyContained = false; break; } //the sphere is definitely inside the frustums, but let's check if it's FULLY contained by checking the NEGATIVE radius (on the inside of each frustum plane) Mask = VectorAnyGreaterThan(Distance,NegativeVRadius); if (Mask) { bOutFullyContained = false; } } return Result; }
static int Vector_NegateOperator(lua_State *L) { vec_t *a; vec3_t b; a = Lua_GetVector(L, 1); VectorNegate(a, b); Lua_PushVector(L, b); return 1; }
/* ================= P_SlamDamage Serves same purpose as P_FallingDamage, but detects wall impacts ================= */ void P_SlamDamage (edict_t *ent) { float delta; int damage; vec3_t dir; vec3_t deltav; if (ent->s.modelindex != MAX_MODELS-1) return; // not in the player model if (ent->movetype == MOVETYPE_NOCLIP) return; deltav[0] = ent->velocity[0] - ent->client->oldvelocity[0]; deltav[1] = ent->velocity[1] - ent->client->oldvelocity[1]; deltav[2] = 0; delta = VectorLength(deltav); delta = delta*delta * 0.0001; // // never take damage if just release grapple or on grappleZOID if (level.time - ent->client->ctf_grapplereleasetime <= FRAMETIME * 2 || (ent->client->ctf_grapple && ent->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY)) return; //ZOID if (delta > 40*(player_max_speed->value/300)) // Knightmare changed { if (ent->health > 0) { /* if(delta > 65) ent->s.event = EV_FALLFAR; else ent->s.event = EV_FALL;*/ //play correct PPM sounds while in third person mode if (delta >= 65*(player_max_speed->value/300)) // Knightmare changed gi.sound(ent,CHAN_VOICE,gi.soundindex("*fall1.wav"),1.0,ATTN_NORM,0); else gi.sound(ent,CHAN_VOICE,gi.soundindex("*fall2.wav"),1.0,ATTN_NORM,0); } ent->pain_debounce_time = level.time; // no normal pain sound damage = (delta-40*(player_max_speed->value/300))/2; // Knightmare changed if (damage < 1) damage = 1; VectorCopy(deltav,dir); VectorNegate(dir,dir); VectorNormalize(dir); if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) ) T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); } }
/* =============== CG_DeathCamView =============== */ static void CG_DeathCamView(void) { vec3_t focusAngles; static vec3_t prevorigin, prevangles, diffangles, difforigin; static int prevclientframe; static float diff; trace_t trace; static vec3_t mins = { -4, -4, -4 }; static vec3_t maxs = { 4, 4, 4 }; vec3_t tracestart, moveback; float *origin; origin = cg.refdef.vieworg; VectorCopy(cg.snap->ps.grapplePoint, focusAngles); //VectorCopy(cg.refdefViewAngles, focusAngles); VectorAdd(origin, difforigin, origin); VectorCopy(origin, tracestart); VectorAdd(focusAngles, diffangles, focusAngles); //move back the camera to show player's body AngleVectors(focusAngles, moveback, NULL, NULL); VectorNegate(moveback, moveback); VectorMA(origin, 200, moveback, origin); origin[2]+=80; //trace to walls CG_Trace( &trace, tracestart, mins, maxs, origin, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0 ) { VectorCopy(trace.endpos, origin); origin[2] += (1.0 - trace.fraction) * 32; CG_Trace(&trace, tracestart, mins, maxs, origin, cg.predictedPlayerState.clientNum, MASK_SOLID); VectorCopy(trace.endpos, origin); } //try to smooth camera movement a bit if (prevclientframe==0 || focusAngles[YAW]!=prevangles[YAW] || focusAngles[PITCH]!=prevangles[PITCH]) { if (prevclientframe!=0) diff=cg.clientFrame-prevclientframe; diff=(diff==0)?1:diff; //avoid division by zero prevclientframe=cg.clientFrame; VectorCopy(origin, prevorigin); VectorCopy(focusAngles, prevangles); VectorClear(diffangles); VectorClear(difforigin); } else { diffangles[YAW]+=(focusAngles[YAW]-prevangles[YAW]) / diff; diffangles[PITCH]+=(focusAngles[PITCH]-prevangles[PITCH]) / diff; diffangles[ROLL]+=(focusAngles[ROLL]-prevangles[ROLL]) / diff; VectorSubtract(origin, prevorigin, difforigin); VectorScale(difforigin, 1/diff, difforigin); } VectorCopy(focusAngles,cg.refdefViewAngles); }
static void R_IQMSetUpTransform (int trivial_accept) { int i; float rotationmatrix[3][4]; static float viewmatrix[3][4]; vec3_t forward, left, up; VectorCopy (currententity->transform + 0, forward); VectorCopy (currententity->transform + 4, left); VectorCopy (currententity->transform + 8, up); // TODO: can do this with simple matrix rearrangement for (i = 0; i < 3; i++) { rotationmatrix[i][0] = forward[i]; rotationmatrix[i][1] = left[i]; rotationmatrix[i][2] = up[i]; } rotationmatrix[0][3] = -modelorg[0]; rotationmatrix[1][3] = -modelorg[1]; rotationmatrix[2][3] = -modelorg[2]; // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); VectorCopy (vup, viewmatrix[1]); VectorNegate (viewmatrix[1], viewmatrix[1]); VectorCopy (vpn, viewmatrix[2]); // viewmatrix[0][3] = 0; // viewmatrix[1][3] = 0; // viewmatrix[2][3] = 0; R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform // for the unclipped case (it would mess up clipping in the clipped case). // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y // correspondingly so the projected x and y come out right // FIXME: make this work for clipped case too? if (trivial_accept) { for (i = 0; i < 4; i++) { aliastransform[0][i] *= aliasxscale * (1.0 / ((float) 0x8000 * 0x10000)); aliastransform[1][i] *= aliasyscale * (1.0 / ((float) 0x8000 * 0x10000)); aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000); } } }
// negate static int _vec3_m_unm(lua_State *L) { luavec3_t a, b; _et_gentity_setluavec3(L, &a); lua_pop(L, 1); VectorNegate(a, b); _et_gentity_getluavec3(L, b); G_LuaSetVec3Class(L); return 1; }
static int vector_NegateOperator(lua_State * L) { vec_t *a; vec3_t b; a = lua_getvector(L, 1); VectorNegate(a, b); lua_pushvector(L, b); return 1; }
/* * CG_BloodDamageEffect */ void CG_BloodDamageEffect( const vec3_t origin, const vec3_t dir, int damage ) { lentity_t *le; int count, i; float radius = 5.0f, alpha = cg_bloodTrailAlpha->value; int time = 8; struct shader_s *shader = CG_MediaShader( cgs.media.shaderBloodImpactPuff ); vec3_t local_dir; if( !cg_showBloodTrail->integer ) return; if( !cg_bloodTrail->integer ) return; count = (int)( damage * 0.25f ); clamp( count, 1, 10 ); if( CG_PointContents( origin ) & MASK_WATER ) { shader = CG_MediaShader( cgs.media.shaderBloodTrailLiquidPuff ); radius += ( 1 + crandom() ); alpha = 0.5f * cg_bloodTrailAlpha->value; } if( !VectorLength( dir ) ) { VectorNegate( &cg.view.axis[AXIS_FORWARD], local_dir ); } else { VectorNormalize2( dir, local_dir ); } for( i = 0; i < count; i++ ) { le = CG_AllocSprite( LE_PUFF_SHRINK, origin, radius + crandom(), time, 1, 1, 1, alpha, 0, 0, 0, 0, shader ); le->ent.rotation = rand() % 360; // randomize dir VectorSet( le->velocity, -local_dir[0] * 5 + crandom()*5, -local_dir[1] * 5 + crandom()*5, -local_dir[2] * 5 + crandom()*5 + 3 ); VectorMA( local_dir, min( 6, count ), le->velocity, le->velocity ); } }
/* ============================================================= DECALS SERIALIZATION ============================================================= */ static qboolean R_DecalUnProject( decal_t *pdecal, decallist_t *entry ) { if( !pdecal || !( pdecal->psurface )) return false; VectorCopy( pdecal->position, entry->position ); entry->entityIndex = pdecal->entityIndex; // Grab surface plane equation if( pdecal->psurface->flags & SURF_PLANEBACK ) VectorNegate( pdecal->psurface->plane->normal, entry->impactPlaneNormal ); else VectorCopy( pdecal->psurface->plane->normal, entry->impactPlaneNormal ); return true; }