diff --git a/src/xrEngine/Frustum.cpp b/src/xrEngine/Frustum.cpp deleted file mode 100644 index a9d798774c1..00000000000 --- a/src/xrEngine/Frustum.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include "stdafx.h" -#pragma hdrstop - -#include "Frustum.h" - -////////////////////////////////////////////////////////////////////// -void CFrustum::fplane::cache() -{ - if (positive(n.x)) - { - if (positive(n.y)) - { - if (positive(n.z)) aabb_overlap_id = 0; - else aabb_overlap_id = 1; - } - else - { - if (positive(n.z)) aabb_overlap_id = 2; - else aabb_overlap_id = 3; - } - } - else - { - if (positive(n.y)) - { - if (positive(n.z)) aabb_overlap_id = 4; - else aabb_overlap_id = 5; - } - else - { - if (positive(n.z)) aabb_overlap_id = 6; - else aabb_overlap_id = 7; - } - } -} -void CFrustum::_add(Fplane& P) -{ - VERIFY(p_count < FRUSTUM_MAXPLANES); - planes[p_count].set(P); - planes[p_count].cache(); - p_count++; -} -void CFrustum::_add(Fvector& P1, Fvector& P2, Fvector& P3) -{ - VERIFY(p_count < FRUSTUM_MAXPLANES); - planes[p_count].build_precise(P1, P2, P3); - planes[p_count].cache(); - p_count++; -} - -#define mx 0 -#define my 1 -#define mz 2 -#define Mx 3 -#define My 4 -#define Mz 5 -u32 frustum_aabb_remap[8][6] = -{ - {Mx, My, Mz, mx, my, mz}, - {Mx, My, mz, mx, my, Mz}, - {Mx, my, Mz, mx, My, mz}, - {Mx, my, mz, mx, My, Mz}, - {mx, My, Mz, Mx, my, mz}, - {mx, My, mz, Mx, my, Mz}, - {mx, my, Mz, Mx, My, mz}, - {mx, my, mz, Mx, My, Mz} -}; - -////////////////////////////////////////////////////////////////////// -EFC_Visible CFrustum::testSphere(Fvector& c, float r, u32& test_mask) const -{ - u32 bit = 1; - for (int i = 0; i < p_count; i++, bit <<= 1) - { - if (test_mask&bit) - { - float cls = planes[i].classify(c); - if (cls > r) { test_mask = 0; return fcvNone; } // none - return - if (_abs(cls) >= r) test_mask &= ~bit; // fully - no need to test this plane - } - } - return test_mask ? fcvPartial : fcvFully; -} - -BOOL CFrustum::testSphere_dirty(Fvector& c, float r) const -{ - switch (p_count) - { - case 12: - if (planes[11].classify(c) > r) return FALSE; - case 11: - if (planes[10].classify(c) > r) return FALSE; - case 10: - if (planes[9].classify(c) > r) return FALSE; - case 9: - if (planes[8].classify(c) > r) return FALSE; - case 8: - if (planes[7].classify(c) > r) return FALSE; - case 7: - if (planes[6].classify(c) > r) return FALSE; - case 6: - if (planes[5].classify(c) > r) return FALSE; - case 5: - if (planes[4].classify(c) > r) return FALSE; - case 4: - if (planes[3].classify(c) > r) return FALSE; - case 3: - if (planes[2].classify(c) > r) return FALSE; - case 2: - if (planes[1].classify(c) > r) return FALSE; - case 1: - if (planes[0].classify(c) > r) return FALSE; - case 0: - break; - default: - NODEFAULT; - } - return TRUE; -} - -EFC_Visible CFrustum::testAABB(const float* mM, u32& test_mask) const -{ - // go for trivial rejection or acceptance using "faster overlap test" - u32 bit = 1; - - for (int i = 0; i < p_count; i++, bit <<= 1) - { - if (test_mask&bit) - { - EFC_Visible r = AABB_OverlapPlane(planes[i], mM); - if (fcvFully == r) test_mask &= ~bit; // fully - no need to test this plane - else if (fcvNone == r) { test_mask = 0; return fcvNone; } // none - return - } - } - return test_mask ? fcvPartial : fcvFully; -} - -EFC_Visible CFrustum::testSAABB(Fvector& c, float r, const float* mM, u32& test_mask) const -{ - u32 bit = 1; - for (int i = 0; i < p_count; i++, bit <<= 1) - { - if (test_mask&bit) - { - float cls = planes[i].classify(c); - if (cls > r) { test_mask = 0; return fcvNone; } // none - return - if (_abs(cls) >= r) test_mask &= ~bit; // fully - no need to test this plane - else - { - EFC_Visible r = AABB_OverlapPlane(planes[i], mM); - if (fcvFully == r) test_mask &= ~bit; // fully - no need to test this plane - else if (fcvNone == r) { test_mask = 0; return fcvNone; } // none - return - } - } - } - return test_mask ? fcvPartial : fcvFully; -} - -BOOL CFrustum::testPolyInside_dirty(Fvector* p, int count) const -{ - Fvector* e = p + count; - for (int i = 0; i < p_count; i++) - { - const fplane& P = planes[i]; - for (Fvector* I = p; I != e; I++) - if (P.classify(*I) > 0) return false; - } - return true; -} - -////////////////////////////////////////////////////////////////////// -void CFrustum::CreateFromPoints(Fvector* p, int count, Fvector& COP) -{ - VERIFY(count < FRUSTUM_MAXPLANES); - VERIFY(count >= 3); - - _clear(); - for (int i = 1; i < count; i++) - _add(COP, p[i - 1], p[i]); - _add(COP, p[count - 1], p[0]); -} - -void CFrustum::CreateFromPlanes(Fplane* p, int count) -{ - for (int k = 0; k < count; k++) - planes[k].set(p[k]); - - for (int i = 0; i < count; i++) - { - float denom = 1.0f / planes[i].n.magnitude();// Get magnitude of Vector - planes[i].n.x *= denom; - planes[i].n.y *= denom; - planes[i].n.z *= denom; - planes[i].d *= denom; - planes[i].cache(); - } - - p_count = count; -} - -void CFrustum::CreateFromPortal(sPoly* poly, Fvector& vPN, Fvector& vBase, Fmatrix& mFullXFORM) -{ - Fplane P; - P.build_precise((*poly)[0], (*poly)[1], (*poly)[2]); - - if (poly->size()>6) - { - SimplifyPoly_AABB(poly, P); - P.build_precise((*poly)[0], (*poly)[1], (*poly)[2]); - } - - // Check plane orientation relative to viewer - // and reverse if needed - if (P.classify(vBase) < 0) - { - std::reverse(poly->begin(), poly->end()); - P.build_precise((*poly)[0], (*poly)[1], (*poly)[2]); - } - - // Base creation - CreateFromPoints(poly->begin(), poly->size(), vBase); - - // Near clipping plane - _add(P); - - // Far clipping plane - Fmatrix& M = mFullXFORM; - P.n.x = -(M._14 - M._13); - P.n.y = -(M._24 - M._23); - P.n.z = -(M._34 - M._33); - P.d = -(M._44 - M._43); - float denom = 1.0f / P.n.magnitude(); - P.n.x *= denom; - P.n.y *= denom; - P.n.z *= denom; - P.d *= denom; - _add(P); -} - -void CFrustum::SimplifyPoly_AABB(sPoly* poly, Fplane& plane) -{ - Fmatrix mView, mInv; - Fvector from, up, right, y; - from.set((*poly)[0]); - y.set(0, 1, 0); - if (_abs(plane.n.y) > 0.99f) y.set(1, 0, 0); - right.crossproduct(y, plane.n); - up.crossproduct(plane.n, right); - mView.build_camera_dir(from, plane.n, up); - - // Project and find extents - Fvector2 min, max; - min.set(flt_max, flt_max); - max.set(flt_min, flt_min); - for (u32 i = 0; i < poly->size(); i++) - { - Fvector2 tmp; - mView.transform_tiny32(tmp, (*poly)[i]); - min.min(tmp.x, tmp.y); - max.max(tmp.x, tmp.y); - } - - // Build other 2 points and inverse project - Fvector2 p1, p2; - p1.set(min.x, max.y); - p2.set(max.x, min.y); - mInv.invert(mView); - poly->clear(); - - mInv.transform_tiny23(poly->last(), min); - poly->inc(); - mInv.transform_tiny23(poly->last(), p1); - poly->inc(); - mInv.transform_tiny23(poly->last(), max); - poly->inc(); - mInv.transform_tiny23(poly->last(), p2); - poly->inc(); -} - -void CFrustum::CreateOccluder(Fvector* p, int count, Fvector& vBase, CFrustum& clip) -{ - VERIFY(count < FRUSTUM_SAFE); - VERIFY(count >= 3); - - BOOL edge[FRUSTUM_SAFE]; - float cls[FRUSTUM_SAFE]; - ZeroMemory(edge, sizeof(edge)); - for (int i = 0; i < clip.p_count; i++) - { - // classify all points relative to plane #i - fplane& P = clip.planes[i]; - for (int j = 0; j < count; j++) cls[j] = _abs(P.classify(p[j])); - - // test edges to see which lies directly on plane - for (j = 0; j < count; j++) - { - if (cls[j] < EPS_L) - { - int next = j + 1; - if (next >= count) next = 0; - if (cls[next] < EPS_L) - { - // both points lies on plane - mark as 'open' - edge[j] = true; - } - } - } - } - - // here we have all edges marked accordenly to 'open' / 'closed' classification - _clear(); - _add(p[0], p[1], p[2]); // main plane - for (i = 0; i < count; i++) - { - if (!edge[i]) - { - int next = i + 1; - if (next >= count) next = 0; - _add(vBase, p[i], p[next]); - } - } -} - -sPoly* CFrustum::ClipPoly(sPoly& S, sPoly& D) const -{ - sPoly* src = &D; - sPoly* dest = &S; - for (int i = 0; i < p_count; i++) - { - // cache plane and swap lists - const fplane& P = planes[i]; - std::swap(src, dest); - dest->clear(); - - // classify all points relative to plane #i - float cls[FRUSTUM_SAFE]; - for (u32 j = 0; j < src->size(); j++) cls[j] = P.classify((*src)[j]); - - // clip everything to this plane - cls[src->size()] = cls[0]; - src->push_back((*src)[0]); - Fvector D; - float denum, t; - for (j = 0; j < src->size() - 1; j++) - { - if ((*src)[j].similar((*src)[j + 1], EPS_S)) continue; - - if (negative(cls[j])) - { - dest->push_back((*src)[j]); - if (positive(cls[j + 1])) - { - // segment intersects plane - D.sub((*src)[j + 1], (*src)[j]); - denum = P.n.dotproduct(D); - if (denum != 0) - { - t = -cls[j] / denum; //VERIFY(t<=1.f && t>=0); - dest->last().mad((*src)[j], D, t); - dest->inc(); - } - } - } - else - { - // J - outside - if (negative(cls[j + 1])) - { - // J+1 - inside - // segment intersects plane - D.sub((*src)[j + 1], (*src)[j]); - denum = P.n.dotproduct(D); - if (denum != 0) - { - t = -cls[j] / denum; //VERIFY(t<=1.f && t>=0); - dest->last().mad((*src)[j], D, t); - dest->inc(); - } - } - } - } - - // here we end up with complete polygon in 'dest' which is inside plane #i - if (dest->size() < 3) return 0; - } - return dest; -} - -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 CFrustum::CreateFromMatrix(Fmatrix& M, u32 mask) -{ - VERIFY(_valid(M)); - p_count = 0; - - // Left clipping plane - if (mask&FRUSTUM_P_LEFT) - { - planes[p_count].n.x = -(M._14 + M._11); - planes[p_count].n.y = -(M._24 + M._21); - planes[p_count].n.z = -(M._34 + M._31); - planes[p_count].d = -(M._44 + M._41); - p_count++; - } - - // Right clipping plane - if (mask&FRUSTUM_P_RIGHT) - { - planes[p_count].n.x = -(M._14 - M._11); - planes[p_count].n.y = -(M._24 - M._21); - planes[p_count].n.z = -(M._34 - M._31); - planes[p_count].d = -(M._44 - M._41); - p_count++; - } - - // Top clipping plane - if (mask&FRUSTUM_P_TOP) - { - planes[p_count].n.x = -(M._14 - M._12); - planes[p_count].n.y = -(M._24 - M._22); - planes[p_count].n.z = -(M._34 - M._32); - planes[p_count].d = -(M._44 - M._42); - p_count++; - } - - // Bottom clipping plane - if (mask&FRUSTUM_P_BOTTOM) - { - planes[p_count].n.x = -(M._14 + M._12); - planes[p_count].n.y = -(M._24 + M._22); - planes[p_count].n.z = -(M._34 + M._32); - planes[p_count].d = -(M._44 + M._42); - p_count++; - } - - // Far clipping plane - if (mask&FRUSTUM_P_FAR) - { - planes[p_count].n.x = -(M._14 - M._13); - planes[p_count].n.y = -(M._24 - M._23); - planes[p_count].n.z = -(M._34 - M._33); - planes[p_count].d = -(M._44 - M._43); - p_count++; - } - - // Near clipping plane - if (mask&FRUSTUM_P_NEAR) - { - planes[p_count].n.x = -(M._14 + M._13); - planes[p_count].n.y = -(M._24 + M._23); - planes[p_count].n.z = -(M._34 + M._33); - planes[p_count].d = -(M._44 + M._43); - p_count++; - } - - for (int i = 0; i < p_count; i++) - { - float denom = 1.0f / planes[i].n.magnitude();// Get magnitude of Vector - planes[i].n.x *= denom; - planes[i].n.y *= denom; - planes[i].n.z *= denom; - planes[i].d *= denom; - planes[i].cache(); - } -} diff --git a/src/xrEngine/Frustum.h b/src/xrEngine/Frustum.h deleted file mode 100644 index 4cd4bef58a9..00000000000 --- a/src/xrEngine/Frustum.h +++ /dev/null @@ -1,100 +0,0 @@ -// Frustum.h: interface for the CFrustum class. -// -////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_FRUSTUM_H__E66ED755_F741_49CF_8B2A_404CCF7067F2__INCLUDED_) -#define AFX_FRUSTUM_H__E66ED755_F741_49CF_8B2A_404CCF7067F2__INCLUDED_ -#pragma once - -#include "../xrcore/fixedvector.h" - -#pragma pack(push,4) - -enum EFC_Visible -{ - fcvNone = 0, - fcvPartial, - fcvFully, - fcv_forcedword = u32(-1) -}; - -#define FRUSTUM_MAXPLANES 12 -#define FRUSTUM_P_LEFT (1<<0) -#define FRUSTUM_P_RIGHT (1<<1) -#define FRUSTUM_P_TOP (1<<2) -#define FRUSTUM_P_BOTTOM (1<<3) -#define FRUSTUM_P_NEAR (1<<4) -#define FRUSTUM_P_FAR (1<<5) - -#define FRUSTUM_P_LRTB (FRUSTUM_P_LEFT|FRUSTUM_P_RIGHT|FRUSTUM_P_TOP|FRUSTUM_P_BOTTOM) -#define FRUSTUM_P_ALL (FRUSTUM_P_LRTB|FRUSTUM_P_NEAR|FRUSTUM_P_FAR) - -#define FRUSTUM_SAFE (FRUSTUM_MAXPLANES*4) -typedef svector sPoly; -ENGINE_API extern u32 frustum_aabb_remap[8][6]; - -class ENGINE_API CFrustum -{ -public: - struct fplane : public Fplane - { - u32 aabb_overlap_id; // [0..7] - void cache(); - }; - fplane planes[FRUSTUM_MAXPLANES]; - int p_count; - -public: - ICF EFC_Visible AABB_OverlapPlane(const fplane& P, const float* mM) const - { - // calc extreme pts (neg,pos) along normal axis (pos in dir of norm, etc.) - u32* id = frustum_aabb_remap[P.aabb_overlap_id]; - - Fvector Neg; - Neg.set(mM[id[3]], mM[id[4]], mM[id[5]]); - if (P.classify(Neg) > 0) return fcvNone; - - Fvector Pos; - Pos.set(mM[id[0]], mM[id[1]], mM[id[2]]); - if (P.classify(Pos) <= 0) return fcvFully; - - return fcvPartial; - } -public: - IC void _clear() { p_count = 0; } - void _add(Fplane& P); - void _add(Fvector& P1, Fvector& P2, Fvector& P3); - - void SimplifyPoly_AABB(sPoly* P, Fplane& plane); - - void CreateOccluder(Fvector* p, int count, Fvector& vBase, CFrustum& clip); - BOOL CreateFromClipPoly(Fvector* p, int count, Fvector& vBase, CFrustum& clip); // returns 'false' if creation failed - void CreateFromPoints(Fvector* p, int count, Fvector& vBase); - void CreateFromMatrix(Fmatrix& M, u32 mask); - void CreateFromPortal(sPoly* P, Fvector& vPN, Fvector& vBase, Fmatrix& mFullXFORM); - void CreateFromPlanes(Fplane* p, int count); - - sPoly* ClipPoly(sPoly& src, sPoly& dest) const; - - u32 getMask() const { return (1 << p_count) - 1; } - - EFC_Visible testSphere(Fvector& c, float r, u32& test_mask) const; - BOOL testSphere_dirty(Fvector& c, float r) const; - EFC_Visible testAABB(const float* mM, u32& test_mask) const; - EFC_Visible testSAABB(Fvector& c, float r, const float* mM, u32& test_mask) const; - BOOL testPolyInside_dirty(Fvector* p, int count) const; - - IC BOOL testPolyInside(sPoly& src) const - { - sPoly d; - return !!ClipPoly(src, d); - } - IC BOOL testPolyInside(Fvector* p, int count) const - { - sPoly src(p, count); - return testPolyInside(src); - } -}; -#pragma pack(pop) - -#endif // !defined(AFX_FRUSTUM_H__E66ED755_F741_49CF_8B2A_404CCF7067F2__INCLUDED_) diff --git a/src/xrEngine/ISpatial.cpp b/src/xrEngine/ISpatial.cpp deleted file mode 100644 index 6a868bccf2f..00000000000 --- a/src/xrEngine/ISpatial.cpp +++ /dev/null @@ -1,346 +0,0 @@ -#include "stdafx.h" -#include "ispatial.h" -#include "render.h" -#include "xr_object.h" -#include "PS_Instance.h" - -ENGINE_API ISpatial_DB* g_SpatialSpace = NULL; -ENGINE_API ISpatial_DB* g_SpatialSpacePhysic = NULL; - -Fvector c_spatial_offset[8] = -{ - {-1, -1, -1}, - {1, -1, -1}, - {-1, 1, -1}, - {1, 1, -1}, - {-1, -1, 1}, - {1, -1, 1}, - {-1, 1, 1}, - {1, 1, 1} -}; - -////////////////////////////////////////////////////////////////////////// -ISpatial::ISpatial(ISpatial_DB* space) -{ - spatial.sphere.P.set(0, 0, 0); - spatial.sphere.R = 0; - spatial.node_center.set(0, 0, 0); - spatial.node_radius = 0; - spatial.node_ptr = NULL; - spatial.sector = NULL; - spatial.space = space; -} -ISpatial::~ISpatial(void) -{ - spatial_unregister(); -} -BOOL ISpatial::spatial_inside() -{ - float dr = -(-spatial.node_radius + spatial.sphere.R); - if (spatial.sphere.P.x < spatial.node_center.x - dr) return FALSE; - if (spatial.sphere.P.x > spatial.node_center.x + dr) return FALSE; - if (spatial.sphere.P.y < spatial.node_center.y - dr) return FALSE; - if (spatial.sphere.P.y > spatial.node_center.y + dr) return FALSE; - if (spatial.sphere.P.z < spatial.node_center.z - dr) return FALSE; - if (spatial.sphere.P.z > spatial.node_center.z + dr) return FALSE; - return TRUE; -} - -BOOL verify_sp(ISpatial* sp, Fvector& node_center, float node_radius) -{ - float dr = -(-node_radius + sp->spatial.sphere.R); - if (sp->spatial.sphere.P.x < node_center.x - dr) return FALSE; - if (sp->spatial.sphere.P.x > node_center.x + dr) return FALSE; - if (sp->spatial.sphere.P.y < node_center.y - dr) return FALSE; - if (sp->spatial.sphere.P.y > node_center.y + dr) return FALSE; - if (sp->spatial.sphere.P.z < node_center.z - dr) return FALSE; - if (sp->spatial.sphere.P.z > node_center.z + dr) return FALSE; - return TRUE; -} - -void ISpatial::spatial_register() -{ - spatial.type |= STYPEFLAG_INVALIDSECTOR; - if (spatial.node_ptr) - { - // already registered - nothing to do - } - else - { - // register - R_ASSERT(spatial.space); - spatial.space->insert(this); - spatial.sector = 0; - } -} - -void ISpatial::spatial_unregister() -{ - if (spatial.node_ptr) - { - // remove - spatial.space->remove(this); - spatial.node_ptr = NULL; - spatial.sector = NULL; - } - else - { - // already unregistered - } -} - -void ISpatial::spatial_move() -{ - if (spatial.node_ptr) - { - //*** somehow it was determined that object has been moved - spatial.type |= STYPEFLAG_INVALIDSECTOR; - - //*** check if we are supposed to correct it's spatial location - if (spatial_inside()) return; // ??? - spatial.space->remove(this); - spatial.space->insert(this); - } - else - { - //*** we are not registered yet, or already unregistered - //*** ignore request - } -} - -void ISpatial::spatial_updatesector_internal() -{ - IRender_Sector* S = ::Render->detectSector(spatial_sector_point()); - spatial.type &= ~STYPEFLAG_INVALIDSECTOR; - if (S) spatial.sector = S; -} - -////////////////////////////////////////////////////////////////////////// -void ISpatial_NODE::_init(ISpatial_NODE* _parent) -{ - parent = _parent; - children[0] = children[1] = children[2] = children[3] = - children[4] = children[5] = children[6] = children[7] = NULL; - items.clear(); -} - -void ISpatial_NODE::_insert(ISpatial* S) -{ - S->spatial.node_ptr = this; - items.push_back(S); - S->spatial.space->stat_objects++; -} - -void ISpatial_NODE::_remove(ISpatial* S) -{ - S->spatial.node_ptr = NULL; - xr_vector::iterator it = std::find(items.begin(), items.end(), S); - VERIFY(it != items.end()); - items.erase(it); - S->spatial.space->stat_objects--; -} - -////////////////////////////////////////////////////////////////////////// - -ISpatial_DB::ISpatial_DB() -#ifdef PROFILE_CRITICAL_SECTIONS - :cs(MUTEX_PROFILE_ID(ISpatial_DB)) -#endif // PROFILE_CRITICAL_SECTIONS -{ - m_root = NULL; - stat_nodes = 0; - stat_objects = 0; -} - -ISpatial_DB::~ISpatial_DB() -{ - if (m_root) - { - _node_destroy(m_root); - } - - while (!allocator_pool.empty()) - { - allocator.destroy(allocator_pool.back()); - allocator_pool.pop_back(); - } -} - -void ISpatial_DB::initialize(Fbox& BB) -{ - if (0 == m_root) - { - // initialize - Fvector bbc, bbd; - BB.get_CD(bbc, bbd); - - bbc.set(0, 0, 0); // generic - bbd.set(1024, 1024, 1024); // generic - - allocator_pool.reserve(128); - m_center.set(bbc); - m_bounds = _max(_max(bbd.x, bbd.y), bbd.z); - rt_insert_object = NULL; - if (0 == m_root) m_root = _node_create(); - m_root->_init(NULL); - } -} -ISpatial_NODE* ISpatial_DB::_node_create() -{ - stat_nodes++; - if (allocator_pool.empty()) return allocator.create(); - else - { - ISpatial_NODE* N = allocator_pool.back(); - allocator_pool.pop_back(); - return N; - } -} -void ISpatial_DB::_node_destroy(ISpatial_NODE*& P) -{ - VERIFY(P->_empty()); - stat_nodes--; - allocator_pool.push_back(P); - P = NULL; -} - -void ISpatial_DB::_insert(ISpatial_NODE* N, Fvector& n_C, float n_R) -{ - //*** we are assured that object lives inside our node - float n_vR = 2 * n_R; - VERIFY(N); - VERIFY(verify_sp(rt_insert_object, n_C, n_vR)); - - // we have to make sure we aren't the leaf node - if (n_R <= c_spatial_min) - { - // this is leaf node - N->_insert(rt_insert_object); - rt_insert_object->spatial.node_center.set(n_C); - rt_insert_object->spatial.node_radius = n_vR; // vR - return; - } - - // we have to check if it can be putted further down - float s_R = rt_insert_object->spatial.sphere.R; // spatial bounds - float c_R = n_R / 2; // children bounds - if (s_R < c_R) - { - // object can be pushed further down - select "octant", calc node position - Fvector& s_C = rt_insert_object->spatial.sphere.P; - u32 octant = _octant(n_C, s_C); - Fvector c_C; - c_C.mad(n_C, c_spatial_offset[octant], c_R); - VERIFY(octant == _octant(n_C, c_C)); // check table assosiations - ISpatial_NODE*& chield = N->children[octant]; - - if (0 == chield) - { - chield = _node_create(); - VERIFY(chield); - chield->_init(N); - VERIFY(chield); - } - VERIFY(chield); - _insert(chield, c_C, c_R); - VERIFY(chield); - } - else - { - // we have to "own" this object (potentially it can be putted down sometimes...) - N->_insert(rt_insert_object); - rt_insert_object->spatial.node_center.set(n_C); - rt_insert_object->spatial.node_radius = n_vR; - } -} - -void ISpatial_DB::insert(ISpatial* S) -{ - cs.Enter(); -#ifdef DEBUG - stat_insert.Begin(); - - BOOL bValid = _valid(S->spatial.sphere.R) && _valid(S->spatial.sphere.P); - if (!bValid) - { - CObject* O = dynamic_cast(S); - if (O) Debug.fatal(DEBUG_INFO, "Invalid OBJECT position or radius (%s)", O->cName()); - else - { - CPS_Instance* P = dynamic_cast(S); - if (P) Debug.fatal(DEBUG_INFO, "Invalid PS spatial position{%3.2f,%3.2f,%3.2f} or radius{%3.2f}", VPUSH(S->spatial.sphere.P), S->spatial.sphere.R); - else Debug.fatal(DEBUG_INFO, "Invalid OTHER spatial position{%3.2f,%3.2f,%3.2f} or radius{%3.2f}", VPUSH(S->spatial.sphere.P), S->spatial.sphere.R); - } - } -#endif - - if (verify_sp(S, m_center, m_bounds)) - { - // Object inside our DB - rt_insert_object = S; - _insert(m_root, m_center, m_bounds); - VERIFY(S->spatial_inside()); - } - else - { - // Object outside our DB, put it into root node and hack bounds - // Object will reinsert itself until fits into "real", "controlled" space - m_root->_insert(S); - S->spatial.node_center.set(m_center); - S->spatial.node_radius = m_bounds; - } -#ifdef DEBUG - stat_insert.End(); -#endif - cs.Leave(); -} - -void ISpatial_DB::_remove(ISpatial_NODE* N, ISpatial_NODE* N_sub) -{ - if (0 == N) return; - - //*** we are assured that node contains N_sub and this subnode is empty - u32 octant = u32(-1); - if (N_sub == N->children[0]) octant = 0; - else if (N_sub == N->children[1]) octant = 1; - else if (N_sub == N->children[2]) octant = 2; - else if (N_sub == N->children[3]) octant = 3; - else if (N_sub == N->children[4]) octant = 4; - else if (N_sub == N->children[5]) octant = 5; - else if (N_sub == N->children[6]) octant = 6; - else if (N_sub == N->children[7]) octant = 7; - VERIFY(octant < 8); - VERIFY(N_sub->_empty()); - _node_destroy(N->children[octant]); - - // Recurse - if (N->_empty()) _remove(N->parent, N); -} - -void ISpatial_DB::remove(ISpatial* S) -{ - cs.Enter(); -#ifdef DEBUG - stat_remove.Begin(); -#endif - ISpatial_NODE* N = S->spatial.node_ptr; - N->_remove(S); - - // Recurse - if (N->_empty()) _remove(N->parent, N); - -#ifdef DEBUG - stat_remove.End(); -#endif - cs.Leave(); -} - -void ISpatial_DB::update(u32 nodes/* =8 */) -{ -#ifdef DEBUG - if (0 == m_root) return; - cs.Enter(); - VERIFY(verify()); - cs.Leave(); -#endif -} diff --git a/src/xrEngine/ISpatial.h b/src/xrEngine/ISpatial.h deleted file mode 100644 index 6f9c148e5c9..00000000000 --- a/src/xrEngine/ISpatial.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef XRENGINE_ISPATIAL_H_INCLUDED -#define XRENGINE_ISPATIAL_H_INCLUDED - -#pragma once - -#include "../xrcore/xrPool.h" -#include "xr_collide_defs.h" - -#pragma pack(push,4) - -/* -Requirements: -0. Generic -* O(1) insertion -- radius completely determines "level" -- position completely detemines "node" -* O(1) removal -* -1. Rendering -* Should live inside spatial DB -* Should have at least "bounding-sphere" or "bounding-box" -* Should have pointer to "sector" it lives in -* Approximate traversal order relative to point ("camera") -2. Spatial queries -* Should live inside spatial DB -* Should have at least "bounding-sphere" or "bounding-box" -*/ - -const float c_spatial_min = 8.f; -////////////////////////////////////////////////////////////////////////// -enum -{ - STYPE_RENDERABLE = (1 << 0), - STYPE_LIGHTSOURCE = (1 << 1), - STYPE_COLLIDEABLE = (1 << 2), - STYPE_VISIBLEFORAI = (1 << 3), - STYPE_REACTTOSOUND = (1 << 4), - STYPE_PHYSIC = (1 << 5), - STYPE_OBSTACLE = (1 << 6), - STYPE_SHAPE = (1 << 7), - STYPE_LIGHTSOURCEHEMI = (1 << 8), - - STYPEFLAG_INVALIDSECTOR = (1 << 16) -}; -////////////////////////////////////////////////////////////////////////// -// Comment: -// ordinal objects - renderable?, collideable?, visibleforAI? -// physical-decorations - renderable, collideable -// lights - lightsource -// particles(temp-objects) - renderable -// glow - renderable -// sound - ??? -////////////////////////////////////////////////////////////////////////// -class ENGINE_API IRender_Sector; -class ENGINE_API ISpatial; -class ENGINE_API ISpatial_NODE; -class ENGINE_API ISpatial_DB; - -////////////////////////////////////////////////////////////////////////// -// Fast type conversion -class ENGINE_API CObject; -class ENGINE_API IRenderable; -class ENGINE_API IRender_Light; -namespace Feel { class ENGINE_API Sound; } - -////////////////////////////////////////////////////////////////////////// -class ENGINE_API ISpatial -{ -public: - struct _spatial - { - u32 type; - Fsphere sphere; - Fvector node_center; // Cached node center for TBV optimization - float node_radius; // Cached node bounds for TBV optimization - ISpatial_NODE* node_ptr; // Cached parent node for "empty-members" optimization - IRender_Sector* sector; - ISpatial_DB* space; // allow different spaces - - _spatial() : type(0) {} // safe way to enhure type is zero before any contstructors takes place - } spatial; -public: - BOOL spatial_inside(); - void spatial_updatesector_internal(); -public: - virtual void spatial_register(); - virtual void spatial_unregister(); - virtual void spatial_move(); - virtual Fvector spatial_sector_point() { return spatial.sphere.P; } - ICF void spatial_updatesector() - { - if (0 == (spatial.type&STYPEFLAG_INVALIDSECTOR)) return; - spatial_updatesector_internal(); - }; - - virtual CObject* dcast_CObject() { return 0; } - virtual Feel::Sound* dcast_FeelSound() { return 0; } - virtual IRenderable* dcast_Renderable() { return 0; } - virtual IRender_Light* dcast_Light() { return 0; } - - ISpatial(ISpatial_DB* space); - virtual ~ISpatial(); -}; - -////////////////////////////////////////////////////////////////////////// -class ENGINE_API ISpatial_NODE -{ -public: - typedef _W64 unsigned ptrt; -public: - ISpatial_NODE* parent; // parent node for "empty-members" optimization - ISpatial_NODE* children[8]; // children nodes - xr_vector items; // own items -public: - void _init(ISpatial_NODE* _parent); - void _remove(ISpatial* _S); - void _insert(ISpatial* _S); - BOOL _empty() - { - return items.empty() && ( - 0 == ( - ptrt(children[0]) | ptrt(children[1]) | - ptrt(children[2]) | ptrt(children[3]) | - ptrt(children[4]) | ptrt(children[5]) | - ptrt(children[6]) | ptrt(children[7]) - ) - ); - } -}; - -////////////////////////////////////////////////////////////////////////// -class ENGINE_API ISpatial_DB -{ -private: - xrCriticalSection cs; - poolSS allocator; - xr_vector allocator_pool; - ISpatial* rt_insert_object; -public: - ISpatial_NODE* m_root; - Fvector m_center; - float m_bounds; - xr_vector* q_result; - u32 stat_nodes; - u32 stat_objects; - CStatTimer stat_insert; - CStatTimer stat_remove; -private: - IC u32 _octant(u32 x, u32 y, u32 z) { return z * 4 + y * 2 + x; } - IC u32 _octant(Fvector& base, Fvector& rel) - { - u32 o = 0; - if (rel.x > base.x) o += 1; - if (rel.y > base.y) o += 2; - if (rel.z > base.z) o += 4; - return o; - } - - ISpatial_NODE* _node_create(); - void _node_destroy(ISpatial_NODE*& P); - - void _insert(ISpatial_NODE* N, Fvector& n_center, float n_radius); - void _remove(ISpatial_NODE* N, ISpatial_NODE* N_sub); -public: - ISpatial_DB(); - ~ISpatial_DB(); - - // managing - void initialize(Fbox& BB); - //void destroy (); - void insert(ISpatial* S); - void remove(ISpatial* S); - void update(u32 nodes = 8); - BOOL verify(); - -public: - enum - { - O_ONLYFIRST = (1 << 0), - O_ONLYNEAREST = (1 << 1), - O_ORDERED = (1 << 2), - O_force_u32 = u32(-1) - }; - - // query - void q_ray(xr_vector& R, u32 _o, u32 _mask_and, const Fvector& _start, const Fvector& _dir, float _range); - void q_box(xr_vector& R, u32 _o, u32 _mask_or, const Fvector& _center, const Fvector& _size); - void q_sphere(xr_vector& R, u32 _o, u32 _mask_or, const Fvector& _center, const float _radius); - void q_frustum(xr_vector& R, u32 _o, u32 _mask_or, const CFrustum& _frustum); -}; - -ENGINE_API extern ISpatial_DB* g_SpatialSpace; -ENGINE_API extern ISpatial_DB* g_SpatialSpacePhysic; - -#pragma pack(pop) - -#endif // #ifndef XRENGINE_ISPATIAL_H_INCLUDED \ No newline at end of file diff --git a/src/xrEngine/ISpatial_q_box.cpp b/src/xrEngine/ISpatial_q_box.cpp deleted file mode 100644 index f7e36e559f9..00000000000 --- a/src/xrEngine/ISpatial_q_box.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "stdafx.h" -#include "ISpatial.h" - -extern Fvector c_spatial_offset[8]; - -template -class walker -{ -public: - u32 mask; - Fvector center; - Fvector size; - Fbox box; - ISpatial_DB* space; -public: - walker(ISpatial_DB* _space, u32 _mask, const Fvector& _center, const Fvector& _size) - { - mask = _mask; - center = _center; - size = _size; - box.setb(center, size); - space = _space; - } - void walk(ISpatial_NODE* N, Fvector& n_C, float n_R) - { - // 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 (!BB.intersect(box)) return; - - // test items - xr_vector::iterator _it = N->items.begin(); - xr_vector::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; - Fbox sB; - sB.set(sC.x - sR, sC.y - sR, sC.z - sR, sC.x + sR, sC.y + sR, sC.z + sR); - if (!sB.intersect(box)) continue; - - space->q_result->push_back(S); - if (b_first) return; - } - - // 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); - if (b_first && !space->q_result->empty()) return; - } - } -}; - -void ISpatial_DB::q_box(xr_vector& R, u32 _o, u32 _mask, const Fvector& _center, const Fvector& _size) -{ - cs.Enter(); - q_result = &R; - q_result->clear_not_free(); - if (_o & O_ONLYFIRST) { walker W(this, _mask, _center, _size); W.walk(m_root, m_center, m_bounds); } - else { walker W(this, _mask, _center, _size); W.walk(m_root, m_center, m_bounds); } - cs.Leave(); -} - -void ISpatial_DB::q_sphere(xr_vector& R, u32 _o, u32 _mask, const Fvector& _center, const float _radius) -{ - Fvector _size = {_radius, _radius, _radius}; - q_box(R, _o, _mask, _center, _size); -} diff --git a/src/xrEngine/ISpatial_q_frustum.cpp b/src/xrEngine/ISpatial_q_frustum.cpp deleted file mode 100644 index ac02f591aa8..00000000000 --- a/src/xrEngine/ISpatial_q_frustum.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "stdafx.h" -#include "ISpatial.h" -#include "frustum.h" - -extern Fvector c_spatial_offset[8]; - -class walker -{ -public: - u32 mask; - CFrustum* F; - ISpatial_DB* space; -public: - walker(ISpatial_DB* _space, u32 _mask, const CFrustum* _F) - { - mask = _mask; - F = (CFrustum*)_F; - space = _space; - } - 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::iterator _it = N->items.begin(); - xr_vector::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); - } - } -}; - -void ISpatial_DB::q_frustum(xr_vector& 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(); -} diff --git a/src/xrEngine/ISpatial_q_ray.cpp b/src/xrEngine/ISpatial_q_ray.cpp deleted file mode 100644 index 8caef9c11ba..00000000000 --- a/src/xrEngine/ISpatial_q_ray.cpp +++ /dev/null @@ -1,336 +0,0 @@ -#include "stdafx.h" -#include "ISpatial.h" -#pragma warning(push) -#pragma warning(disable:4995) -#include -#pragma warning(pop) - -// can you say "barebone"? -#ifndef _MM_ALIGN16 -# define _MM_ALIGN16 __declspec(align(16)) -#endif // _MM_ALIGN16 - -struct _MM_ALIGN16 vec_t : public Fvector3 -{ - float pad; -}; -vec_t vec_c(float _x, float _y, float _z) { vec_t v; v.x = _x; v.y = _y; v.z = _z; v.pad = 0; return v; } -struct _MM_ALIGN16 aabb_t -{ - vec_t min; - vec_t max; -}; -struct _MM_ALIGN16 ray_t -{ - vec_t pos; - vec_t inv_dir; - vec_t fwd_dir; -}; -struct ray_segment_t -{ - float t_near, t_far; -}; - -ICF u32& uf(float& x) { return (u32&)x; } -ICF BOOL isect_fpu(const Fvector& min, const Fvector& max, const ray_t& ray, Fvector& coord) -{ - Fvector MaxT; - MaxT.x = MaxT.y = MaxT.z = -1.0f; - BOOL Inside = TRUE; - - // Find candidate planes. - if (ray.pos[0] < min[0]) - { - coord[0] = min[0]; - Inside = FALSE; - if (uf(ray.inv_dir[0])) MaxT[0] = (min[0] - ray.pos[0]) * ray.inv_dir[0]; // Calculate T distances to candidate planes - } - else if (ray.pos[0] > max[0]) - { - coord[0] = max[0]; - Inside = FALSE; - if (uf(ray.inv_dir[0])) MaxT[0] = (max[0] - ray.pos[0]) * ray.inv_dir[0]; // Calculate T distances to candidate planes - } - if (ray.pos[1] < min[1]) - { - coord[1] = min[1]; - Inside = FALSE; - if (uf(ray.inv_dir[1])) MaxT[1] = (min[1] - ray.pos[1]) * ray.inv_dir[1]; // Calculate T distances to candidate planes - } - else if (ray.pos[1] > max[1]) - { - coord[1] = max[1]; - Inside = FALSE; - if (uf(ray.inv_dir[1])) MaxT[1] = (max[1] - ray.pos[1]) * ray.inv_dir[1]; // Calculate T distances to candidate planes - } - if (ray.pos[2] < min[2]) - { - coord[2] = min[2]; - Inside = FALSE; - if (uf(ray.inv_dir[2])) MaxT[2] = (min[2] - ray.pos[2]) * ray.inv_dir[2]; // Calculate T distances to candidate planes - } - else if (ray.pos[2] > max[2]) - { - coord[2] = max[2]; - Inside = FALSE; - if (uf(ray.inv_dir[2])) MaxT[2] = (max[2] - ray.pos[2]) * ray.inv_dir[2]; // Calculate T distances to candidate planes - } - - // Ray ray.pos inside bounding box - if (Inside) - { - coord = ray.pos; - return true; - } - - // Get largest of the maxT's for final choice of intersection - u32 WhichPlane = 0; - if (MaxT[1] > MaxT[0]) WhichPlane = 1; - if (MaxT[2] > MaxT[WhichPlane]) WhichPlane = 2; - - // Check final candidate actually inside box (if max < 0) - if (uf(MaxT[WhichPlane]) & 0x80000000) return false; - - if (0 == WhichPlane) // 1 & 2 - { - coord[1] = ray.pos[1] + MaxT[0] * ray.fwd_dir[1]; - if ((coord[1] < min[1]) || (coord[1] > max[1])) return false; - coord[2] = ray.pos[2] + MaxT[0] * ray.fwd_dir[2]; - if ((coord[2] < min[2]) || (coord[2] > max[2])) return false; - return true; - } - if (1 == WhichPlane) // 0 & 2 - { - coord[0] = ray.pos[0] + MaxT[1] * ray.fwd_dir[0]; - if ((coord[0] < min[0]) || (coord[0] > max[0])) return false; - coord[2] = ray.pos[2] + MaxT[1] * ray.fwd_dir[2]; - if ((coord[2] < min[2]) || (coord[2] > max[2])) return false; - return true; - } - if (2 == WhichPlane) // 0 & 1 - { - coord[0] = ray.pos[0] + MaxT[2] * ray.fwd_dir[0]; - if ((coord[0] < min[0]) || (coord[0] > max[0])) return false; - coord[1] = ray.pos[1] + MaxT[2] * ray.fwd_dir[1]; - if ((coord[1] < min[1]) || (coord[1] > max[1])) return false; - return true; - } - return false; -} - -// turn those verbose intrinsics into something readable. -#define loadps(mem) _mm_load_ps((const float * const)(mem)) -#define storess(ss,mem) _mm_store_ss((float * const)(mem),(ss)) -#define minss _mm_min_ss -#define maxss _mm_max_ss -#define minps _mm_min_ps -#define maxps _mm_max_ps -#define mulps _mm_mul_ps -#define subps _mm_sub_ps -#define rotatelps(ps) _mm_shuffle_ps((ps),(ps), 0x39) // a,b,c,d -> b,c,d,a -#define muxhps(low,high) _mm_movehl_ps((low),(high)) // low{a,b,c,d}|high{e,f,g,h} = {c,d,g,h} - - -static const float flt_plus_inf = -logf(0); // let's keep C and C++ compilers happy. -static const float _MM_ALIGN16 -ps_cst_plus_inf[4] = {flt_plus_inf, flt_plus_inf, flt_plus_inf, flt_plus_inf}, -ps_cst_minus_inf[4] = {-flt_plus_inf, -flt_plus_inf, -flt_plus_inf, -flt_plus_inf}; - -ICF BOOL isect_sse(const aabb_t& box, const ray_t& ray, float& dist) -{ - // you may already have those values hanging around somewhere - const __m128 - plus_inf = loadps(ps_cst_plus_inf), - minus_inf = loadps(ps_cst_minus_inf); - - // use whatever's apropriate to load. - const __m128 - box_min = loadps(&box.min), - box_max = loadps(&box.max), - pos = loadps(&ray.pos), - inv_dir = loadps(&ray.inv_dir); - - // use a div if inverted directions aren't available - const __m128 l1 = mulps(subps(box_min, pos), inv_dir); - const __m128 l2 = mulps(subps(box_max, pos), inv_dir); - - // the order we use for those min/max is vital to filter out - // NaNs that happens when an inv_dir is +/- inf and - // (box_min - pos) is 0. inf * 0 = NaN - const __m128 filtered_l1a = minps(l1, plus_inf); - const __m128 filtered_l2a = minps(l2, plus_inf); - - const __m128 filtered_l1b = maxps(l1, minus_inf); - const __m128 filtered_l2b = maxps(l2, minus_inf); - - // now that we're back on our feet, test those slabs. - __m128 lmax = maxps(filtered_l1a, filtered_l2a); - __m128 lmin = minps(filtered_l1b, filtered_l2b); - - // unfold back. try to hide the latency of the shufps & co. - const __m128 lmax0 = rotatelps(lmax); - const __m128 lmin0 = rotatelps(lmin); - lmax = minss(lmax, lmax0); - lmin = maxss(lmin, lmin0); - - const __m128 lmax1 = muxhps(lmax, lmax); - const __m128 lmin1 = muxhps(lmin, lmin); - lmax = minss(lmax, lmax1); - lmin = maxss(lmin, lmin1); - - const BOOL ret = _mm_comige_ss(lmax, _mm_setzero_ps()) & _mm_comige_ss(lmax, lmin); - - storess(lmin, &dist); - //storess (lmax, &rs.t_far); - - return ret; -} - -extern Fvector c_spatial_offset[8]; - -template -class _MM_ALIGN16 walker -{ -public: - ray_t ray; - u32 mask; - float range; - float range2; - ISpatial_DB* space; -public: - walker(ISpatial_DB* _space, u32 _mask, const Fvector& _start, const Fvector& _dir, float _range) - { - mask = _mask; - ray.pos.set(_start); - ray.inv_dir.set(1.f, 1.f, 1.f).div(_dir); - ray.fwd_dir.set(_dir); - if (!b_use_sse) - { - // for FPU - zero out inf - if (_abs(_dir.x) > flt_eps) {} - else ray.inv_dir.x = 0; - if (_abs(_dir.y) > flt_eps) {} - else ray.inv_dir.y = 0; - if (_abs(_dir.z) > flt_eps) {} - else ray.inv_dir.z = 0; - } - range = _range; - range2 = _range*_range; - space = _space; - } - // fpu - ICF BOOL _box_fpu(const Fvector& n_C, const float n_R, Fvector& coord) - { - // 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); - return isect_fpu(BB.min, BB.max, ray, coord); - } - // sse - ICF BOOL _box_sse(const Fvector& n_C, const float n_R, float& dist) - { - aabb_t box; - float n_vR = 2 * n_R; - box.min.set(n_C.x - n_vR, n_C.y - n_vR, n_C.z - n_vR); - box.min.pad = 0; - box.max.set(n_C.x + n_vR, n_C.y + n_vR, n_C.z + n_vR); - box.max.pad = 0; - return isect_sse(box, ray, dist); - } - void walk(ISpatial_NODE* N, Fvector& n_C, float n_R) - { - // Actual ray/aabb test - if (b_use_sse) - { - // use SSE - float d; - if (!_box_sse(n_C, n_R, d)) return; - if (d > range) return; - } - else - { - // use FPU - Fvector P; - if (!_box_fpu(n_C, n_R, P)) return; - if (P.distance_to_sqr(ray.pos) > range2) return; - } - - // test items - xr_vector::iterator _it = N->items.begin(); - xr_vector::iterator _end = N->items.end(); - for (; _it != _end; _it++) - { - ISpatial* S = *_it; - if (mask != (S->spatial.type&mask)) continue; - Fsphere& sS = S->spatial.sphere; - int quantity; - float afT[2]; - Fsphere::ERP_Result result = sS.intersect(ray.pos, ray.fwd_dir, range, quantity, afT); - - if (result == Fsphere::rpOriginInside || ((result == Fsphere::rpOriginOutside) && (afT[0] < range))) - { - if (b_nearest) - { - switch (result) - { - case Fsphere::rpOriginInside: - range = afT[0] < range ? afT[0] : range; - break; - case Fsphere::rpOriginOutside: - range = afT[0]; - break; - } - range2 = range*range; - } - space->q_result->push_back(S); - if (b_first) return; - } - } - - // 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); - if (b_first && !space->q_result->empty()) return; - } - } -}; - -void ISpatial_DB::q_ray(xr_vector& R, u32 _o, u32 _mask_and, const Fvector& _start, const Fvector& _dir, float _range) -{ - cs.Enter(); - q_result = &R; - q_result->clear_not_free(); - if (CPU::ID.feature&_CPU_FEATURE_SSE) - { - if (_o & O_ONLYFIRST) - { - if (_o & O_ONLYNEAREST) { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - else { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - } - else - { - if (_o & O_ONLYNEAREST) { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - else { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - } - } - else - { - if (_o & O_ONLYFIRST) - { - if (_o & O_ONLYNEAREST) { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - else { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - } - else - { - if (_o & O_ONLYNEAREST) { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - else { walker W(this, _mask_and, _start, _dir, _range); W.walk(m_root, m_center, m_bounds); } - } - } - cs.Leave(); -} diff --git a/src/xrEngine/ISpatial_verify.cpp b/src/xrEngine/ISpatial_verify.cpp deleted file mode 100644 index c6306aeae35..00000000000 --- a/src/xrEngine/ISpatial_verify.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "stdafx.h" -#include "ISpatial.h" - -extern Fvector c_spatial_offset[8]; - -class walker -{ -public: - u32 o_count; - u32 n_count; -public: - walker() - { - o_count = 0; - n_count = 0; - } - void walk(ISpatial_NODE* N, Fvector& n_C, float n_R) - { - // test items - n_count += 1; - o_count += N->items.size(); - - // 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); - } - } -}; - -BOOL ISpatial_DB::verify() -{ - walker W; - W.walk(m_root, m_center, m_bounds); - BOOL bResult = (W.o_count == stat_objects) && (W.n_count == stat_nodes); - VERIFY(bResult); - return bResult; -} diff --git a/src/xrEngine/xrXRC.cpp b/src/xrEngine/xrXRC.cpp deleted file mode 100644 index 3fe6840cdcc..00000000000 --- a/src/xrEngine/xrXRC.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// xrXRC.cpp: implementation of the xrXRC class. -// -////////////////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "xrXRC.h" - -ENGINE_API xrXRC XRC; - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -xrXRC::xrXRC() -{ - -} - -xrXRC::~xrXRC() -{ - -} diff --git a/src/xrEngine/xrXRC.h b/src/xrEngine/xrXRC.h deleted file mode 100644 index 31f070db5bd..00000000000 --- a/src/xrEngine/xrXRC.h +++ /dev/null @@ -1,72 +0,0 @@ -// xrXRC.h: interface for the xrXRC class. -// -////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_XRXRC_H__9AA25268_621F_4FCA_BD75_AF2E9822B8E3__INCLUDED_) -#define AFX_XRXRC_H__9AA25268_621F_4FCA_BD75_AF2E9822B8E3__INCLUDED_ -#pragma once - -#include "../xrCDB/xrCDB.h" - -class ENGINE_API xrXRC -{ - CDB::COLLIDER CL; -public: - IC void ray_options(u32 f) - { - CL.ray_options(f); - } - IC void ray_query(const CDB::MODEL* m_def, const Fvector& r_start, const Fvector& r_dir, float r_range = 10000.f) - { -#ifdef DEBUG - Device.Statistic->clRAY.Begin(); -#endif - CL.ray_query(m_def, r_start, r_dir, r_range); -#ifdef DEBUG - Device.Statistic->clRAY.End(); -#endif - } - - IC void box_options(u32 f) - { - CL.box_options(f); - } - IC void box_query(const CDB::MODEL* m_def, const Fvector& b_center, const Fvector& b_dim) - { -#ifdef DEBUG - Device.Statistic->clBOX.Begin(); -#endif - CL.box_query(m_def, b_center, b_dim); -#ifdef DEBUG - Device.Statistic->clBOX.End(); -#endif - } - - IC void frustum_options(u32 f) - { - CL.frustum_options(f); - } - IC void frustum_query(const CDB::MODEL* m_def, const CFrustum& F) - { -#ifdef DEBUG - Device.Statistic->clFRUSTUM.Begin(); -#endif - CL.frustum_query(m_def, F); -#ifdef DEBUG - Device.Statistic->clFRUSTUM.End(); -#endif - } - - IC CDB::RESULT* r_begin() { return CL.r_begin(); }; - IC CDB::RESULT* r_end() { return CL.r_end(); }; - IC void r_free() { CL.r_free(); } - IC int r_count() { return CL.r_count(); }; - IC void r_clear() { CL.r_clear(); }; - IC void r_clear_compact() { CL.r_clear_compact(); }; - - xrXRC(); - ~xrXRC(); -}; -ENGINE_API extern xrXRC XRC; - -#endif // !defined(AFX_XRXRC_H__9AA25268_621F_4FCA_BD75_AF2E9822B8E3__INCLUDED_) diff --git a/src/xrEngine/xr_area.cpp b/src/xrEngine/xr_area.cpp deleted file mode 100644 index 0f2bded67dc..00000000000 --- a/src/xrEngine/xr_area.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "stdafx.h" -#include "igame_level.h" - -#include "xr_area.h" -#include "xr_object.h" -#include "xrLevel.h" -#include "feel_sound.h" -#include "x_ray.h" -#include "GameFont.h" - -using namespace collide; - -extern BOOL g_bLoaded; - -void IGame_Level::SoundEvent_Register(ref_sound_data_ptr S, float range) -{ - if (!g_bLoaded) return; - if (!S) return; - if (S->g_object && S->g_object->getDestroy()) { S->g_object = 0; return; } - if (0 == S->feedback) return; - - clamp(range, 0.1f, 500.f); - - const CSound_params* p = S->feedback->get_params(); - Fvector snd_position = p->position; - if (S->feedback->is_2D()) - { - snd_position.add(Sound->listener_position()); - } - - VERIFY(p && _valid(range)); - range = _min(range, p->max_ai_distance); - VERIFY(_valid(snd_position)); - VERIFY(_valid(p->max_ai_distance)); - VERIFY(_valid(p->volume)); - - // Query objects - Fvector bb_size = {range, range, range}; - g_SpatialSpace->q_box(snd_ER, 0, STYPE_REACTTOSOUND, snd_position, bb_size); - - // Iterate - xr_vector::iterator it = snd_ER.begin(); - xr_vector::iterator end = snd_ER.end(); - for (; it != end; it++) - { - Feel::Sound* L = (*it)->dcast_FeelSound(); - if (0 == L) continue; - CObject* CO = (*it)->dcast_CObject(); - VERIFY(CO); - if (CO->getDestroy()) continue; - - // Energy and signal - VERIFY(_valid((*it)->spatial.sphere.P)); - float dist = snd_position.distance_to((*it)->spatial.sphere.P); - if (dist > p->max_ai_distance) continue; - VERIFY(_valid(dist)); - VERIFY2(!fis_zero(p->max_ai_distance), S->handle->file_name()); - float Power = (1.f - dist / p->max_ai_distance)*p->volume; - VERIFY(_valid(Power)); - if (Power > EPS_S) - { - float occ = Sound->get_occlusion_to((*it)->spatial.sphere.P, snd_position); - VERIFY(_valid(occ)); - Power *= occ; - if (Power > EPS_S) - { - _esound_delegate D = {L, S, Power}; - snd_Events.push_back(D); - } - } - } - snd_ER.clear_not_free(); -} - -void IGame_Level::SoundEvent_Dispatch() -{ - while (!snd_Events.empty()) - { - _esound_delegate& D = snd_Events.back(); - VERIFY(D.dest && D.source); - if (D.source->feedback) - { - D.dest->feel_sound_new( - D.source->g_object, - D.source->g_type, - D.source->g_userdata, - D.source->feedback->get_params()->position, - D.power - ); - } - snd_Events.pop_back(); - } -} - -// Lain: added -void IGame_Level::SoundEvent_OnDestDestroy(Feel::Sound* obj) -{ - struct rem_pred - { - rem_pred(Feel::Sound* obj) : m_obj(obj) {} - - bool operator () (const _esound_delegate& d) - { - return d.dest == m_obj; - } - - private: - Feel::Sound* m_obj; - }; - - snd_Events.erase(std::remove_if(snd_Events.begin(), snd_Events.end(), rem_pred(obj)), - snd_Events.end()); -} - -void __stdcall _sound_event(ref_sound_data_ptr S, float range) -{ - if (g_pGameLevel && S && S->feedback) g_pGameLevel->SoundEvent_Register(S, range); -} - -//---------------------------------------------------------------------- -// Class : CObjectSpace -// Purpose : stores space slots -//---------------------------------------------------------------------- -CObjectSpace::CObjectSpace() -#ifdef PROFILE_CRITICAL_SECTIONS - :Lock(MUTEX_PROFILE_ID(CObjectSpace::Lock)) -#endif // PROFILE_CRITICAL_SECTIONS -{ -#ifdef DEBUG - //sh_debug.create ("debug\\wireframe","$null"); -#endif - m_BoundingVolume.invalidate(); -} -//---------------------------------------------------------------------- -CObjectSpace::~CObjectSpace() -{ - Sound->set_geometry_occ(NULL); - Sound->set_handler(NULL); -#ifdef DEBUG - //sh_debug.destroy (); -#endif -} -//---------------------------------------------------------------------- - -//---------------------------------------------------------------------- -int CObjectSpace::GetNearest(xr_vector& q_spatial, xr_vector& q_nearest, const Fvector& point, float range, CObject* ignore_object) -{ - q_spatial.clear_not_free(); - // Query objects - q_nearest.clear_not_free(); - Fsphere Q; - Q.set(point, range); - Fvector B; - B.set(range, range, range); - g_SpatialSpace->q_box(q_spatial, 0, STYPE_COLLIDEABLE, point, B); - - // Iterate - xr_vector::iterator it = q_spatial.begin(); - xr_vector::iterator end = q_spatial.end(); - for (; it != end; it++) - { - CObject* O = (*it)->dcast_CObject(); - if (0 == O) continue; - if (O == ignore_object) continue; - Fsphere mS = {O->spatial.sphere.P, O->spatial.sphere.R}; - if (Q.intersect(mS)) q_nearest.push_back(O); - } - - return q_nearest.size(); -} - -//---------------------------------------------------------------------- -IC int CObjectSpace::GetNearest(xr_vector& q_nearest, const Fvector& point, float range, CObject* ignore_object) -{ - return ( - GetNearest( - r_spatial, - q_nearest, - point, - range, - ignore_object - ) - ); -} - -//---------------------------------------------------------------------- -IC int CObjectSpace::GetNearest(xr_vector& q_nearest, ICollisionForm* obj, float range) -{ - CObject* O = obj->Owner(); - return GetNearest(q_nearest, O->spatial.sphere.P, range + O->spatial.sphere.R, O); -} - -//---------------------------------------------------------------------- -static void __stdcall build_callback(Fvector* V, int Vcnt, CDB::TRI* T, int Tcnt, void* params) -{ - g_pGameLevel->Load_GameSpecific_CFORM(T, Tcnt); -} -void CObjectSpace::Load() -{ - IReader* F = FS.r_open("$level$", "level.cform"); - R_ASSERT(F); - - hdrCFORM H; - F->r(&H, sizeof(hdrCFORM)); - Fvector* verts = (Fvector*)F->pointer(); - CDB::TRI* tris = (CDB::TRI*)(verts + H.vertcount); - R_ASSERT(CFORM_CURRENT_VERSION == H.version); - Static.build(verts, H.vertcount, tris, H.facecount, build_callback); - - m_BoundingVolume.set(H.aabb); - g_SpatialSpace->initialize(H.aabb); - g_SpatialSpacePhysic->initialize(H.aabb); - Sound->set_geometry_occ(&Static); - Sound->set_handler(_sound_event); - - FS.r_close(F); -} -//---------------------------------------------------------------------- -#ifdef DEBUG -void CObjectSpace::dbgRender() -{ - m_pRender->dbgRender(); -} -/* -void CObjectSpace::dbgRender() -{ -R_ASSERT(bDebug); - -RCache.set_Shader(sh_debug); -for (u32 i=0; i& P = dbg_S[i]; -Fsphere& S = P.first; -Fmatrix M; -M.scale (S.R,S.R,S.R); -M.translate_over(S.P); -RCache.dbg_DrawEllipse(M,P.second); -} -dbg_S.clear(); -} -*/ -#endif diff --git a/src/xrEngine/xr_area.h b/src/xrEngine/xr_area.h deleted file mode 100644 index 708cd56153c..00000000000 --- a/src/xrEngine/xr_area.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __XR_AREA_H__ -#define __XR_AREA_H__ - -#include "xr_collide_form.h" -#include "xr_collide_defs.h" - -// refs -class ENGINE_API ISpatial; -class ENGINE_API ICollisionForm; -class ENGINE_API CObject; - -#include "../Include/xrRender/FactoryPtr.h" -#include "../Include/xrRender/ObjectSpaceRender.h" -#include "xrXRC.h" - -//----------------------------------------------------------------------------------------------------------- -//Space Area -//----------------------------------------------------------------------------------------------------------- -class ENGINE_API CObjectSpace -{ -private: - // Debug - xrCriticalSection Lock; - CDB::MODEL Static; - Fbox m_BoundingVolume; - xrXRC xrc; // MT: dangerous - collide::rq_results r_temp; // MT: dangerous - xr_vector r_spatial; // MT: dangerous -public: - -#ifdef DEBUG - FactoryPtr m_pRender; - //ref_shader sh_debug; - //clQueryCollision q_debug; // MT: dangerous - //xr_vector > dbg_S; // MT: dangerous -#endif - -private: - BOOL _RayTest(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object); - BOOL _RayPick(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::rq_result& R, CObject* ignore_object); - BOOL _RayQuery(collide::rq_results& dest, const collide::ray_defs& rq, collide::rq_callback* cb, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object); - BOOL _RayQuery2(collide::rq_results& dest, const collide::ray_defs& rq, collide::rq_callback* cb, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object); - BOOL _RayQuery3(collide::rq_results& dest, const collide::ray_defs& rq, collide::rq_callback* cb, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object); -public: - CObjectSpace(); - ~CObjectSpace(); - - void Load(); - - // Occluded/No - BOOL RayTest(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object); - - // Game raypick (nearest) - returns object and addititional params - BOOL RayPick(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::rq_result& R, CObject* ignore_object); - - // General collision query - BOOL RayQuery(collide::rq_results& dest, const collide::ray_defs& rq, collide::rq_callback* cb, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object); - BOOL RayQuery(collide::rq_results& dest, ICollisionForm* target, const collide::ray_defs& rq); - // void BoxQuery ( collide::rq_results& dest, const Fbox& B, const Fmatrix& M, u32 flags=clGET_TRIS|clGET_BOXES|clQUERY_STATIC|clQUERY_DYNAMIC); - - int GetNearest(xr_vector& q_nearest, ICollisionForm* obj, float range); - int GetNearest(xr_vector& q_nearest, const Fvector& point, float range, CObject* ignore_object); - int GetNearest(xr_vector& q_spatial, xr_vector& q_nearest, const Fvector& point, float range, CObject* ignore_object); - - CDB::TRI* GetStaticTris() { return Static.get_tris(); } - Fvector* GetStaticVerts() { return Static.get_verts(); } - CDB::MODEL* GetStaticModel() { return &Static; } - - const Fbox& GetBoundingVolume() { return m_BoundingVolume; } - - // Debugging -#ifdef DEBUG - void dbgRender(); - //ref_shader dbgGetShader () { return sh_debug; } -#endif -}; - -#endif //__XR_AREA_H__ diff --git a/src/xrEngine/xr_area_query.cpp b/src/xrEngine/xr_area_query.cpp deleted file mode 100644 index a95d50ae694..00000000000 --- a/src/xrEngine/xr_area_query.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "stdafx.h" -#include "xr_area.h" -#include "xr_object.h" - -using namespace collide; - -/* -const u32 clStatic = clQUERY_STATIC+clGET_TRIS; - -void CObjectSpace::BoxQuery (collide::rq_results& r_dest, const Fbox& B, const Fmatrix& M, u32 flags) -{ -Fvector bc,bd; -Fbox xf; -xf.xform (B,M); -xf.get_CD (bc,bd); - -q_result.Clear (); -xrc.box_options ( -(flags&clCOARSE?0:CDB::OPT_FULL_TEST)| -(flags&clQUERY_ONLYFIRST?CDB::OPT_ONLYFIRST:0) -); - -if ((flags&clStatic) == clStatic) -{ -xrc.box_query (&Static, bc, bd); -if (xrc.r_count()) -{ -CDB::RESULT* it =xrc.r_begin(); -CDB::RESULT* end=xrc.r_end (); -for (; it!=end; it++) -q_result.AddTri(&Static.get_tris() [it->id],Static.get_verts()); -} -}; - -if (flags&clQUERY_DYNAMIC) -{ -// Traverse object database -g_SpatialSpace->q_box (r_spatial,0,STYPE_COLLIDEABLE,bc,bd); - -// Determine visibility for dynamic part of scene -for (u32 o_it=0; o_itdcast_CObject (); -if (0==collidable) continue; -collidable->collidable.model->_BoxQuery (B,M,flags); -} -}; -} -*/ diff --git a/src/xrEngine/xr_area_raypick.cpp b/src/xrEngine/xr_area_raypick.cpp deleted file mode 100644 index 5d69b824aee..00000000000 --- a/src/xrEngine/xr_area_raypick.cpp +++ /dev/null @@ -1,465 +0,0 @@ -#include "stdafx.h" -#include "xr_area.h" -#include "xr_collide_form.h" -#include "xr_object.h" -#include "cl_intersect.h" - -#include "igame_level.h" -#include "x_ray.h" -#include "GameFont.h" - -using namespace collide; - -//-------------------------------------------------------------------------------- -// RayTest - Occluded/No -//-------------------------------------------------------------------------------- -BOOL CObjectSpace::RayTest(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object) -{ - Lock.Enter(); - BOOL _ret = _RayTest(start, dir, range, tgt, cache, ignore_object); - r_spatial.clear(); - Lock.Leave(); - return _ret; -} -BOOL CObjectSpace::_RayTest(const Fvector& start, const Fvector& dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object) -{ - VERIFY(_abs(dir.magnitude() - 1) < EPS); - r_temp.r_clear(); - - xrc.ray_options(CDB::OPT_ONLYFIRST); - collide::ray_defs Q(start, dir, range, CDB::OPT_ONLYFIRST, tgt); - - // dynamic test - if (tgt&rqtDyn) - { - u32 d_flags = STYPE_COLLIDEABLE | ((tgt&rqtObstacle) ? STYPE_OBSTACLE : 0) | ((tgt&rqtShape) ? STYPE_SHAPE : 0); - // traverse object database - g_SpatialSpace->q_ray(r_spatial, 0, d_flags, start, dir, range); - // Determine visibility for dynamic part of scene - for (u32 o_it = 0; o_it < r_spatial.size(); o_it++) - { - ISpatial* spatial = r_spatial[o_it]; - CObject* collidable = spatial->dcast_CObject(); - if (collidable && (collidable != ignore_object)) - { - ECollisionFormType tp = collidable->collidable.model->Type(); - if ((tgt&(rqtObject | rqtObstacle)) && (tp == cftObject) && collidable->collidable.model->_RayQuery(Q, r_temp)) return TRUE; - if ((tgt&rqtShape) && (tp == cftShape) && collidable->collidable.model->_RayQuery(Q, r_temp)) return TRUE; - } - } - } - // static test - if (tgt&rqtStatic) - { - // If we get here - test static model - if (cache) - { - // 0. similar query??? - if (cache->similar(start, dir, range)) - { - return cache->result; - } - - // 1. Check cached polygon - float _u, _v, _range; - if (CDB::TestRayTri(start, dir, cache->verts, _u, _v, _range, false)) - { - if (_range > 0 && _range < range) return TRUE; - } - - // 2. Polygon doesn't pick - real database query - xrc.ray_query(&Static, start, dir, range); - if (0 == xrc.r_count()) - { - cache->set(start, dir, range, FALSE); - return FALSE; - } - else - { - // cache polygon - cache->set(start, dir, range, TRUE); - CDB::RESULT* R = xrc.r_begin(); - CDB::TRI& T = Static.get_tris()[R->id]; - Fvector* V = Static.get_verts(); - cache->verts[0].set(V[T.verts[0]]); - cache->verts[1].set(V[T.verts[1]]); - cache->verts[2].set(V[T.verts[2]]); - return TRUE; - } - } - else - { - xrc.ray_query(&Static, start, dir, range); - return xrc.r_count(); - } - } - return FALSE; -} - -//-------------------------------------------------------------------------------- -// RayPick -//-------------------------------------------------------------------------------- -BOOL CObjectSpace::RayPick(const Fvector& start, const Fvector& dir, float range, rq_target tgt, rq_result& R, CObject* ignore_object) -{ - Lock.Enter(); - BOOL _res = _RayPick(start, dir, range, tgt, R, ignore_object); - r_spatial.clear(); - Lock.Leave(); - return _res; -} -BOOL CObjectSpace::_RayPick(const Fvector& start, const Fvector& dir, float range, rq_target tgt, rq_result& R, CObject* ignore_object) -{ - r_temp.r_clear(); - R.O = 0; - R.range = range; - R.element = -1; - // static test - if (tgt&rqtStatic) - { - xrc.ray_options(CDB::OPT_ONLYNEAREST | CDB::OPT_CULL); - xrc.ray_query(&Static, start, dir, range); - if (xrc.r_count()) R.set_if_less(xrc.r_begin()); - } - // dynamic test - if (tgt&rqtDyn) - { - collide::ray_defs Q(start, dir, R.range, CDB::OPT_ONLYNEAREST | CDB::OPT_CULL, tgt); - // traverse object database - u32 d_flags = STYPE_COLLIDEABLE | ((tgt&rqtObstacle) ? STYPE_OBSTACLE : 0) | ((tgt&rqtShape) ? STYPE_SHAPE : 0); - g_SpatialSpace->q_ray(r_spatial, 0, d_flags, start, dir, range); - // Determine visibility for dynamic part of scene - for (u32 o_it = 0; o_it < r_spatial.size(); o_it++) - { - ISpatial* spatial = r_spatial[o_it]; - CObject* collidable = spatial->dcast_CObject(); - if (0 == collidable) continue; - if (collidable == ignore_object) continue; - ECollisionFormType tp = collidable->collidable.model->Type(); - if (((tgt&(rqtObject | rqtObstacle)) && (tp == cftObject)) || ((tgt&rqtShape) && (tp == cftShape))) - { - u32 C = D3DCOLOR_XRGB(64, 64, 64); - Q.range = R.range; - if (collidable->collidable.model->_RayQuery(Q, r_temp)) - { - C = D3DCOLOR_XRGB(128, 128, 196); - R.set_if_less(r_temp.r_begin()); - } -#ifdef DEBUG - if (bDebug) - { - Fsphere S; - S.P = spatial->spatial.sphere.P; - S.R = spatial->spatial.sphere.R; - m_pRender->dbgAddSphere(S, C); - //dbg_S.push_back (mk_pair(S,C)); - } -#endif - } - } - } - return (R.element >= 0); -} - -//-------------------------------------------------------------------------------- -// RayQuery -//-------------------------------------------------------------------------------- -BOOL CObjectSpace::RayQuery(collide::rq_results& dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object) -{ - Lock.Enter(); - BOOL _res = _RayQuery2(dest, R, CB, user_data, tb, ignore_object); - r_spatial.clear_not_free(); - Lock.Leave(); - return (_res); -} -BOOL CObjectSpace::_RayQuery2(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object) -{ - // initialize query - r_dest.r_clear(); - r_temp.r_clear(); - - rq_target s_mask = rqtStatic; - rq_target d_mask = rq_target(((R.tgt&rqtObject) ? rqtObject : rqtNone) | - ((R.tgt&rqtObstacle) ? rqtObstacle : rqtNone) | - ((R.tgt&rqtShape) ? rqtShape : rqtNone)); - u32 d_flags = STYPE_COLLIDEABLE | ((R.tgt&rqtObstacle) ? STYPE_OBSTACLE : 0) | ((R.tgt&rqtShape) ? STYPE_SHAPE : 0); - - // Test static - if (R.tgt&s_mask) - { - xrc.ray_options(R.flags); - xrc.ray_query(&Static, R.start, R.dir, R.range); - if (xrc.r_count()) - { - CDB::RESULT* _I = xrc.r_begin(); - CDB::RESULT* _E = xrc.r_end(); - for (; _I != _E; _I++) - r_temp.append_result(rq_result().set(0, _I->range, _I->id)); - } - } - // Test dynamic - if (R.tgt&d_mask) - { - // Traverse object database - g_SpatialSpace->q_ray(r_spatial, 0, d_flags, R.start, R.dir, R.range); - for (u32 o_it = 0; o_it < r_spatial.size(); o_it++) - { - CObject* collidable = r_spatial[o_it]->dcast_CObject(); - if (0 == collidable) continue; - if (collidable == ignore_object) continue; - ICollisionForm* cform = collidable->collidable.model; - ECollisionFormType tp = collidable->collidable.model->Type(); - if (((R.tgt&(rqtObject | rqtObstacle)) && (tp == cftObject)) || ((R.tgt&rqtShape) && (tp == cftShape))) - { - if (tb&&!tb(R, collidable, user_data))continue; - cform->_RayQuery(R, r_temp); - } - } - } - if (r_temp.r_count()) - { - r_temp.r_sort(); - collide::rq_result* _I = r_temp.r_begin(); - collide::rq_result* _E = r_temp.r_end(); - for (; _I != _E; _I++) - { - r_dest.append_result(*_I); - if (!(CB ? CB(*_I, user_data) : TRUE)) return r_dest.r_count(); - if (R.flags&(CDB::OPT_ONLYNEAREST | CDB::OPT_ONLYFIRST)) return r_dest.r_count(); - } - } - return r_dest.r_count(); -} - -BOOL CObjectSpace::_RayQuery3(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object) -{ - // initialize query - r_dest.r_clear(); - - ray_defs d_rd(R); - ray_defs s_rd(R.start, R.dir, R.range, CDB::OPT_ONLYNEAREST | R.flags, R.tgt); - rq_target s_mask = rqtStatic; - rq_target d_mask = rq_target(((R.tgt&rqtObject) ? rqtObject : rqtNone) | - ((R.tgt&rqtObstacle) ? rqtObstacle : rqtNone) | - ((R.tgt&rqtShape) ? rqtShape : rqtNone)); - u32 d_flags = STYPE_COLLIDEABLE | ((R.tgt&rqtObstacle) ? STYPE_OBSTACLE : 0) | ((R.tgt&rqtShape) ? STYPE_SHAPE : 0); - float d_range = 0.f; - - do - { - r_temp.r_clear(); - if (R.tgt&s_mask) - { - // static test allowed - - // test static - xrc.ray_options(s_rd.flags); - xrc.ray_query(&Static, s_rd.start, s_rd.dir, s_rd.range); - - if (xrc.r_count()) - { - VERIFY(xrc.r_count() == 1); - rq_result s_res; - s_res.set(0, xrc.r_begin()->range, xrc.r_begin()->id); - // update dynamic test range - d_rd.range = s_res.range; - // set next static start & range - s_rd.range -= (s_res.range + EPS_L); - s_rd.start.mad(s_rd.dir, s_res.range + EPS_L); - s_res.range = R.range - s_rd.range - EPS_L; - r_temp.append_result(s_res); - } - else - { - d_rd.range = s_rd.range; - } - } - // test dynamic - if (R.tgt&d_mask) - { - // Traverse object database - g_SpatialSpace->q_ray(r_spatial, 0, d_flags, d_rd.start, d_rd.dir, d_rd.range); - for (u32 o_it = 0; o_it < r_spatial.size(); o_it++) - { - CObject* collidable = r_spatial[o_it]->dcast_CObject(); - if (0 == collidable) continue; - if (collidable == ignore_object) continue; - ICollisionForm* cform = collidable->collidable.model; - ECollisionFormType tp = collidable->collidable.model->Type(); - if (((R.tgt&(rqtObject | rqtObstacle)) && (tp == cftObject)) || ((R.tgt&rqtShape) && (tp == cftShape))) - { - if (tb&&!tb(d_rd, collidable, user_data))continue; - u32 r_cnt = r_temp.r_count(); - cform->_RayQuery(d_rd, r_temp); - for (int k = r_cnt; k < r_temp.r_count(); k++) - { - rq_result& d_res = *(r_temp.r_begin() + k); - d_res.range += d_range; - } - } - } - } - // set dynamic ray def - d_rd.start = s_rd.start; - d_range = R.range - s_rd.range; - if (r_temp.r_count()) - { - r_temp.r_sort(); - collide::rq_result* _I = r_temp.r_begin(); - collide::rq_result* _E = r_temp.r_end(); - for (; _I != _E; _I++) - { - r_dest.append_result(*_I); - if (!(CB ? CB(*_I, user_data) : TRUE)) return r_dest.r_count(); - if (R.flags&CDB::OPT_ONLYFIRST) return r_dest.r_count(); - } - } - if ((R.flags&(CDB::OPT_ONLYNEAREST | CDB::OPT_ONLYFIRST)) && r_dest.r_count()) return r_dest.r_count(); - } - while (r_temp.r_count()); - return r_dest.r_count(); -} - -BOOL CObjectSpace::_RayQuery(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object) -{ -#ifdef DEBUG - if (R.range < EPS || !_valid(R.range)) - Debug.fatal(DEBUG_INFO, "Invalid RayQuery range passed: %f.", R.range); -#endif - // initialize query - r_dest.r_clear(); - r_temp.r_clear(); - - Flags32 sd_test; - sd_test.assign(R.tgt); - rq_target next_test = R.tgt; - - rq_result s_res; - ray_defs s_rd(R.start, R.dir, R.range, CDB::OPT_ONLYNEAREST | R.flags, R.tgt); - ray_defs d_rd(R.start, R.dir, R.range, CDB::OPT_ONLYNEAREST | R.flags, R.tgt); - rq_target s_mask = rqtStatic; - rq_target d_mask = rq_target(((R.tgt&rqtObject) ? rqtObject : rqtNone) | - ((R.tgt&rqtObstacle) ? rqtObstacle : rqtNone) | - ((R.tgt&rqtShape) ? rqtShape : rqtNone)); - u32 d_flags = STYPE_COLLIDEABLE | ((R.tgt&rqtObstacle) ? STYPE_OBSTACLE : 0) | ((R.tgt&rqtShape) ? STYPE_SHAPE : 0); - - s_res.set(0, s_rd.range, -1); - do - { - if ((R.tgt&s_mask) && sd_test.is(s_mask) && (next_test&s_mask)) - { - s_res.set(0, s_rd.range, -1); - // Test static model - if (s_rd.range > EPS) - { - xrc.ray_options(s_rd.flags); - xrc.ray_query(&Static, s_rd.start, s_rd.dir, s_rd.range); - if (xrc.r_count()) - { - if (s_res.set_if_less(xrc.r_begin())) - { - // set new static start & range - s_rd.range -= (s_res.range + EPS_L); - s_rd.start.mad(s_rd.dir, s_res.range + EPS_L); - s_res.range = R.range - s_rd.range - EPS_L; -#ifdef DEBUG - if (!(fis_zero(s_res.range, EPS) || s_res.range >= 0.f)) - Debug.fatal(DEBUG_INFO, "Invalid RayQuery static range: %f (%f). /#1/", s_res.range, s_rd.range); -#endif - } - } - } - if (!s_res.valid()) sd_test.set(s_mask, FALSE); - } - if ((R.tgt&d_mask) && sd_test.is_any(d_mask) && (next_test&d_mask)) - { - r_temp.r_clear(); - - if (d_rd.range > EPS) - { - // Traverse object database - g_SpatialSpace->q_ray(r_spatial, 0, d_flags, d_rd.start, d_rd.dir, d_rd.range); - // Determine visibility for dynamic part of scene - for (u32 o_it = 0; o_it < r_spatial.size(); o_it++) - { - CObject* collidable = r_spatial[o_it]->dcast_CObject(); - if (0 == collidable) continue; - if (collidable == ignore_object) continue; - ICollisionForm* cform = collidable->collidable.model; - ECollisionFormType tp = collidable->collidable.model->Type(); - if (((R.tgt&(rqtObject | rqtObstacle)) && (tp == cftObject)) || ((R.tgt&rqtShape) && (tp == cftShape))) - { - if (tb&&!tb(d_rd, collidable, user_data))continue; - cform->_RayQuery(d_rd, r_temp); - } -#ifdef DEBUG - if (!((0 == r_temp.r_count()) || (r_temp.r_count() && (fis_zero(r_temp.r_begin()->range, EPS) || (r_temp.r_begin()->range >= 0.f))))) - Debug.fatal(DEBUG_INFO, "Invalid RayQuery dynamic range: %f (%f). /#2/", r_temp.r_begin()->range, d_rd.range); -#endif - } - } - if (r_temp.r_count()) - { - // set new dynamic start & range - rq_result& d_res = *r_temp.r_begin(); - d_rd.range -= (d_res.range + EPS_L); - d_rd.start.mad(d_rd.dir, d_res.range + EPS_L); - d_res.range = R.range - d_rd.range - EPS_L; -#ifdef DEBUG - if (!(fis_zero(d_res.range, EPS) || d_res.range >= 0.f)) - Debug.fatal(DEBUG_INFO, "Invalid RayQuery dynamic range: %f (%f). /#3/", d_res.range, d_rd.range); -#endif - } - else - { - sd_test.set(d_mask, FALSE); - } - } - if (s_res.valid() && r_temp.r_count()) - { - // all test return result - if (s_res.range < r_temp.r_begin()->range) - { - // static nearer - BOOL need_calc = CB ? CB(s_res, user_data) : TRUE; - next_test = need_calc ? s_mask : rqtNone; - r_dest.append_result(s_res); - } - else - { - // dynamic nearer - BOOL need_calc = CB ? CB(*r_temp.r_begin(), user_data) : TRUE; - next_test = need_calc ? d_mask : rqtNone; - r_dest.append_result(*r_temp.r_begin()); - } - } - else if (s_res.valid()) - { - // only static return result - BOOL need_calc = CB ? CB(s_res, user_data) : TRUE; - next_test = need_calc ? s_mask : rqtNone; - r_dest.append_result(s_res); - } - else if (r_temp.r_count()) - { - // only dynamic return result - BOOL need_calc = CB ? CB(*r_temp.r_begin(), user_data) : TRUE; - next_test = need_calc ? d_mask : rqtNone; - r_dest.append_result(*r_temp.r_begin()); - } - else - { - // nothing selected - next_test = rqtNone; - } - if ((R.flags&CDB::OPT_ONLYFIRST) || (R.flags&CDB::OPT_ONLYNEAREST)) break; - } - while (next_test != rqtNone); - return r_dest.r_count(); -} - -BOOL CObjectSpace::RayQuery(collide::rq_results& r_dest, ICollisionForm* target, const collide::ray_defs& R) -{ - VERIFY(target); - r_dest.r_clear(); - return target->_RayQuery(R, r_dest); -} diff --git a/src/xrEngine/xr_collide_defs.h b/src/xrEngine/xr_collide_defs.h deleted file mode 100644 index 19dfebb64b1..00000000000 --- a/src/xrEngine/xr_collide_defs.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef xr_collide_defsH -#define xr_collide_defsH -#pragma once - -class ENGINE_API CObject; -namespace collide -{ -struct tri -{ - Fvector e10; - float e10s; - Fvector e21; - float e21s; - Fvector e02; - float e02s; - Fvector p[3]; - Fvector N; - float d; -}; -struct elipsoid -{ - Fmatrix mL2W; // convertion from sphere(000,1) to real space - Fmatrix mW2L; // convertion from real space to sphere(000,1) -}; -struct ray_cache -{ - // previous state - Fvector start; - Fvector dir; - float range; - BOOL result; - - // cached vertices - Fvector verts[3]; - ray_cache() - { - start.set(0, 0, 0); - dir.set(0, 0, 0); - range = 0; - result = FALSE; - verts[0].set(0, 0, 0); - verts[1].set(0, 0, 0); - verts[2].set(0, 0, 0); - } - void set(const Fvector& _start, const Fvector& _dir, const float _range, const BOOL _result) - { - start = _start; - dir = _dir; - range = _range; - result = _result; - } - BOOL similar(const Fvector& _start, const Fvector& _dir, const float _range) - { - if (!_start.similar(start)) return FALSE; - if (!fsimilar(1.f, dir.dotproduct(_dir))) return FALSE; - if (!fsimilar(_range, range)) return FALSE; - return TRUE; - } -}; -enum rq_target -{ - rqtNone = (0), - rqtObject = (1 << 0), - rqtStatic = (1 << 1), - rqtShape = (1 << 2), - rqtObstacle = (1 << 3), - rqtBoth = (rqtObject | rqtStatic), - rqtDyn = (rqtObject | rqtShape | rqtObstacle) -}; -struct ray_defs -{ - Fvector start; - Fvector dir; - float range; - u32 flags; - rq_target tgt; - ray_defs(const Fvector& _start, const Fvector& _dir, float _range, u32 _flags, rq_target _tgt) - { - start = _start; - dir = _dir; - range = _range; - flags = _flags; - tgt = _tgt; - } -}; -struct rq_result -{ - CObject* O; // if NULL - static - float range; // range to intersection - int element; // номер кости/номер треугольника - IC rq_result& set(CObject* _O, float _range, int _element) - { - O = _O; - range = _range; - element = _element; - return *this; - } - IC BOOL set_if_less(CDB::RESULT* I) { if (I->range < range) { set(0, I->range, I->id); return TRUE; } else return FALSE; } - IC BOOL set_if_less(rq_result* R) { if (R->range < range) { set(R->O, R->range, R->element); return TRUE; } else return FALSE; } - IC BOOL set_if_less(CObject* _who, float _range, int _element) { if (_range < range) { set(_who, _range, _element); return TRUE; } else return FALSE; } - IC BOOL valid() { return (element >= 0); } -}; -DEFINE_VECTOR(rq_result, rqVec, rqIt); - -class rq_results -{ -protected: - rqVec results; - static bool r_sort_pred(const rq_result& a, const rq_result& b) { return a.range < b.range; } -public: - IC BOOL append_result(CObject* _who, float _range, int _element, BOOL bNearest) - { - if (bNearest&&!results.empty()) - { - rq_result& R = results.back(); - if (_range < R.range) - { - R.O = _who; - R.range = _range; - R.element = _element; - return TRUE; - } - return FALSE; - } - results.push_back(rq_result()); - rq_result& rq = results.back(); - rq.range = _range; - rq.element = _element; - rq.O = _who; - return TRUE; - } - IC void append_result(rq_result& res) - { - if (0 == results.capacity()) results.reserve(8); - results.push_back(res); - } - IC int r_count() { return results.size(); } - IC rq_result* r_begin() { return &*results.begin(); } - IC rq_result* r_end() { return &*results.end(); } - IC void r_clear() { results.clear_not_free(); } - IC void r_sort() { std::sort(results.begin(), results.end(), r_sort_pred); } - IC rqVec& r_results() { return results; } - -}; -typedef BOOL rq_callback(rq_result& result, LPVOID user_data); -typedef BOOL test_callback(const ray_defs& rd, CObject* object, LPVOID user_data); -}; -#endif