int CScriptBind_Game::DebugDrawAABB( IFunctionHandler *pH, float x, float y, float z, float x2, float y2, float z2, int r, int g, int b, int a ) { IRenderAuxGeom* pRenderAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); if (pRenderAuxGeom) { SAuxGeomRenderFlags oldFlags = pRenderAuxGeom->GetRenderFlags(); SAuxGeomRenderFlags newFlags = oldFlags; newFlags.SetCullMode(e_CullModeNone); newFlags.SetAlphaBlendMode(e_AlphaBlended); pRenderAuxGeom->SetRenderFlags(newFlags); AABB bbox(Vec3(x, y, z), Vec3(x2, y2, z2)); pRenderAuxGeom->DrawAABB(bbox, true, ColorB(r, g, b, a), eBBD_Faceted); pRenderAuxGeom->SetRenderFlags(oldFlags); } return pH->EndFunction(); }
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot) { CProjectile::Update(ctx, updateSlot); bool debug = (g_pGameCVars->g_debugMines != 0); if(gEnv->bServer) { if(m_armed) { CGameRules* pGR = g_pGame->GetGameRules(); if(pGR) { for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it); if(!pEntity) continue; // if this is a team game, claymores aren't set off by their own team... if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) continue; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) continue; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f) { // now check angle between this claymore and approaching object // to see if it is within the angular range m_triggerAngle. // If it is, then check distance is less than m_triggerRange, // and also check line-of-sight between the two entities. IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); AABB entityBBox; pEntity->GetWorldBounds(entityBBox); if(debug) { pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted ); } Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos(); Vec3 checkDir = enemyDir; checkDir.z = 0; float distanceSq = enemyDir.GetLengthSquared(); // for players a simple distance check is fine, but for vehicles use a better intersection check // so any corner of the vehicle going inside the zone sets off the claymore. static float playerRadius = 2.5f; bool inside = false; if(entityBBox.GetRadius() < playerRadius) { inside = (distanceSq < (m_triggerRadius * m_triggerRadius)); } else { static ray_hit hit; if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit)) { inside = true; enemyDir = hit.pt - GetEntity()->GetWorldPos(); } } if(inside) { enemyDir.NormalizeSafe(); checkDir.NormalizeSafe(); float dotProd = checkDir.Dot(m_triggerDirection); if(debug) { pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } if(dotProd > cry_cosf(m_triggerAngle/2.0f)) { static const int objTypes = ent_all&(~ent_terrain); static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics()); bool bang = false; if (!col) bang = true; else if (entityBBox.IsContainPoint(hit.pt)) bang = true; else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq) bang = true; if (bang) { // pass in the explosion normal, which is -m_triggerDirection Explode(true, false, Vec3(0,0,0), -m_triggerDirection); if(debug) { ColorF clr; clr.a = 0.3f; clr.g = 0.1f; clr.r = 1.0f; clr.b = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } } } } } } } } } else { m_timeToArm -= gEnv->pTimer->GetFrameTime(); if(m_timeToArm <= 0.0f) { m_armed = true; IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER)); if (!pTriggerProxy) { GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER); pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER); } if(pTriggerProxy) { // create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles. // Checks above will still make sure the entity is within the radius before detonating though. float radius = m_triggerRadius + 2.0f; AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius)); pTriggerProxy->SetTriggerBounds(boundingBox); } } } } if(debug && m_armed) { IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr); Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f); AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size); pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted); pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f); } }
void CPersistantDebug::Update( float frameTime ) { if (m_objects.empty()) return; IRenderAuxGeom * pAux = gEnv->pRenderer->GetIRenderAuxGeom(); static const int flags3D = e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn; static const int flags2D = e_Mode2D | e_AlphaBlended; std::vector<ListObj::iterator> toClear; std::vector<MapListObj::iterator> toClearMap; for (MapListObj::iterator iterMap = m_objects.begin(); iterMap != m_objects.end(); ++iterMap) { toClear.resize(0); for (ListObj::iterator iterList = iterMap->second.begin(); iterList != iterMap->second.end(); ++iterList) { iterList->timeRemaining -= frameTime; if (iterList->timeRemaining <= 0.0f && !(iterList->obj == eOT_EntityTag && iterList->columns.size() > 1)) toClear.push_back(iterList); else { ColorF clr = iterList->clr; clr.a *= iterList->timeRemaining / iterList->totalTime; switch (iterList->obj) { case eOT_Sphere: pAux->SetRenderFlags( flags3D ); pAux->DrawSphere( iterList->pos, iterList->radius, clr ); break; case eOT_Quat: pAux->SetRenderFlags( flags3D ); { float r = iterList->radius; Vec3 x = r * iterList->q.GetColumn0(); Vec3 y = r * iterList->q.GetColumn1(); Vec3 z = r * iterList->q.GetColumn2(); Vec3 p = iterList->pos; OBB obb = OBB::CreateOBB( Matrix33::CreateIdentity(), Vec3(0.05f,0.05f,0.05f), ZERO ); pAux->DrawOBB( obb, p, false, clr, eBBD_Extremes_Color_Encoded ); pAux->DrawLine( p, ColorF(1,0,0,clr.a), p+x, ColorF(1,0,0,clr.a) ); pAux->DrawLine( p, ColorF(0,1,0,clr.a), p+y, ColorF(0,1,0,clr.a) ); pAux->DrawLine( p, ColorF(0,0,1,clr.a), p+z, ColorF(0,0,1,clr.a) ); } break; case eOT_Arrow: pAux->SetRenderFlags( flags3D ); pAux->DrawLine( iterList->pos - iterList->dir * iterList->radius, clr, iterList->pos + iterList->dir * iterList->radius, clr ); pAux->DrawCone( iterList->pos + iterList->dir * iterList->radius, iterList->dir, 0.1f * iterList->radius, 0.3f * iterList->radius, clr ); break; case eOT_Line: pAux->SetRenderFlags( flags3D ); pAux->DrawLine( iterList->pos, clr, iterList->pos + iterList->dir, clr ); break; case eOT_Cone: pAux->SetRenderFlags( flags3D ); pAux->DrawCone( iterList->pos, iterList->dir, iterList->radius, iterList->radius2, clr ); break; case eOT_Cylinder: pAux->SetRenderFlags( flags3D ); pAux->DrawCylinder( iterList->pos, iterList->dir, iterList->radius, iterList->radius2, clr ); break; case eOT_AABB: pAux->SetRenderFlags( flags3D ); pAux->DrawAABB( AABB(iterList->pos,iterList->dir), Matrix34(IDENTITY), false, clr, eBBD_Faceted ); break; case eOT_Line2D: pAux->SetRenderFlags( flags2D ); pAux->DrawLine( iterList->pos, clr, iterList->dir, clr ); break; case eOT_Text: { float clrAry[4] = {clr.r, clr.g, clr.b, clr.a}; gEnv->pRenderer->Draw2dLabel( iterList->pos.x, iterList->pos.y, iterList->radius, clrAry, false, "%s", iterList->text.c_str() ); } break; case eOT_Disc: { pAux->SetRenderFlags( flags3D ); vtx_idx indTriQuad[ 6 ] = { 0, 2, 1, 0, 3, 2 }; vtx_idx indTriTri[ 3 ] = { 0, 1, 2 }; int steps = (int)(10 * iterList->radius2); steps = std::max(steps, 10); float angStep = gf_PI2 / steps; for (int i=0; i<steps; i++) { float a0 = angStep*i; float a1 = angStep*(i+1); float c0 = cosf( a0 ); float c1 = cosf( a1 ); float s0 = sinf( a0 ); float s1 = sinf( a1 ); Vec3 pts[4]; int n, n2; vtx_idx * indTri; if (iterList->radius) { n = 4; n2 = 6; pts[0] = iterList->pos + iterList->radius * Vec3( c0, s0, 0 ); pts[1] = iterList->pos + iterList->radius * Vec3( c1, s1, 0 ); pts[2] = iterList->pos + iterList->radius2 * Vec3( c1, s1, 0 ); pts[3] = iterList->pos + iterList->radius2 * Vec3( c0, s0, 0 ); indTri = indTriQuad; } else { n = 3; n2 = 3; pts[0] = iterList->pos; pts[1] = pts[0] + iterList->radius2 * Vec3( c0, s0, 0 ); pts[2] = pts[0] + iterList->radius2 * Vec3( c1, s1, 0 ); indTri = indTriTri; } pAux->DrawTriangles( pts, n, indTri, n2, clr ); } } break; case eOT_EntityTag: { UpdateTags(frameTime, *iterList); } break; } } } while (!toClear.empty()) { iterMap->second.erase(toClear.back()); toClear.pop_back(); } if (iterMap->second.empty()) toClearMap.push_back(iterMap); } while (!toClearMap.empty()) { m_objects.erase(toClearMap.back()); toClearMap.pop_back(); } }