void CActor::PickupModeUpdate() { if(!m_bPickupMode) return; if (GameID() != GAME_SINGLE) return; //подбирание объекта if(inventory().m_pTarget && inventory().m_pTarget->Useful() && m_pUsableObject && m_pUsableObject->nonscript_usable() && !Level().m_feel_deny.is_object_denied(smart_cast<CGameObject*>(inventory().m_pTarget)) ) { NET_Packet P; u_EventGen(P, GE_OWNERSHIP_TAKE, ID()); P.w_u16(inventory().m_pTarget->object().ID()); u_EventSend(P); } //. ????? GetNearest ????? feel_touch_update (Position(), /*inventory().GetTakeDist()*/m_fPickupInfoRadius); CFrustum frustum; frustum.CreateFromMatrix(Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); //. slow (ray-query test) for(xr_vector<CObject*>::iterator it = feel_touch.begin(); it != feel_touch.end(); it++) if (CanPickItem(frustum,Device.vCameraPosition,*it)) PickupInfoDraw(*it); }
/////////////////////////////////////////////////////////////////////////////// // Intersect with frustum by repeated slicing void CBrush::Intersect(const CFrustum& frustum, CBrush& result) const { ENSURE(&result != this); if (!frustum.GetNumPlanes()) { result = *this; return; } CBrush buf; const CBrush* prev = this; CBrush* next; if (frustum.GetNumPlanes() & 1) next = &result; else next = &buf; for(size_t i = 0; i < frustum.GetNumPlanes(); ++i) { prev->Slice(frustum[i], *next); prev = next; if (prev == &buf) next = &result; else next = &buf; } ENSURE(prev == &result); }
void CActor::PickupModeUpdate() { if(!m_bPickupMode) return; // kUSE key pressed if(!IsGameTypeSingle()) return; //подбирание объекта if( m_pObjectWeLookingAt && m_pObjectWeLookingAt->cast_inventory_item() && m_pObjectWeLookingAt->cast_inventory_item()->Useful() && m_pUsableObject && !m_pUsableObject->nonscript_usable() && !Level().m_feel_deny.is_object_denied(m_pObjectWeLookingAt) ) { m_pUsableObject->use(this); Game().SendPickUpEvent(ID(), m_pObjectWeLookingAt->ID()); } feel_touch_update (Position(), m_fPickupInfoRadius); CFrustum frustum; frustum.CreateFromMatrix(Device.mFullTransform, FRUSTUM_P_LRTB|FRUSTUM_P_FAR); for(xr_vector<CObject*>::iterator it = feel_touch.begin(); it != feel_touch.end(); it++) { if (CanPickItem(frustum, Device.vCameraPosition, *it)) PickupInfoDraw(*it); } }
void CInstanceMesh::Render() { if ( !mStaticMesh || !GetActive() ) return; Math::Mat44f lTransform = GetTransform(); mCenter = lTransform* mStaticMesh->GetAABB().GetCenter(); if( mIsDynamic ) { mPhysicActor->GetMat44( lTransform ); Math::Vect3f lUp( 0.0f, -mStaticMesh->GetAABB().GetCenter().y, 0.0f ); Math::Mat44f lCenterTransform; lCenterTransform.SetIdentity(); lCenterTransform.Translate( lUp ); lTransform = lTransform * lCenterTransform; } CFrustum lCameraFrustum = CameraMInstance->GetCurrentCamera()->GetFrustum(); CGraphicsManager* lGM = GraphicsInstance; if ( lCameraFrustum.SphereVisible( D3DXVECTOR3( mCenter.u ), mRadius ) ) { lGM ->SetTransform( lTransform ); mStaticMesh->Render( lGM ); lGM ->SetTransform( Math::Mat44f() ); } }
void Vision::feel_vision_query (Fmatrix& mFull, Fvector& P) { CFrustum Frustum ; Frustum.CreateFromMatrix (mFull,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); // Traverse object database r_spatial.clear_not_free (); g_SpatialSpace->q_frustum ( r_spatial, 0, STYPE_VISIBLEFORAI, Frustum ); // Determine visibility for dynamic part of scene seen.clear_and_reserve () ; for (u32 o_it=0; o_it<r_spatial.size(); o_it++) { ISpatial* spatial = r_spatial [o_it]; CObject* object = spatial->dcast_CObject (); if (object && feel_vision_isRelevant(object)) seen.push_back (object); } if (seen.size()>1) { std::sort (seen.begin(),seen.end()); xr_vector<CObject*>::iterator end = std::unique (seen.begin(),seen.end()); if (end!=seen.end()) seen.erase (end,seen.end()); } }
void walk (ISpatial_NODE* N, Fvector& n_C, float n_R, u32 fmask) { // box float n_vR = 2*n_R; Fbox BB; BB.set (n_C.x-n_vR, n_C.y-n_vR, n_C.z-n_vR, n_C.x+n_vR, n_C.y+n_vR, n_C.z+n_vR); if (fcvNone==F->testAABB(BB.data(),fmask)) return; // test items xr_vector<ISpatial*>::iterator _it = N->items.begin (); xr_vector<ISpatial*>::iterator _end = N->items.end (); for (; _it!=_end; _it++) { ISpatial* S = *_it; if (0==(S->spatial.type&mask)) continue; Fvector& sC = S->spatial.sphere.P; float sR = S->spatial.sphere.R; u32 tmask = fmask; if (fcvNone==F->testSphere(sC,sR,tmask)) continue; space->q_result->push_back (S); } // recurse float c_R = n_R/2; for (u32 octant=0; octant<8; octant++) { if (0==N->children[octant]) continue; Fvector c_C; c_C.mad (n_C,c_spatial_offset[octant],c_R); walk (N->children[octant],c_C,c_R,fmask); } }
/////////////////////////////////////////////////////////////////////////////// // Intersect with frustum by repeated slicing void CBrush::Intersect(const CFrustum& frustum, CBrush& result) const { ENSURE(&result != this); if (!frustum.GetNumPlanes()) { result = *this; return; } CBrush buf; const CBrush* prev = this; CBrush* next; // Repeatedly slice this brush with each plane of the frustum, alternating between 'result' and 'buf' to // save intermediate results. Set up the starting brush so that the final version always ends up in 'result'. if (frustum.GetNumPlanes() & 1) next = &result; else next = &buf; for(size_t i = 0; i < frustum.GetNumPlanes(); ++i) { prev->Slice(frustum[i], *next); prev = next; if (prev == &buf) next = &result; else next = &buf; } ENSURE(prev == &result); }
void EDetailManager::UpdateSlotBBox(int sx, int sz, DetailSlot& slot) { Fbox bbox; Frect rect; GetSlotRect (rect,sx,sz); bbox.min.set (rect.x1, m_BBox.min.y, rect.y1); bbox.max.set (rect.x2, m_BBox.max.y, rect.y2); SBoxPickInfoVec pinf; ETOOLS::box_options(0); if (Scene->BoxPickObjects(bbox,pinf,&m_SnapObjects)){ bbox.grow (EPS_L_VAR); Fplane frustum_planes[4]; frustum_planes[0].build(bbox.min,left_vec); frustum_planes[1].build(bbox.min,back_vec); frustum_planes[2].build(bbox.max,right_vec); frustum_planes[3].build(bbox.max,fwd_vec); CFrustum frustum; frustum.CreateFromPlanes(frustum_planes,4); float y_min = flt_max; float y_max = flt_min; for (SBoxPickInfoIt it=pinf.begin(); it!=pinf.end(); it++){ for (int k=0; k<(int)it->inf.size(); k++){ float range; Fvector verts[3]; it->e_obj->GetFaceWorld(it->s_obj->_Transform(),it->e_mesh,it->inf[k].id,verts); sPoly sSrc (verts,3); sPoly sDest; sPoly* sRes = frustum.ClipPoly(sSrc, sDest); if (sRes){ for (u32 k=0; k<sRes->size(); k++){ float H = (*sRes)[k].y; if (H>y_max) y_max = H+0.03f; if (H<y_min) y_min = H-0.03f; } slot.w_y (y_min,y_max-y_min); slot.w_id(0,DetailSlot::ID_Empty); slot.w_id(1,DetailSlot::ID_Empty); slot.w_id(2,DetailSlot::ID_Empty); slot.w_id(3,DetailSlot::ID_Empty); } } } }else{ ZeroMemory(&slot,sizeof(DetailSlot)); slot.w_id(0,DetailSlot::ID_Empty); slot.w_id(1,DetailSlot::ID_Empty); slot.w_id(2,DetailSlot::ID_Empty); slot.w_id(3,DetailSlot::ID_Empty); } }
void __stdcall CHOM::MT_RENDER() { MT.Enter (); bool b_main_menu_is_active = (g_pGamePersistent->m_pMainMenu && g_pGamePersistent->m_pMainMenu->IsActive() ); if (MT_frame_rendered!=Device.dwFrame && !b_main_menu_is_active) { CFrustum ViewBase; ViewBase.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB + FRUSTUM_P_FAR); Enable (); Render (ViewBase); } MT.Leave (); }
/////////////////////////////////////////////////////////// // This callback is part of the Scene interface // Submit all objects visible in the given frustum void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c) { { PROFILE3("submit terrain"); CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain(); float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight + 0.001f; const ssize_t patchesPerSide = pTerrain->GetPatchesPerSide(); // find out which patches will be drawn for (ssize_t j=0; j<patchesPerSide; ++j) { for (ssize_t i=0; i<patchesPerSide; ++i) { CPatch* patch=pTerrain->GetPatch(i,j); // can't fail // If the patch is underwater, calculate a bounding box that also contains the water plane CBoundingBoxAligned bounds = patch->GetWorldBounds(); if(bounds[1].Y < waterHeight) bounds[1].Y = waterHeight; if (!m->Culling || frustum.IsBoxVisible(bounds)) c->Submit(patch); } } } m->Game->GetSimulation2()->RenderSubmit(*c, frustum, m->Culling); }
IC EFC_Visible _box (Fvector& C, Fvector& E, u32& mask) { Fvector mM[2]; mM[0].sub (C,E); mM[1].add (C,E); return F->testAABB (&mM[0].x,mask); }
void _prim (DWORD prim) { if (bClass3) { sPoly src,dst; src.resize (3); src[0] = verts[ tris[prim].verts[0] ]; src[1] = verts[ tris[prim].verts[1] ]; src[2] = verts[ tris[prim].verts[2] ]; if (F->ClipPoly(src,dst)) { RESULT& R = dest->r_add(); R.id = prim; R.verts[0] = verts[ tris[prim].verts[0] ]; R.verts[1] = verts[ tris[prim].verts[1] ]; R.verts[2] = verts[ tris[prim].verts[2] ]; R.dummy = tris[prim].dummy; } } else { RESULT& R = dest->r_add(); R.id = prim; R.verts[0] = verts[ tris[prim].verts[0] ]; R.verts[1] = verts[ tris[prim].verts[1] ]; R.verts[2] = verts[ tris[prim].verts[2] ]; R.dummy = tris[prim].dummy; } }
/** * CABT::renderTree * @date Modified Apr 17, 2006 */ void CABT::renderTree(CFrustum& oFrustum, SABTNode* pNode, bool bContained) { ACEASSERT(pNode); // Process subnodes CFrustum::EFrustumTest eTest = CFrustum::TEST_IN; eTest = oFrustum.containsAABB(pNode->m_oAABB); if(eTest == CFrustum::TEST_OUT) return; // Draw geometry, if the node is a leaf. if(pNode->m_bIsLeaf) { for(size_t v = 0; v < pNode->m_nVertCount/3; ++v) m_pRenderQueue->addRenderable(&pNode->m_pTris[v]); m_nNumTrianglesRendered += pNode->m_nVertCount / 3; #ifdef _DEBUG static int i = 0; if(true) { drawBoundingBox(pNode->m_oAABB, D3DCOLOR_XRGB(255, 0, 0)); } #endif } if(pNode->m_pLeft) renderTree(oFrustum, pNode->m_pLeft, eTest == CFrustum::TEST_IN); if(pNode->m_pRight) renderTree(oFrustum, pNode->m_pRight, eTest == CFrustum::TEST_IN); }
void ISpatial_DB::q_frustum (xr_vector<ISpatial*>& R, u32 _o, u32 _mask, const CFrustum& _frustum) { cs.Enter (); q_result = &R; q_result->clear_not_free(); walker W(this,_mask,&_frustum); W.walk(m_root,m_center,m_bounds,_frustum.getMask()); cs.Leave (); }
void CQuake3BSP::RenderLevel(const CVector3 &vPos) { // Reset our bitset so all the slots are zero. m_FacesDrawn.ClearAll(); // Grab the leaf index that our camera is in int leafIndex = FindLeaf(vPos); // Grab the cluster that is assigned to the leaf int cluster = m_pLeafs[leafIndex].cluster; // Initialize our counter variables (start at the last leaf and work down) int i = m_numOfLeafs; g_VisibleFaces = 0; // Go through all the leafs and check their visibility while(i--) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &(m_pLeafs[i]); // If the current leaf can't be seen from our cluster, go to the next leaf if(!IsClusterVisible(cluster, pLeaf->cluster)) continue; // If the current leaf is not in the camera's frustum, go to the next leaf if(!g_Frustum.BoxInFrustum((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)) continue; // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceCount--) { // Grab the current face index from our leaf faces array int faceIndex = m_pLeafFaces[pLeaf->leafface + faceCount]; // Before drawing this face, make sure it's a normal polygon if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if(!m_FacesDrawn.On(faceIndex)) { // Increase the rendered face count to display for fun g_VisibleFaces++; // Set this face as drawn and render it m_FacesDrawn.Set(faceIndex); RenderFace(faceIndex); } } } }
/** * CABT::renderTree * @date Modified Apr 17, 2006 */ void CABT::renderTree(CFrustum& oFrustum) { if(!m_pRoot) return; m_nNumTrianglesRendered = 0; renderTree(oFrustum, m_pRoot); m_pRenderQueue->renderAll(oFrustum.getViewPosition()); }
int ZQuadTree::_IsInFrustum(CGeoMapData &pHeightMap, Point &bottomLeft, CFrustum& pFrustum) { bool b[4]; bool bInSphere; bInSphere = pFrustum.SphereInFrustum(bottomLeft.x + m_nCenter.x, bottomLeft.y + m_nCenter.y, 0, m_fRadius); if(!bInSphere) return FRUSTUM_OUT; b[0] = pFrustum.PointInFrustum(bottomLeft.x + m_nCorner[0].x, bottomLeft.y + m_nCorner[0].y, 0); b[1] = pFrustum.PointInFrustum(bottomLeft.x + m_nCorner[1].x, bottomLeft.y + m_nCorner[1].y, 0); b[2] = pFrustum.PointInFrustum(bottomLeft.x + m_nCorner[2].x, bottomLeft.y + m_nCorner[2].y, 0); b[3] = pFrustum.PointInFrustum(bottomLeft.x + m_nCorner[3].x, bottomLeft.y + m_nCorner[3].y, 0); if(b[0] + b[1] + b[2] + b[3] == 4) return FRUSTUM_COMPLETELY_IN; return FRUSTUM_PRTIALLY_IN; }
void MK_Frustum(CFrustum& F, float FOV, float _FAR, float A, Fvector &P, Fvector &D, Fvector &U) { float YFov = deg2rad(FOV); float XFov = deg2rad(FOV/A); // calc window extents in camera coords float wR=tanf(XFov*0.5f); float wL=-wR; float wT=tanf(YFov*0.5f); float wB=-wT; // calc x-axis (viewhoriz) and store cop // here we are assuring that vectors are perpendicular & normalized Fvector R,COP; D.normalize (); R.crossproduct (D,U); R.normalize (); U.crossproduct (R,D); U.normalize (); COP.set (P); // calculate the corner vertices of the window Fvector sPts[4]; // silhouette points (corners of window) Fvector Offset,T; Offset.add (D,COP); sPts[0].mul(R,wR); T.mad(Offset,U,wT); sPts[0].add(T); sPts[1].mul(R,wL); T.mad(Offset,U,wT); sPts[1].add(T); sPts[2].mul(R,wL); T.mad(Offset,U,wB); sPts[2].add(T); sPts[3].mul(R,wR); T.mad(Offset,U,wB); sPts[3].add(T); // find projector direction vectors (from cop through silhouette pts) Fvector ProjDirs[4]; ProjDirs[0].sub(sPts[0],COP); ProjDirs[1].sub(sPts[1],COP); ProjDirs[2].sub(sPts[2],COP); ProjDirs[3].sub(sPts[3],COP); Fvector _F[4]; _F[0].mad(COP, ProjDirs[0], _FAR); _F[1].mad(COP, ProjDirs[1], _FAR); _F[2].mad(COP, ProjDirs[2], _FAR); _F[3].mad(COP, ProjDirs[3], _FAR); F.CreateFromPoints(_F,4,COP); }
bool CGroupObject::FrustumPick(const CFrustum& frustum) { if (m_Objects.empty()){ Fbox bb; GetBox (bb); u32 mask = u32(-1); return (frustum.testAABB(bb.data(),mask)); }else{ for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++) if ((*it)->FrustumPick(frustum)) return true; } return false; }
bool CEditShape::FrustumPick(const CFrustum& frustum) { const Fmatrix& M = _Transform(); for (ShapeIt it=shapes.begin(); it!=shapes.end(); it++){ switch (it->type){ case cfSphere:{ Fvector C; Fsphere& T = it->data.sphere; M.transform_tiny(C,T.P); if (frustum.testSphere_dirty(C,T.R*FScale.x)) return true; }break; case cfBox:{ Fbox box; box.identity (); Fmatrix B = it->data.box; B.mulA_43 (_Transform()); box.xform (B); u32 mask = 0xff; if (frustum.testAABB(box.data(),mask)) return true; }break; } } return false; }
BOOL CFrustum::CreateFromClipPoly(Fvector* p, int count, Fvector& vBase, CFrustum& clip) { VERIFY(count<FRUSTUM_MAXPLANES); VERIFY(count>=3); sPoly poly1 (p,count); sPoly poly2; sPoly* dest = clip.ClipPoly(poly1,poly2); // here we end up with complete frustum-polygon in 'dest' if (0==dest) return false; CreateFromPoints(dest->begin(),dest->size(),vBase); return true; }
void CRenderer::DrawScene(const CFrustum& frustum, CWorld* world, int localctrlid, bool generateShadowMap) { CObj* obj; OBJITER iter; // Draw the level if(!generateShadowMap && world->GetBSP()->IsLoaded()) { // Draw the level with lightmapping? if(m_lightmapactive && m_shaderactive) glUniform1i(m_uselightmap, 1); world->GetBSP()->RenderGL(frustum.pos, frustum); if(m_shaderactive) glUniform1i(m_uselightmap, 0); } // Draw every object for(iter=world->ObjBegin();iter!=world->ObjEnd();++iter) { obj = (*iter).second; if((obj->GetFlags() & OBJ_FLAGS_GHOST) || // ghosts are invisible - duh obj->GetID() == localctrlid || // don't draw the player object !obj->GetMesh()) // object has no md5 model continue; // check if object is in view frustum if(!generateShadowMap && !frustum.TestSphere(obj->GetOrigin(), obj->GetRadius())) continue; glPushMatrix(); glTranslatef(obj->GetOrigin().x, obj->GetOrigin().y, obj->GetOrigin().z); glTranslatef(0.0f, -obj->GetRadius(), 0.0f); glMultMatrixf(obj->GetRotMatrix()->pm); obj->GetMesh()->Render(obj->GetMeshState()); #ifdef DRAW_NORMALS obj->GetMesh()->RenderNormals(obj->GetMeshState()); // not implemented for md2s? #endif glPopMatrix(); } }
BOOL CActor::CanPickItem(const CFrustum& frustum, const Fvector& from, CObject* item) { BOOL bOverlaped = FALSE; Fvector dir,to; item->Center (to); float range = dir.sub(to,from).magnitude(); if (range>0.25f){ if (frustum.testSphere_dirty(to,item->Radius())){ dir.div (range); collide::ray_defs RD(from, dir, range, CDB::OPT_CULL, collide::rqtBoth); VERIFY (!fis_zero(RD.dir.square_magnitude())); RQR.r_clear (); Level().ObjectSpace.RayQuery(RQR,RD, info_trace_callback, &bOverlaped, NULL, item); } } return !bOverlaped; }
void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Reset The matrix // Position the camera g_Camera.Look(); // Each frame we calculate the new frustum. In reality you only need to // calculate the frustum when we move the camera. g_Frustum.CalculateFrustum(); // Initialize the total node count that is being draw per frame g_TotalNodesDrawn = 0; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Here we draw the octree, starting with the root node and recursing down each node. // This time, we pass in the root node and just the original world model. You could // just store the world in the root node and not have to keep the original data around. // This is up to you. I like this way better because it's easy, though it could be // more error prone. g_Octree.DrawOctree(&g_Octree, &g_World); // Render the cubed nodes to visualize the octree (in wire frame mode) if( g_bDisplayNodes ) g_Debug.RenderDebugLines(); // Create a buffer to store the octree information for the title bar static char strBuffer[255] = {0}; // Display in window mode the current subdivision information. We now display the // max triangles per node, the max level of subdivision, total end nodes, current nodes drawn // and frames per second we are receiving. sprintf(strBuffer, "Triangles: %d Subdivisions: %d EndNodes: %d NodesDraw: %d FPS: %s", g_MaxTriangles, g_MaxSubdivisions, g_EndNodeCount, g_TotalNodesDrawn, g_strFrameRate); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Set our window title bar to the subdivision information SetWindowText(g_hWnd, strBuffer); // Swap the backbuffers to the foreground SwapBuffers(g_hDC); }
void RenderScene() { int i = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The matrix // Tell OpenGL where to look from our camera info g_Camera.Look(); // Calculate our frustum to check the world data again for PVS and Portal Rendering g_Frustum.CalculateFrustum(); // Render the level to the screen g_Level.RenderLevel(g_Camera.Position()); // Swap the backbuffers to the foreground SwapBuffers(g_hDC); }
void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The matrix // Give OpenGL our camera position g_Camera.Look(); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Each frame we calculate the new frustum. In reality you only need to // calculate the frustum when we move the camera. g_Frustum.CalculateFrustum(); // Initialize the total node count that is being draw per frame g_TotalNodesDrawn = 0; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Here we draw the octree, starting with the root node and recursing down each node. // When we get to each of the end nodes we will draw the vertices assigned to them. g_Octree.DrawOctree(&g_Octree); // Render the cube'd nodes to visualize the octree (in wire frame mode) g_Debug.RenderDebugLines(); SwapBuffers(g_hDC); // Swap the backbuffers to the foreground char strBuffer[255] = {0}; // Create a character buffer // To view our octree information I set the window's title bar to the some basic // information such as the max triangles per node, the max subdivisions, // total end nodes and the total drawn end nodes that are currently in the frustum. // Display in window mode the current subdivision information sprintf(strBuffer, "MaxTriangles: %d MaxSubdivisions: %d TotalEndNodes: %d TotalNodesDraw: %d", g_MaxTriangles, g_MaxSubdivisions, g_EndNodeCount, g_TotalNodesDrawn); // Set our window title bar to the subdivision data SetWindowText(g_hWnd, strBuffer); }
void COLLIDER::frustum_query(const MODEL *m_def, const CFrustum& F) { m_def->syncronize (); // Get nodes const AABBNoLeafTree* T = (const AABBNoLeafTree*)m_def->tree->GetTree(); const AABBNoLeafNode* N = T->GetNodes(); const DWORD mask= F.getMask(); r_clear (); // Binary dispatcher if (frustum_mode&OPT_FULL_TEST) { if (frustum_mode&OPT_ONLYFIRST) { frustum_collider<true,true> BC; BC._init (this,m_def->verts,m_def->tris,&F); BC._stab (N,mask); } else { frustum_collider<true,false> BC; BC._init (this,m_def->verts,m_def->tris,&F); BC._stab (N,mask); } } else { if (frustum_mode&OPT_ONLYFIRST) { frustum_collider<false,true> BC; BC._init (this,m_def->verts,m_def->tris,&F); BC._stab (N,mask); } else { frustum_collider<false,false> BC; BC._init (this,m_def->verts,m_def->tris,&F); BC._stab (N,mask); } } }
void RenderScene() { /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * int spheresRendered = 0; // This will hold how many spheres are being rendered char strText[255]= {0}; // This will hold the window title info glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The matrix // Give OpenGL our camera position g_Camera.Look(); // We don't need to calculate this every frame, only when the camera view changes. // I just did it every frame anyway. In this case it isn't a big deal. g_Frustum.CalculateFrustum(); // Calculate the frustum each frame // If you are unfamiliar with Quadrics, see the tutorial on Quadrics at www.GameTutorials.com. // They basically allow you to draw circles and cylinders fast and easily. GLUquadricObj *pObj = gluNewQuadric(); // Get a Quadric off the stack // Loop through all of our allowed spheres and render them to the screen if in the frustum. for(int i = 0; i < g_MaxSpheres; i++) // g_MaxSpheres varies. { g_Spheres[i].zPos += SPHERE_SPEED; // Increase the Z position of the sphere. // Below we check if the sphere needs to be draw or not. If g_bIgnoreFrustum is TRUE, // it draws it regardless (which is SLOOOooOoW). We just pass in the (X, Y, Z) // and the radius of the sphere to find out if it is inside of the frustum. if(g_bIgnoreFrustum || g_Frustum.SphereInFrustum(g_Spheres[i].xPos, g_Spheres[i].yPos, g_Spheres[i].zPos, g_Spheres[i].radius)) { // Set the sphere's color glColor3ub(g_Spheres[i].r, g_Spheres[i].g, g_Spheres[i].b); // Create a new scope before positiong the sphere so we don't effect the other spheres. glPushMatrix(); // Position the sphere on the screen at it's XYZ position. glTranslatef(g_Spheres[i].xPos, g_Spheres[i].yPos, g_Spheres[i].zPos); // Create a sphere with the desired radius chosen in the beginning. gluSphere(pObj, g_Spheres[i].radius, 20, 20); // Draw the sphere with a radius of 0.5 glPopMatrix(); // Close the scope of this matrix spheresRendered++; // Increase the amount of spheres rendered } // Here we check to see if the sphere went out of our range, // If so, we need to set it back again with a new random position. if(g_Spheres[i].zPos > MAX_DISTANCE) { // Give the sphere a new random position back in the beginning. g_Spheres[i].xPos = (rand() % (MAX_DISTANCE * 10)) * 0.1f; g_Spheres[i].yPos = (rand() % (MAX_DISTANCE * 10)) * 0.1f; g_Spheres[i].zPos = -MAX_DISTANCE; // Send it to the back again. // Give a 50/50 chance for the sphere to be to the left/right or above/below the XY axis. // This is because we are centered at the origin if(rand() % 2) g_Spheres[i].xPos = -g_Spheres[i].xPos; if(rand() % 2) g_Spheres[i].yPos = -g_Spheres[i].yPos; } } // Since I didn't want to add more code for a rendered font, I decided to just // render the frustum information in the title bar of the window. // The information tells you how many spheres were rendered and out of how many. // Use +/- to increase and decrease the max spheres tested. sprintf(strText, "www.GameTutorials.com - Spheres Rendered: %d / %d", spheresRendered, g_MaxSpheres); SetWindowText(g_hWnd, strText); // Change the window title bar /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * SwapBuffers(g_hDC); // Swap the backbuffers to the foreground gluDeleteQuadric(pObj); // Free the Quadric }
void WaterManager::RenderWaves(const CFrustum& frustrum) { #if CONFIG2_GLES #warning Fix WaterManager::RenderWaves on GLES #else if (g_Renderer.m_SkipSubmit || !m_WaterFancyEffects) return; pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FancyEffectsFBO); GLuint attachments[2] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; pglDrawBuffers(2, attachments); glClearColor(0.0f,0.0f, 0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); CShaderDefines none; CShaderProgramPtr shad = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", none); shad->Bind(); shad->BindTexture(str_waveTex, m_WaveTex); shad->BindTexture(str_foamTex, m_FoamTex); shad->Uniform(str_time, (float)m_WaterTexTimer); shad->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection()); for (size_t a = 0; a < m_ShoreWaves.size(); ++a) { if (!frustrum.IsBoxVisible(m_ShoreWaves[a]->m_AABB)) continue; CVertexBuffer::VBChunk* VBchunk = m_ShoreWaves[a]->m_VBvertices; SWavesVertex* base = (SWavesVertex*)VBchunk->m_Owner->Bind(); // setup data pointers GLsizei stride = sizeof(SWavesVertex); shad->VertexPointer(3, GL_FLOAT, stride, &base[VBchunk->m_Index].m_BasePosition); shad->TexCoordPointer(GL_TEXTURE0, 2, GL_UNSIGNED_BYTE, stride, &base[VBchunk->m_Index].m_UV); // NormalPointer(gl_FLOAT, stride, &base[m_VBWater->m_Index].m_UV) pglVertexAttribPointerARB(2, 2, GL_FLOAT, GL_TRUE, stride, &base[VBchunk->m_Index].m_PerpVect); // replaces commented above because my normal is vec2 shad->VertexAttribPointer(str_a_apexPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_ApexPosition); shad->VertexAttribPointer(str_a_splashPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_SplashPosition); shad->VertexAttribPointer(str_a_retreatPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_RetreatPosition); shad->AssertPointersBound(); shad->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff); shad->Uniform(str_width, (int)m_ShoreWaves[a]->m_Width); u8* indexBase = m_ShoreWaves_VBIndices->m_Owner->Bind(); glDrawElements(GL_TRIANGLES, (GLsizei) (m_ShoreWaves[a]->m_Width-1)*(7*6), GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_ShoreWaves_VBIndices->m_Index)); shad->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff + 6.0f); // TODO: figure out why this doesn't work. //g_Renderer.m_Stats.m_DrawCalls++; //g_Renderer.m_Stats.m_WaterTris += m_ShoreWaves_VBIndices->m_Count / 3; CVertexBuffer::Unbind(); } shad->Unbind(); pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); #endif }
////////////////////////////////////////////////////////////////////////// // sub-space rendering - shortcut to render with frustum extracted from matrix void R_dsgraph_structure::r_dsgraph_render_subspace (IRender_Sector* _sector, Fmatrix& mCombined, Fvector& _cop, BOOL _dynamic, BOOL _precise_portals) { CFrustum temp; temp.CreateFromMatrix (mCombined, FRUSTUM_P_ALL); r_dsgraph_render_subspace (_sector,&temp,mCombined,_cop,_dynamic,_precise_portals); }