// Returns true if the segment e1-e2 intersects the shape boundary // segment s1-s2, blocking visibility. // bool segmentShapeIntersect(const Point& e1, const Point& e2, const Point& s1, const Point& s2, bool& seenIntersectionAtEndpoint) { if (segmentIntersect(e1, e2, s1, s2)) { // Basic intersection of segments. return true; } else if ( (((s2 == e1) || pointOnLine(s1, s2, e1)) && (vecDir(s1, s2, e2) != 0)) || (((s2 == e2) || pointOnLine(s1, s2, e2)) && (vecDir(s1, s2, e1) != 0)) ) { // Segments intersect at the endpoint of one of the segments. We // allow this once, but the second one blocks visibility. Otherwise // shapes butted up against each other could have visibility through // shapes. if (seenIntersectionAtEndpoint) { return true; } seenIntersectionAtEndpoint = true; } return false; }
// Returns true if the segment cd intersects the segment ab, blocking // visibility. // // Based on the code of 'IntersectProp' and 'Intersect'. // bool segmentIntersect(const Point& a, const Point& b, const Point& c, const Point& d) { int ab_c = vecDir(a, b, c); if (ab_c == 0) { return false; } int ab_d = vecDir(a, b, d); if (ab_d == 0) { return false; } // It's ok for either of the points a or b to be on the line cd, // so we don't have to check the other two cases. int cd_a = vecDir(c, d, a); int cd_b = vecDir(c, d, b); // Is an intersection if a and b are on opposite sides of cd, // and c and d are on opposite sides of the line ab. // // Note: this is safe even though the textbook warns about it // since, unlike them, our vecDir is equivilent to 'AreaSign' // rather than 'Area2'. return (((ab_c * ab_d) < 0) && ((cd_a * cd_b) < 0)); }
// Gives the side of a corner that a point lies on: // 1 anticlockwise // -1 clockwise // e.g. /|s2 // /s3 -1 / | // / / | // 1 |s2 -1 / 1 | -1 // | / | // |s1 s3/ |s1 // int cornerSide(const Point &c1, const Point &c2, const Point &c3, const Point& p) { int s123 = vecDir(c1, c2, c3); int s12p = vecDir(c1, c2, p); int s23p = vecDir(c2, c3, p); if (s123 == 1) { if ((s12p >= 0) && (s23p >= 0)) { return 1; } return -1; } else if (s123 == -1) { if ((s12p <= 0) && (s23p <= 0)) { return -1; } return 1; } // c1-c2-c3 are collinear, so just return vecDir from c1-c2 return s12p; }
// Returns true iff the point p in a valid region that can contain // shortest paths. a0, a1, a2 are ordered vertices of a shape. // // Based on the code of 'InCone'. // bool inValidRegion(bool IgnoreRegions, const Point& a0, const Point& a1, const Point& a2, const Point& b) { // r is a0--a1 // s is a1--a2 int rSide = vecDir(b, a0, a1); int sSide = vecDir(b, a1, a2); bool rOutOn = (rSide <= 0); bool sOutOn = (sSide <= 0); bool rOut = (rSide < 0); bool sOut = (sSide < 0); if (vecDir(a0, a1, a2) > 0) { // Convex at a1: // // !rO rO // sO sO // // ---s---+ // | // !rO r rO // !sO | !sO // // if (IgnoreRegions) { return (rOutOn && !sOut) || (!rOut && sOutOn); } return (rOutOn || sOutOn); } else { // Concave at a1: // // !rO rO // !sO !sO // // +---s--- // | // !rO r rO // sO | sO // // return (IgnoreRegions ? false : (rOutOn && sOutOn)); } }
Polygon Polygon::simplify(void) const { Polygon simplified = *this; std::vector<Point>::iterator it = simplified.ps.begin(); if (it != simplified.ps.end()) ++it; // Combine collinear line segments into single segments: for (size_t j = 2; j < simplified.size(); ) { if (vecDir(simplified.ps[j - 2], simplified.ps[j - 1], simplified.ps[j]) == 0) { // These three points make up two collinear segments, so just // compine them into a single segment. it = simplified.ps.erase(it); } else { ++j; ++it; } } return simplified; }
// DeadTakeDamage - takedamage function called when a monster's corpse is damaged. int CBaseMonster::DeadTakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) { // grab the vector of the incoming attack. ( pretend that the inflictor is a little lower than it really is, so the body will tend to fly upward a bit). Vector vecDir(0, 0, 0); if (!FNullEnt(pevInflictor)) { CBaseEntity *pInflictor = CBaseEntity::Instance(pevInflictor); if (pInflictor) { vecDir = (pInflictor->Center() - Vector(0, 0, 10) - Center()).Normalize(); vecDir = g_vecAttackDir = vecDir.Normalize(); } } // turn this back on when the bounding box issues are resolved. #if 0 pev->flags &= ~FL_ONGROUND; pev->origin.z += 1; // let the damage scoot the corpse around a bit. if (!FNullEnt(pevInflictor) && (pevAttacker->solid != SOLID_TRIGGER)) { pev->velocity = pev->velocity + vecDir * -DamageForce(flDamage); } #endif // kill the corpse if enough damage was done to destroy the corpse and the damage is of a type that is allowed to destroy the corpse. if (bitsDamageType & DMG_GIB_CORPSE) { if (pev->health <= flDamage) { pev->health = -50; Killed(pevAttacker, GIB_ALWAYS); return 0; } // Accumulate corpse gibbing damage, so you can gib with multiple hits pev->health -= flDamage * 0.1; } return 1; }
void LudoRenderer::SetLight(const LudoVector * const position, int r, int g, int b) { D3DLIGHT9 light; ZeroMemory(&light, sizeof(D3DLIGHT9)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.a = 1.0f; light.Diffuse.r = (float)r / 255.0f; light.Diffuse.g = (float)g / 255.0f; light.Diffuse.b = (float)b / 255.0f; light.Range = 4000.0f; D3DXVECTOR3 vecDir(position->GetX(), position->GetY(), position->GetZ()); D3DXVec3Normalize( (D3DXVECTOR3 *)&light.Direction, &vecDir); //m_d3DDev->SetLight(0, &light); //m_d3DDev->LightEnable(0, TRUE); }
// Returns true iff the point c lies on the closed segment ab. // To be used when the points are known to be collinear. // // Based on the code of 'Between'. // bool inBetween(const Point& a, const Point& b, const Point& c) { // We only call this when we know the points are collinear, // otherwise we should be checking this here. COLA_ASSERT(vecDir(a, b, c, 0.0001) == 0); if ((fabs(a.x - b.x) > 1) && (a.x != b.x)) { // not vertical return (((a.x < c.x) && (c.x < b.x)) || ((b.x < c.x) && (c.x < a.x))); } else { return (((a.y < c.y) && (c.y < b.y)) || ((b.y < c.y) && (c.y < a.y))); } }
void CAWP::PrimaryAttack() { if( m_iClip <= 0 ) return; m_iClip--; m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); Vector vecSrc( m_pPlayer->GetGunPosition() ); Vector vecAim( m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ) ); Vector vecAcc( g_vecZero ); if ( !( m_pPlayer->pev->flags & FL_ONGROUND ) ) vecAcc = vec3_t( 0.85, 0.85, 0.85 ); else if ( m_pPlayer->pev->velocity.Length2D() > 140 || !scope ) vecAcc = vec3_t( 0.25, 0.25, 0.25 ); else if ( m_pPlayer->pev->velocity.Length2D() > 10 ) vecAcc = vec3_t( 0.10, 0.10, 0.10 ); else vecAcc = vec3_t( 0, 0, 0 ); Vector vecDir( m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAim, vecAcc, 8192,0, 0, 114, m_pPlayer->pev, m_pPlayer->random_seed ) ); SendWeaponAnim( AWP_SHOOT1 ); PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_event, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, (m_iClip ? 0 : 1), 0 ); m_pPlayer->pev->fov = 0; m_pPlayer->m_iFOV = m_pPlayer->pev->fov; scope = false; g_engfuncs.pfnSetClientMaxspeed(m_pPlayer->edict(), 210 ); #ifndef CLIENT_DLL MESSAGE_BEGIN( MSG_ONE, gmsgScopeToggle, NULL, m_pPlayer->pev ); WRITE_BYTE( 0 ); MESSAGE_END(); #endif m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.45; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.45; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.45; }
TEST(collideWorld, ray2sphere) { Vector3 p1(0.0f, 0.0f, 0.0f); Vector3 p2(0.0f, 4.0f, 0.0f); Vector3 vecDir(0.0f, 2.0f, 0.0f); float r = 2.0f; Sphere sphere(p2, r); Ray ray(p1, vecDir); CollidableObject object1(&ray, p1, 0); CollidableObject object2(&sphere, p1, 1); /* CollisionWorld world; world.addObject(object1); world.addObject(object2); world.computeCollision(); printf("# of objects: %d\n", world.getObjectSize()); printf("# of collides: %d\n", world.getCollideSize()); */ }
// Returns true iff the point c lies on the closed segment ab. // bool pointOnLine(const Point& a, const Point& b, const Point& c, const double tolerance) { // Do this a bit more optimally for orthogonal AB line segments. if (a.x == b.x) { return (a.x == c.x) && (((a.y < c.y) && (c.y < b.y)) || ((b.y < c.y) && (c.y < a.y))); } else if (a.y == b.y) { return (a.y == c.y) && (((a.x < c.x) && (c.x < b.x)) || ((b.x < c.x) && (c.x < a.x))); } // Or use the general case. return (vecDir(a, b, c, tolerance) == 0) && inBetween(a, b, c); }
void Rocket_Update(Object *pObject) { Projectile *pProjectile=(Projectile *)pObject; Matrix mat; Matrix *pLast; Object_GetMatrix(pObject,&mat); mat.SetColumn(3, mat.GetColumn(3) + pProjectile->vecVel); Object_GetMatrixPtrLast(pObject,&pLast); Vec3 vecDir(mat.GetColumn(0)*0.25f); Trail_AddPoint((Object*)pProjectile->pTrails[0], pLast->GetColumn(3), vecDir); vecDir = (mat.GetColumn(1)*0.25f); Trail_AddPoint((Object*)pProjectile->pTrails[1], pLast->GetColumn(3), vecDir); if(Level_TestLineCollide( pLast->GetColumn(3), mat.GetColumn(3) )) { pProjectile->fLife = -1.f; ColData Data; // Get the collision data Collision_GetColData(&Data); vecDir = (mat.GetColumn(0)*0.25f); Trail_AddPoint((Object*)pProjectile->pTrails[0], Data.vecPoint, vecDir); vecDir = (mat.GetColumn(1)*0.25f); Trail_AddPoint((Object*)pProjectile->pTrails[1], Data.vecPoint, vecDir); // NIK: Create particle effect at collision position Particles_Create( 0, Data.vecPoint ); } Object_SetMatrix(pObject, &mat); }
// Returns true iff the three points are colinear. // bool colinear(const Point& a, const Point& b, const Point& c, const double tolerance) { // Do this a bit more optimally for orthogonal AB line segments. if (a == b) { return true; } else if (a.x == b.x) { return (a.x == c.x); } else if (a.y == b.y) { return (a.y == c.y); } // Or use the general case. return (vecDir(a, b, c, tolerance) == 0); }
// Returns true iff the point q is inside (or on the edge of) the // polygon argpoly. // // This is a fast version that only works for convex shapes. The // other version (inPolyGen) is more general. // bool inPoly(const Polygon& poly, const Point& q, bool countBorder) { size_t n = poly.size(); const std::vector<Point>& P = poly.ps; bool onBorder = false; for (size_t i = 0; i < n; i++) { // point index; i1 = i-1 mod n size_t prev = (i + n - 1) % n; int dir = vecDir(P[prev], P[i], q); if (dir == -1) { // Point is outside return false; } // Record if point was on a boundary. onBorder |= (dir == 0); } if (!countBorder && onBorder) { return false; } return true; }
ShaderDevise* ShaderDevise::init(int w, int h, HWND hWnd) { ShaderDevise& sd(ShaderDevise::inst()); if(!(sd._d3d = Direct3DCreate9(D3D_SDK_VERSION))) return 0; D3DPRESENT_PARAMETERS d3dpp = {w, h, D3DFMT_UNKNOWN, 0, D3DMULTISAMPLE_NONE, 0, D3DSWAPEFFECT_DISCARD,NULL,TRUE,TRUE,D3DFMT_D24S8,0,0}; if( FAILED(sd._d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &sd._device))) { if( FAILED(sd._d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &sd._device))) { if( FAILED(sd._d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &sd._device))) { if( FAILED(sd._d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &sd._device))) { sd._d3d->Release(); sd._d3d = NULL; sd._device = NULL; return 0; } } } } sd._device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); sd._device->SetRenderState(D3DRS_LIGHTING, TRUE); sd._device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); sd._device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); sd._device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); sd._device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); sd._device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); sd._device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); sd._device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); sd._device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); sd._device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); ZeroMemory(&sd.light, sizeof(D3DLIGHT9)*8); sd.light[0].Type = D3DLIGHT_DIRECTIONAL; sd.light[0].Diffuse.r = 0.5f; sd.light[0].Diffuse.g = 0.5f; sd.light[0].Diffuse.b = 0.5f; sd.light[0].Diffuse.a = 1.0f; sd.light[0].Specular.r = sd.light[0].Specular.g = sd.light[0].Specular.b = sd.light[0].Specular.a = 1.0f; sd.light[0].Ambient.r = 0.098f; sd.light[0].Ambient.g = 0.098f; sd.light[0].Ambient.b = 0.439f; sd.light[0].Ambient.a = 1.0f; D3DXVECTOR3 vecDir(-0.76f, -0.52f, -0.31f); D3DXVec3Normalize((D3DXVECTOR3*)&sd.light[0].Direction, &vecDir); sd._device->SetLight(0, &sd.light[0]); sd._device->LightEnable(0, TRUE); sd.light_vec[0] = sd.light[0].Direction; sd._device->SetRenderState(D3DRS_SPECULARENABLE, true); D3DMATERIAL9 mat = { 1, 1, 1, 1, 1.0f, 1.0f, 1.0f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0, 0, 0, 0, 5 }; sd._device->SetMaterial(&mat); // フォントの生成 int fontsize = 24; D3DXFONT_DESC lf = {fontsize, 0, 0, 1, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, "MS ゴシック"}; if(FAILED(D3DXCreateFontIndirect(sd._device, &lf, &sd.font))){ return 0; } return &sd; }
// The damage is coming from inflictor, but get mad at attacker // This should be the only function that ever reduces health. // bitsDamageType indicates the type of damage sustained, ie: DMG_SHOCK // // Time-based damage: only occurs while the monster is within the trigger_hurt. // When a monster is poisoned via an arrow etc it takes all the poison damage at once. int CBaseMonster::__MAKE_VHOOK(TakeDamage)(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) { if (pev->takedamage == DAMAGE_NO) return 0; if (!IsAlive()) { return DeadTakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); } if (pev->deadflag == DEAD_NO) { // no pain sound during death animation. PainSound(); } // LATER: make armor consideration here! float flTake = flDamage; // set damage type sustained m_bitsDamageType |= bitsDamageType; // grab the vector of the incoming attack. ( pretend that the inflictor is a little lower than it really is, so the body will tend to fly upward a bit). Vector vecDir(0, 0, 0); if (!FNullEnt(pevInflictor)) { CBaseEntity *pInflictor = CBaseEntity::Instance(pevInflictor); if (pInflictor) { #ifndef PLAY_GAMEDLL vecDir = (pInflictor->Center() - Vector(0, 0, 10) - Center()).Normalize(); #else // TODO: fix test demo vecDir = NormalizeSubtract< float_precision, float, float_precision, float_precision >(Center(), pInflictor->Center() - Vector(0, 0, 10)); #endif vecDir = g_vecAttackDir = vecDir.Normalize(); } } // add to the damage total for clients, which will be sent as a single // message at the end of the frame // TODO: remove after combining shotgun blasts? if (IsPlayer()) { if (pevInflictor) { pev->dmg_inflictor = ENT(pevInflictor); } pev->dmg_take += flTake; } pev->health -= flTake; if (m_MonsterState == MONSTERSTATE_SCRIPT) { SetConditions(bits_COND_LIGHT_DAMAGE); return 0; } if (pev->health <= 0.0f) { g_pevLastInflictor = pevInflictor; if (bitsDamageType & DMG_ALWAYSGIB) Killed(pevAttacker, GIB_ALWAYS); else if (bitsDamageType & DMG_NEVERGIB) Killed(pevAttacker, GIB_NEVER); else Killed(pevAttacker, GIB_NORMAL); g_pevLastInflictor = NULL; return 0; } if ((pev->flags & FL_MONSTER) && !FNullEnt(pevAttacker)) { if (pevAttacker->flags & (FL_MONSTER | FL_CLIENT)) { if (pevInflictor) { if (m_hEnemy == NULL || pevInflictor == m_hEnemy->pev || !HasConditions(bits_COND_SEE_ENEMY)) m_vecEnemyLKP = pevInflictor->origin; } else { m_vecEnemyLKP = pev->origin + (g_vecAttackDir * 64); } MakeIdealYaw(m_vecEnemyLKP); if (flDamage > 20.0f) { SetConditions(bits_COND_LIGHT_DAMAGE); } if (flDamage >= 20.0f) { SetConditions(bits_COND_HEAVY_DAMAGE); } } } return 1; }
// Returns true iff the point c lies on the closed segment ab. // bool pointOnLine(const Point& a, const Point& b, const Point& c, const double tolerance) { return (vecDir(a, b, c, tolerance) == 0) && inBetween(a, b, c); }