@@ -28,7 +28,7 @@ enum EFC_Visible
2828
2929#define FRUSTUM_SAFE (FRUSTUM_MAXPLANES*4 )
3030typedef svector<Fvector,FRUSTUM_SAFE> sPoly ;
31- extern u32 frustum_aabb_remap[8 ][6 ];
31+ extern XRCORE_API u32 frustum_aabb_remap[8 ][6 ];
3232
3333class XRCORE_API CFrustum
3434{
@@ -71,22 +71,156 @@ class XRCORE_API CFrustum
7171 void CreateFromPortal (sPoly * P, Fvector& vPN, Fvector& vBase, Fmatrix& mFullXFORM );
7272 void CreateFromPlanes (Fplane* p, int count);
7373
74- sPoly * ClipPoly (sPoly & src, sPoly & dest) const ;
74+ ICF sPoly * ClipPoly (sPoly & S, sPoly & D) const
75+ {
76+ sPoly * src = &D;
77+ sPoly * dest = &S;
78+ for (int i = 0 ; i < p_count; i++)
79+ {
80+ // cache plane and swap lists
81+ const fplane& P = planes[i];
82+ std::swap (src, dest);
83+ dest->clear ();
84+
85+ // classify all points relative to plane #i
86+ float cls[FRUSTUM_SAFE];
87+ for (u32 j = 0 ; j < src->size (); j++) cls[j] = P.classify ((*src)[j]);
88+
89+ // clip everything to this plane
90+ cls[src->size ()] = cls[0 ];
91+ src->push_back ((*src)[0 ]);
92+ Fvector D_; float denum, t;
93+ for (u32 j = 0 ; j < src->size () - 1 ; j++)
94+ {
95+ if ((*src)[j].similar ((*src)[j + 1 ], EPS_S)) continue ;
96+
97+ if (negative (cls[j]))
98+ {
99+ dest->push_back ((*src)[j]);
100+ if (positive (cls[j + 1 ]))
101+ {
102+ // segment intersects plane
103+ D_.sub ((*src)[j + 1 ], (*src)[j]);
104+ denum = P.n .dotproduct (D_);
105+ if (denum != 0 ) {
106+ t = -cls[j] / denum; // VERIFY(t<=1.f && t>=0);
107+ dest->last ().mad ((*src)[j], D_, t);
108+ dest->inc ();
109+ }
110+ }
111+ }
112+ else {
113+ // J - outside
114+ if (negative (cls[j + 1 ]))
115+ {
116+ // J+1 - inside
117+ // segment intersects plane
118+ D_.sub ((*src)[j + 1 ], (*src)[j]);
119+ denum = P.n .dotproduct (D_);
120+ if (denum != 0 ) {
121+ t = -cls[j] / denum; // VERIFY(t<=1.f && t>=0);
122+ dest->last ().mad ((*src)[j], D_, t);
123+ dest->inc ();
124+ }
125+ }
126+ }
127+ }
128+
129+ // here we end up with complete polygon in 'dest' which is inside plane #i
130+ if (dest->size () < 3 ) return 0 ;
131+ }
132+ return dest;
133+ }
75134
76135 u32 getMask () const { return (1 <<p_count)-1 ; }
77136
78- EFC_Visible testSphere (Fvector& c, float r, u32 & test_mask) const ;
79- BOOL testSphere_dirty (const Fvector& c, float r) const ;
80- EFC_Visible testAABB (const float * mM , u32 & test_mask) const ;
81- EFC_Visible testSAABB (Fvector& c, float r, const float * mM , u32 & test_mask) const ;
82- BOOL testPolyInside_dirty (Fvector* p, int count) const ;
137+ ICF EFC_Visible testSphere (Fvector& c, float r, u32 & test_mask) const
138+ {
139+ u32 bit = 1 ;
140+ for (int i = 0 ; i < p_count; i++, bit <<= 1 )
141+ {
142+ if (test_mask & bit) {
143+ float cls = planes[i].classify (c);
144+ if (cls > r) { test_mask = 0 ; return fcvNone; } // none - return
145+ if (_abs (cls) >= r) test_mask &= ~bit; // fully - no need to test this plane
146+ }
147+ }
148+ return test_mask ? fcvPartial : fcvFully;
149+ }
150+
151+ ICF BOOL testSphere_dirty (const Fvector& c, float r) const
152+ {
153+ switch (p_count) {
154+ case 12 :if (planes[11 ].classify (c) > r) return FALSE ;
155+ case 11 :if (planes[10 ].classify (c) > r) return FALSE ;
156+ case 10 :if (planes[9 ].classify (c) > r) return FALSE ;
157+ case 9 : if (planes[8 ].classify (c) > r) return FALSE ;
158+ case 8 : if (planes[7 ].classify (c) > r) return FALSE ;
159+ case 7 : if (planes[6 ].classify (c) > r) return FALSE ;
160+ case 6 : if (planes[5 ].classify (c) > r) return FALSE ;
161+ case 5 : if (planes[4 ].classify (c) > r) return FALSE ;
162+ case 4 : if (planes[3 ].classify (c) > r) return FALSE ;
163+ case 3 : if (planes[2 ].classify (c) > r) return FALSE ;
164+ case 2 : if (planes[1 ].classify (c) > r) return FALSE ;
165+ case 1 : if (planes[0 ].classify (c) > r) return FALSE ;
166+ case 0 : break ;
167+ default : NODEFAULT;
168+ }
169+ return TRUE ;
170+ }
171+ ICF EFC_Visible testAABB (const float * mM , u32 & test_mask) const
172+ {
173+ // go for trivial rejection or acceptance using "faster overlap test"
174+ u32 bit = 1 ;
175+
176+ for (int i = 0 ; i < p_count; i++, bit <<= 1 )
177+ {
178+ if (test_mask & bit) {
179+ EFC_Visible r = AABB_OverlapPlane (planes[i], mM );
180+ if (fcvFully == r) test_mask &= ~bit; // fully - no need to test this plane
181+ else if (fcvNone == r) { test_mask = 0 ; return fcvNone; } // none - return
182+ }
183+ }
184+ return test_mask ? fcvPartial : fcvFully;
185+ }
186+
187+ ICF EFC_Visible testSAABB (Fvector& c, float r, const float * mM , u32 & test_mask) const
188+ {
189+ u32 bit = 1 ;
190+ for (int i = 0 ; i < p_count; i++, bit <<= 1 )
191+ {
192+ if (test_mask & bit) {
193+ float cls = planes[i].classify (c);
194+ if (cls > r) { test_mask = 0 ; return fcvNone; } // none - return
195+ if (_abs (cls) >= r) test_mask &= ~bit; // fully - no need to test this plane
196+ else {
197+ EFC_Visible r_ = AABB_OverlapPlane (planes[i], mM );
198+ if (fcvFully == r_) test_mask &= ~bit; // fully - no need to test this plane
199+ else if (fcvNone == r_) { test_mask = 0 ; return fcvNone; } // none - return
200+ }
201+ }
202+ }
203+ return test_mask ? fcvPartial : fcvFully;
204+ }
205+
206+ ICF BOOL testPolyInside_dirty (Fvector* p, int count) const
207+ {
208+ Fvector* e = p + count;
209+ for (int i = 0 ; i < p_count; i++)
210+ {
211+ const fplane& P = planes[i];
212+ for (Fvector* I = p; I != e; I++)
213+ if (P.classify (*I) > 0 ) return false ;
214+ }
215+ return true ;
216+ }
83217
84- IC BOOL testPolyInside (sPoly & src) const
218+ ICF BOOL testPolyInside (sPoly & src) const
85219 {
86220 sPoly d;
87221 return !!ClipPoly (src,d);
88222 }
89- IC BOOL testPolyInside (Fvector* p, int count) const
223+ ICF BOOL testPolyInside (Fvector* p, int count) const
90224 {
91225 sPoly src (p,count);
92226 return testPolyInside (src);
0 commit comments