#include "g_local.h"#include "bg_saga.h"#include "q_shared.h"#include "../namespace_begin.h"#include "../namespace_end.h"Go to the source code of this file.
Data Structures | |
| struct | shaderRemap_t |
Defines | |
| #define | MAX_SHADER_REMAPS 128 |
| #define | MAX_VEHICLES_AT_A_TIME 128 |
| #define | MAXCHOICES 32 |
| #define | MAX_G2_KILL_QUEUE 256 |
| #define | USE_DISTANCE 64.0f |
Functions | |
| void | AddRemap (const char *oldShader, const char *newShader, float timeOffset) |
| const char * | BuildShaderStateConfig (void) |
| int | G_BoneIndex (const char *name) |
| int | G_ModelIndex (const char *name) |
| int | G_IconIndex (const char *name) |
| int | G_SoundIndex (const char *name) |
| int | G_SoundSetIndex (const char *name) |
| int | G_EffectIndex (const char *name) |
| int | G_BSPIndex (const char *name) |
| qboolean | G_PlayerHasCustomSkeleton (gentity_t *ent) |
| void | G_TeamCommand (team_t team, char *cmd) |
| gentity_t * | G_Find (gentity_t *from, int fieldofs, const char *match) |
| int | G_RadiusList (vec3_t origin, float radius, gentity_t *ignore, qboolean takeDamage, gentity_t *ent_list[MAX_GENTITIES]) |
| void | G_Throw (gentity_t *targ, vec3_t newDir, float push) |
| void | G_FreeFakeClient (gclient_t **cl) |
| void | G_AllocateVehicleObject (Vehicle_t **pVeh) |
| void | G_FreeVehicleObject (Vehicle_t *pVeh) |
| void | G_CreateFakeClient (int entNum, gclient_t **cl) |
| void | G_CleanAllFakeClients (void) |
| void | BG_SetAnim (playerState_t *ps, animation_t *animations, int setAnimParts, int anim, int setAnimFlags, int blendTime) |
| void | G_SetAnim (gentity_t *ent, usercmd_t *ucmd, int setAnimParts, int anim, int setAnimFlags, int blendTime) |
| gentity_t * | G_PickTarget (char *targetname) |
| void | GlobalUse (gentity_t *self, gentity_t *other, gentity_t *activator) |
| void | G_UseTargets2 (gentity_t *ent, gentity_t *activator, const char *string) |
| void | G_UseTargets (gentity_t *ent, gentity_t *activator) |
| float * | tv (float x, float y, float z) |
| char * | vtos (const vec3_t v) |
| void | G_SetMovedir (vec3_t angles, vec3_t movedir) |
| void | G_InitGentity (gentity_t *e) |
| gentity_t * | G_Spawn (void) |
| qboolean | G_EntitiesFree (void) |
| void | G_SendG2KillQueue (void) |
| void | G_KillG2Queue (int entNum) |
| void | G_FreeEntity (gentity_t *ed) |
| gentity_t * | G_TempEntity (vec3_t origin, int event) |
| gentity_t * | G_SoundTempEntity (vec3_t origin, int event, int channel) |
| void | G_ScaleNetHealth (gentity_t *self) |
| void | G_KillBox (gentity_t *ent) |
| void | G_AddPredictableEvent (gentity_t *ent, int event, int eventParm) |
| void | G_AddEvent (gentity_t *ent, int event, int eventParm) |
| gentity_t * | G_PlayEffect (int fxID, vec3_t org, vec3_t ang) |
| gentity_t * | G_PlayEffectID (const int fxID, vec3_t org, vec3_t ang) |
| gentity_t * | G_ScreenShake (vec3_t org, gentity_t *target, float intensity, int duration, qboolean global) |
| void | G_MuteSound (int entnum, int channel) |
| void | G_Sound (gentity_t *ent, int channel, int soundIndex) |
| void | G_SoundAtLoc (vec3_t loc, int channel, int soundIndex) |
| void | G_EntitySound (gentity_t *ent, int channel, int soundIndex) |
| void | G_SoundOnEnt (gentity_t *ent, int channel, const char *soundPath) |
| qboolean | ValidUseTarget (gentity_t *ent) |
| void | G_UseDispenserOn (gentity_t *ent, int dispType, gentity_t *target) |
| int | G_CanUseDispOn (gentity_t *ent, int dispType) |
| qboolean | TryHeal (gentity_t *ent, gentity_t *target) |
| void | Touch_Button (gentity_t *ent, gentity_t *other, trace_t *trace) |
| void | TryUse (gentity_t *ent) |
| qboolean | G_PointInBounds (vec3_t point, vec3_t mins, vec3_t maxs) |
| qboolean | G_BoxInBounds (vec3_t point, vec3_t mins, vec3_t maxs, vec3_t boundsMins, vec3_t boundsMaxs) |
| void | G_SetAngles (gentity_t *ent, vec3_t angles) |
| qboolean | G_ClearTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int ignore, int clipmask) |
| void | G_SetOrigin (gentity_t *ent, vec3_t origin) |
| qboolean | G_CheckInSolid (gentity_t *self, qboolean fix) |
| int | DebugLine (vec3_t start, vec3_t end, int color) |
| void | G_ROFF_NotetrackCallback (gentity_t *cent, const char *notetrack) |
| void | G_SpeechEvent (gentity_t *self, int event) |
| qboolean | G_ExpandPointToBBox (vec3_t point, const vec3_t mins, const vec3_t maxs, int ignore, int clipmask) |
| qboolean | G_FindClosestPointOnLineSegment (const vec3_t start, const vec3_t end, const vec3_t from, vec3_t result) |
| float | ShortestLineSegBewteen2LineSegs (vec3_t start1, vec3_t end1, vec3_t start2, vec3_t end2, vec3_t close_pnt1, vec3_t close_pnt2) |
| void | GetAnglesForDirection (const vec3_t p1, const vec3_t p2, vec3_t out) |
Variables | |
| int | remapCount = 0 |
| shaderRemap_t | remappedShaders [MAX_SHADER_REMAPS] |
| gclient_t * | gClPtrs [MAX_GENTITIES] |
| int | gG2KillIndex [MAX_G2_KILL_QUEUE] |
| int | gG2KillNum = 0 |
| qboolean | gSiegeRoundBegun |
|
|
Definition at line 875 of file g_utils.c. Referenced by G_KillG2Queue(). |
|
|
Definition at line 15 of file g_utils.c. Referenced by AddRemap(). |
|
|
Definition at line 384 of file g_utils.c. Referenced by G_AllocateVehicleObject(), and G_FreeVehicleObject(). |
|
|
Definition at line 519 of file g_utils.c. Referenced by G_PickTarget(). |
|
|
Definition at line 1612 of file g_utils.c. Referenced by TryUse(). |
|
||||||||||||||||
|
Definition at line 20 of file g_utils.c. References MAX_SHADER_REMAPS, Q_stricmp(), remapCount, remappedShaders, strcpy(), and shaderRemap_t::timeOffset. Referenced by G_RemapTeamShaders(), and G_UseTargets2().
00020 {
00021 int i;
00022
00023 for (i = 0; i < remapCount; i++) {
00024 if (Q_stricmp(oldShader, remappedShaders[i].oldShader) == 0) {
00025 // found it, just update this one
00026 strcpy(remappedShaders[i].newShader,newShader);
00027 remappedShaders[i].timeOffset = timeOffset;
00028 return;
00029 }
00030 }
00031 if (remapCount < MAX_SHADER_REMAPS) {
00032 strcpy(remappedShaders[remapCount].newShader,newShader);
00033 strcpy(remappedShaders[remapCount].oldShader,oldShader);
00034 remappedShaders[remapCount].timeOffset = timeOffset;
00035 remapCount++;
00036 }
00037 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 2976 of file bg_panimate.c. References animation_t, bgLoadedAnim_t::anims, BG_SetAnimFinal(), BG_SetLegsAnimTimer(), BG_SetTorsoAnimTimer(), bgAllAnims, BOTH_RUN1, BOTH_RUNBACK1, BOTH_WALK2, BOTH_WALKBACK1, animation_s::firstFrame, playerState_s::legsAnim, animation_s::numFrames, playerState_t, SETANIM_FLAG_OVERRIDE, SETANIM_FLAG_RESTART, SETANIM_LEGS, SETANIM_TORSO, and playerState_s::torsoAnim. Referenced by AnimateRiders(), G_SetAnim(), Initialize(), PM_SetAnim(), and Vehicle_SetAnim().
02977 {
02978 if (!animations)
02979 {
02980 animations = bgAllAnims[0].anims;
02981 }
02982
02983 if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
02984 {
02985 if (anim == BOTH_RUNBACK1 ||
02986 anim == BOTH_WALKBACK1 ||
02987 anim == BOTH_RUN1)
02988 { //hack for droids
02989 anim = BOTH_WALK2;
02990 }
02991
02992 if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
02993 { //still? Just return then I guess.
02994 return;
02995 }
02996 }
02997
02998 /*
02999 if (BG_InSpecialJump(anim))
03000 {
03001 setAnimFlags |= SETANIM_FLAG_RESTART;
03002 }
03003 */
03004 //Don't know why I put this here originally but it's messing stuff up now and it isn't needed.
03005
03006 // if (BG_InRoll(ps, ps->legsAnim))
03007 // { //never interrupt a roll
03008 // return;
03009 // }
03010
03011 if (setAnimFlags&SETANIM_FLAG_OVERRIDE)
03012 {
03013 if (setAnimParts & SETANIM_TORSO)
03014 {
03015 if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->torsoAnim) != anim )
03016 {
03017 BG_SetTorsoAnimTimer(ps, 0);
03018 }
03019 }
03020 if (setAnimParts & SETANIM_LEGS)
03021 {
03022 if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->legsAnim) != anim )
03023 {
03024 BG_SetLegsAnimTimer(ps, 0);
03025 }
03026 }
03027 }
03028
03029 BG_SetAnimFinal(ps, animations, setAnimParts, anim, setAnimFlags, blendTime);
03030 }
|
|
|
Definition at line 39 of file g_utils.c. References Com_sprintf(), MAX_QPATH, MAX_STRING_CHARS, memset(), Q_strcat(), remapCount, and remappedShaders. Referenced by G_RemapTeamShaders(), and G_UseTargets2().
00039 {
00040 static char buff[MAX_STRING_CHARS*4];
00041 char out[(MAX_QPATH * 2) + 5];
00042 int i;
00043
00044 memset(buff, 0, MAX_STRING_CHARS);
00045 for (i = 0; i < remapCount; i++) {
00046 Com_sprintf(out, (MAX_QPATH * 2) + 5, "%s=%s:%5.2f@", remappedShaders[i].oldShader, remappedShaders[i].newShader, remappedShaders[i].timeOffset);
00047 Q_strcat( buff, sizeof( buff ), out);
00048 }
00049 return buff;
00050 }
|
|
||||||||||||||||
|
Definition at line 2011 of file g_utils.c. References DotProduct, trap_DebugPolygonCreate(), vec3_t, VectorCopy, VectorMA, VectorNormalize(), VectorSet, and VectorSubtract.
02011 {
02012 vec3_t points[4], dir, cross, up = {0, 0, 1};
02013 float dot;
02014
02015 VectorCopy(start, points[0]);
02016 VectorCopy(start, points[1]);
02017 //points[1][2] -= 2;
02018 VectorCopy(end, points[2]);
02019 //points[2][2] -= 2;
02020 VectorCopy(end, points[3]);
02021
02022
02023 VectorSubtract(end, start, dir);
02024 VectorNormalize(dir);
02025 dot = DotProduct(dir, up);
02026 if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
02027 else CrossProduct(dir, up, cross);
02028
02029 VectorNormalize(cross);
02030
02031 VectorMA(points[0], 2, cross, points[0]);
02032 VectorMA(points[1], -2, cross, points[1]);
02033 VectorMA(points[2], -2, cross, points[2]);
02034 VectorMA(points[3], 2, cross, points[3]);
02035
02036 return trap_DebugPolygonCreate(color, 4, points);
02037 }
|
|
||||||||||||||||
|
||||||||||||||||
|
Definition at line 1206 of file g_utils.c. References BG_AddPredictableEventToPlayerstate(), gentity_s::client, gentity_t, and gclient_s::ps. Referenced by Touch_Item().
01206 {
01207 if ( !ent->client ) {
01208 return;
01209 }
01210 BG_AddPredictableEventToPlayerstate( event, eventParm, &ent->client->ps );
01211 }
|
|
|
Definition at line 388 of file g_utils.c. References Com_Error(), ERR_DROP, MAX_VEHICLES_AT_A_TIME, memset(), qtrue, and Vehicle_t. Referenced by G_CreateAnimalNPC(), G_CreateFighterNPC(), G_CreateSpeederNPC(), and G_CreateWalkerNPC().
00389 {
00390 int i = 0;
00391
00392 if (!g_vehiclePoolInit)
00393 {
00394 g_vehiclePoolInit = qtrue;
00395 memset(g_vehiclePoolOccupied, 0, sizeof(g_vehiclePoolOccupied));
00396 }
00397
00398 while (i < MAX_VEHICLES_AT_A_TIME)
00399 { //iterate through and try to find a free one
00400 if (!g_vehiclePoolOccupied[i])
00401 {
00402 g_vehiclePoolOccupied[i] = qtrue;
00403 memset(&g_vehiclePool[i], 0, sizeof(Vehicle_t));
00404 *pVeh = &g_vehiclePool[i];
00405 return;
00406 }
00407 i++;
00408 }
00409 Com_Error(ERR_DROP, "Ran out of vehicle pool slots.");
00410 }
|
|
|
Definition at line 101 of file g_utils.c. References CS_G2BONES, MAX_G2BONES, name, and qtrue. Referenced by EWeb_SetBoneAngles(), G2Tur_SetBoneAngles(), and NPC_SetBoneAngles().
00101 {
00102 return G_FindConfigstringIndex (name, CS_G2BONES, MAX_G2BONES, qtrue);
00103 }
|
|
||||||||||||||||||||||||
|
Definition at line 1896 of file g_utils.c. References qboolean, qfalse, qtrue, vec3_t, and VectorAdd. Referenced by W_TraceSetStart().
01897 {
01898 vec3_t boxMins;
01899 vec3_t boxMaxs;
01900
01901 VectorAdd( point, mins, boxMins );
01902 VectorAdd( point, maxs, boxMaxs );
01903
01904 if(boxMaxs[0]>boundsMaxs[0])
01905 return qfalse;
01906
01907 if(boxMaxs[1]>boundsMaxs[1])
01908 return qfalse;
01909
01910 if(boxMaxs[2]>boundsMaxs[2])
01911 return qfalse;
01912
01913 if(boxMins[0]<boundsMins[0])
01914 return qfalse;
01915
01916 if(boxMins[1]<boundsMins[1])
01917 return qfalse;
01918
01919 if(boxMins[2]<boundsMins[2])
01920 return qfalse;
01921
01922 //box is completely contained within bounds
01923 return qtrue;
01924 }
|
|
|
Definition at line 153 of file g_utils.c. References CS_BSP_MODELS, MAX_SUB_BSP, name, and qtrue. Referenced by SP_misc_bsp().
00154 {
00155 return G_FindConfigstringIndex (name, CS_BSP_MODELS, MAX_SUB_BSP, qtrue);
00156 }
|
|
||||||||||||
|
Definition at line 1508 of file g_utils.c. References playerState_s::ammo, ammoData, gentity_s::client, gentity_t, gentity_s::health, HI_AMMODISP, HI_HEALTHDISP, gentity_s::inuse, LAST_USEABLE_WEAPON, gclient_s::ps, STAT_HEALTH, STAT_MAX_HEALTH, playerState_s::stats, playerState_s::weapon, weaponData, and WP_NONE. Referenced by TryUse().
01509 {
01510 if (!ent->client || !ent->inuse || ent->health < 1 ||
01511 ent->client->ps.stats[STAT_HEALTH] < 1)
01512 { //dead or invalid
01513 return 0;
01514 }
01515
01516 if (dispType == HI_HEALTHDISP)
01517 {
01518 if (ent->client->ps.stats[STAT_HEALTH] < ent->client->ps.stats[STAT_MAX_HEALTH])
01519 { //he's hurt
01520 return 1;
01521 }
01522
01523 //otherwise no
01524 return 0;
01525 }
01526 else if (dispType == HI_AMMODISP)
01527 {
01528 if (ent->client->ps.weapon <= WP_NONE || ent->client->ps.weapon > LAST_USEABLE_WEAPON)
01529 { //not a player-useable weapon
01530 return 0;
01531 }
01532
01533 if (ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex] < ammoData[weaponData[ent->client->ps.weapon].ammoIndex].max)
01534 { //needs more ammo for current weapon
01535 return 1;
01536 }
01537
01538 //needs none
01539 return 0;
01540 }
01541
01542 //invalid type?
01543 return 0;
01544 }
|
|
||||||||||||
|
Definition at line 1965 of file g_utils.c. References trace_t::allsolid, gentity_s::clipmask, entityShared_t::currentOrigin, trace_t::endpos, trace_t::fraction, G_SetOrigin(), gentity_t, entityShared_t::maxs, entityShared_t::mins, entityState_s::number, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, trace_t::startsolid, trap_LinkEntity(), trap_Trace(), vec3_t, and VectorCopy. Referenced by NPC_Begin(), SP_point_combat(), SP_waypoint(), SP_waypoint_navgoal(), SP_waypoint_navgoal_1(), SP_waypoint_navgoal_2(), SP_waypoint_navgoal_4(), SP_waypoint_navgoal_8(), and SP_waypoint_small().
01966 {
01967 trace_t trace;
01968 vec3_t end, mins;
01969
01970 VectorCopy(self->r.currentOrigin, end);
01971 end[2] += self->r.mins[2];
01972 VectorCopy(self->r.mins, mins);
01973 mins[2] = 0;
01974
01975 trap_Trace(&trace, self->r.currentOrigin, mins, self->r.maxs, end, self->s.number, self->clipmask);
01976 if(trace.allsolid || trace.startsolid)
01977 {
01978 return qtrue;
01979 }
01980
01981 if(trace.fraction < 1.0)
01982 {
01983 if(fix)
01984 {//Put them at end of trace and check again
01985 vec3_t neworg;
01986
01987 VectorCopy(trace.endpos, neworg);
01988 neworg[2] -= self->r.mins[2];
01989 G_SetOrigin(self, neworg);
01990 trap_LinkEntity(self);
01991
01992 return G_CheckInSolid(self, qfalse);
01993 }
01994 else
01995 {
01996 return qtrue;
01997 }
01998 }
01999
02000 return qfalse;
02001 }
|
|
|
Definition at line 450 of file g_utils.c. References gentity_s::client, ET_NPC, entityState_s::eType, g_entities, G_FreeFakeClient(), gentity_t, gentity_s::inuse, MAX_CLIENTS, MAX_GENTITIES, and gentity_s::s. Referenced by G_ShutdownGame().
00451 {
00452 int i = MAX_CLIENTS; //start off here since all ents below have real client structs.
00453 gentity_t *ent;
00454
00455 while (i < MAX_GENTITIES)
00456 {
00457 ent = &g_entities[i];
00458
00459 if (ent->inuse && ent->s.eType == ET_NPC && ent->client)
00460 {
00461 G_FreeFakeClient(&ent->client);
00462 }
00463 i++;
00464 }
00465 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1934 of file g_utils.c. References trace_t::allsolid, trace_t::fraction, qboolean, qfalse, qtrue, trace_t::startsolid, trap_Trace(), and vec3_t.
01935 {
01936 static trace_t tr;
01937
01938 trap_Trace( &tr, start, mins, maxs, end, ignore, clipmask );
01939
01940 if ( tr.allsolid || tr.startsolid || tr.fraction < 1.0 )
01941 {
01942 return qfalse;
01943 }
01944
01945 return qtrue;
01946 }
|
|
||||||||||||
|
Definition at line 430 of file g_utils.c. References BG_Alloc(), gclient_t, and gClPtrs. Referenced by NPC_Spawn_Do().
|
|
|
|
Definition at line 860 of file g_utils.c. References g_entities, gentity_t, gentity_s::inuse, level, MAX_CLIENTS, level_locals_t::num_entities, qboolean, qfalse, and qtrue.
00860 {
00861 int i;
00862 gentity_t *e;
00863
00864 e = &g_entities[MAX_CLIENTS];
00865 for ( i = MAX_CLIENTS; i < level.num_entities; i++, e++) {
00866 if ( e->inuse ) {
00867 continue;
00868 }
00869 // slot available
00870 return qtrue;
00871 }
00872 return qfalse;
00873 }
|
|
||||||||||||||||
|
Definition at line 1392 of file g_utils.c. References entityState_s::clientNum, entityShared_t::currentOrigin, EV_ENTITY_SOUND, entityState_s::eventParm, G_TempEntity(), gentity_t, entityState_s::number, gentity_s::r, gentity_s::s, and entityState_s::trickedentindex. Referenced by ClientCommand(), ClientThink_real(), DoGripAction(), faller_think(), faller_touch(), G_BreakArm(), G_RunFrame(), G_SpecialRollGetup(), hurt_touch(), WP_ForcePowerStop(), WP_ForcePowersUpdate(), and WP_SaberPositionUpdate().
01392 {
01393 gentity_t *te;
01394
01395 te = G_TempEntity( ent->r.currentOrigin, EV_ENTITY_SOUND );
01396 te->s.eventParm = soundIndex;
01397 te->s.clientNum = ent->s.number;
01398 te->s.trickedentindex = channel;
01399 }
|
|
||||||||||||||||||||||||
|
Definition at line 2087 of file g_utils.c. References trace_t::allsolid, trace_t::fraction, qboolean, qfalse, qtrue, trace_t::startsolid, trap_Trace(), vec3_origin, vec3_t, and VectorCopy.
02088 {
02089 trace_t tr;
02090 vec3_t start, end;
02091 int i;
02092
02093 VectorCopy( point, start );
02094
02095 for ( i = 0; i < 3; i++ )
02096 {
02097 VectorCopy( start, end );
02098 end[i] += mins[i];
02099 trap_Trace( &tr, start, vec3_origin, vec3_origin, end, ignore, clipmask );
02100 if ( tr.allsolid || tr.startsolid )
02101 {
02102 return qfalse;
02103 }
02104 if ( tr.fraction < 1.0 )
02105 {
02106 VectorCopy( start, end );
02107 end[i] += maxs[i]-(mins[i]*tr.fraction);
02108 trap_Trace( &tr, start, vec3_origin, vec3_origin, end, ignore, clipmask );
02109 if ( tr.allsolid || tr.startsolid )
02110 {
02111 return qfalse;
02112 }
02113 if ( tr.fraction < 1.0 )
02114 {
02115 return qfalse;
02116 }
02117 VectorCopy( end, start );
02118 }
02119 }
02120 //expanded it, now see if it's all clear
02121 trap_Trace( &tr, start, mins, maxs, start, ignore, clipmask );
02122 if ( tr.allsolid || tr.startsolid )
02123 {
02124 return qfalse;
02125 }
02126 VectorCopy( start, point );
02127 return qtrue;
02128 }
|
|
||||||||||||||||
|
||||||||||||||||||||
|
Definition at line 1524 of file q_math.c.
01525 {
01526 vec3_t vecStart2From, vecStart2End, vecEnd2Start, vecEnd2From;
01527 float distEnd2From, distEnd2Result, theta, cos_theta, dot;
01528
01529 //Find the perpendicular vector to vec from start to end
01530 VectorSubtract( from, start, vecStart2From);
01531 VectorSubtract( end, start, vecStart2End);
01532
01533 dot = DotProductNormalize( vecStart2From, vecStart2End );
01534
01535 if ( dot <= 0 )
01536 {
01537 //The perpendicular would be beyond or through the start point
01538 VectorCopy( start, result );
01539 return qfalse;
01540 }
01541
01542 if ( dot == 1 )
01543 {
01544 //parallel, closer of 2 points will be the target
01545 if( (VectorLengthSquared( vecStart2From )) < (VectorLengthSquared( vecStart2End )) )
01546 {
01547 VectorCopy( from, result );
01548 }
01549 else
01550 {
01551 VectorCopy( end, result );
01552 }
01553 return qfalse;
01554 }
01555
01556 //Try other end
01557 VectorSubtract( from, end, vecEnd2From);
01558 VectorSubtract( start, end, vecEnd2Start);
01559
01560 dot = DotProductNormalize( vecEnd2From, vecEnd2Start );
01561
01562 if ( dot <= 0 )
01563 {//The perpendicular would be beyond or through the start point
01564 VectorCopy( end, result );
01565 return qfalse;
01566 }
01567
01568 if ( dot == 1 )
01569 {//parallel, closer of 2 points will be the target
01570 if( (VectorLengthSquared( vecEnd2From )) < (VectorLengthSquared( vecEnd2Start )))
01571 {
01572 VectorCopy( from, result );
01573 }
01574 else
01575 {
01576 VectorCopy( end, result );
01577 }
01578 return qfalse;
01579 }
01580
01581 // /|
01582 // c / |
01583 // / |a
01584 // theta /)__|
01585 // b
01586 //cos(theta) = b / c
01587 //solve for b
01588 //b = cos(theta) * c
01589
01590 //angle between vecs end2from and end2start, should be between 0 and 90
01591 theta = 90 * (1 - dot);//theta
01592
01593 //Get length of side from End2Result using sine of theta
01594 distEnd2From = VectorLength( vecEnd2From );//c
01595 cos_theta = cos(DEG2RAD(theta));//cos(theta)
01596 distEnd2Result = cos_theta * distEnd2From;//b
01597
01598 //Extrapolate to find result
01599 VectorNormalize( vecEnd2Start );
01600 VectorMA( end, distEnd2Result, vecEnd2Start, result );
01601
01602 //perpendicular intersection is between the 2 endpoints
01603 return qtrue;
01604 }
|
|