JNR
laTriangle3.cpp
1 /*
2 
3 Jump'n'Run Engine
4 http://www.atanaslaskov.com/jnr/
5 
6 BSD LICENSE
7 Copyright (c) 2007-2013, Atanas Laskov
8 All rights reserved.
9 
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 1. Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ATANAS LASKOV BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 */
29 
30 #include "stdafx.h"
31 #include "Core.h"
32 
33 #define VERRY_SMALL 0.000001
34 
35 #define TRIANLE_BACK_DIST 0.00001
36 #define TRIANGLE_SPACING 0.00000001
37 
38 #define TRIANLE_BACK_DIST 0.00001
39 
40 //#define M_MIN(a, b) ((a)<(b) ? (a):(b))
41 //#define M_MIN3(a,b,c) M_MIN(a, M_MIN(b, c))
42 
43 //#define M_MAX(a, b) ((a)>(b) ? (a):(b))
44 //#define M_MAX3(a,b,c) M_MAX(a, M_MAX(b, c))
45 
46 /*void laTriangle3::updateBB()
47 {
48  box.min[0] = M_MIN3(p[0].x(), p[1].x(), p[2].x())-VERRY_SMALL;
49  box.min[1] = M_MIN3(p[0].y(), p[1].y(), p[2].y())-VERRY_SMALL;
50  box.min[2] = M_MIN3(p[0].z(), p[1].z(), p[2].z())-VERRY_SMALL;
51 
52  box.max[0] = M_MAX3(p[0].x(), p[1].x(), p[2].x())+VERRY_SMALL;
53  box.max[1] = M_MAX3(p[0].y(), p[1].y(), p[2].y())+VERRY_SMALL;
54  box.max[2] = M_MAX3(p[0].z(), p[1].z(), p[2].z())+VERRY_SMALL;
55 }*/
56 
57 /*void laTriangle3::Validate()
58 {
59  bValid = 1;
60  if(p[0]==p[1])bValid=0;
61  if(p[0]==p[2])bValid=0;
62  if(p[1]==p[2])bValid=0;
63 }*/
64 
65 // Check if a point is inside the folume defined by the 3 planes,
66 // originating at the edges of the triangle
67 //
68 BOOL laTriangle3::isInsideVolume(laPoint3 &pt)
69 {
70  laPoint3 new_p[3];
71  new_p[0] = p[0] + pn.normal;
72  new_p[1] = p[1] + pn.normal;
73  new_p[2] = p[2] + pn.normal;
74 
75  laPlane3 pln[3];
76  pln[0].build(p[1], p[0], new_p[0]);
77  pln[1].build(p[2], p[1], new_p[1]);
78  pln[2].build(p[0], p[2], new_p[2]);
79 
80  if( (pln[0].distance(pt)>0) &&
81  (pln[1].distance(pt)>0) &&
82  (pln[2].distance(pt)>0) )
83  {
84  return TRUE;
85  }
86  return FALSE;
87 }
88 
89 void laTriangle3::wrapPoint(laPoint3 &p)
90 {
91  double len_xz = sqrt(p.x()*p.x() + p.z()*p.z());
92  double len_xy = sqrt(p.x()*p.x() + p.y()*p.y());
93 
94  laPoint3 oz;
95  oz.x(0); oz.y(0); oz.z(1);
96 
97  laPoint3 oy;
98  oz.x(0); oz.y(1); oz.z(0);
99 
100  //ry
101  laPoint3 p_xz = p;
102  p_xz[1] = 0;
103 
104  laPoint3 n_xz = pn.normal;
105  n_xz[1] = 0;
106 
107  double ry = p_xz.angle(oz) + n_xz.angle(oz);
108 
109  //rz
110  laPoint3 p_xy = p;
111  p_xz[2] = 0;
112 
113  laPoint3 n_xy = pn.normal;
114  n_xz[2] = 0;
115 
116  double rz = p_xy.angle(oy) + n_xy.angle(oy);
117  //if(rz>=3.14 ||rz<0){rz=0; len_xy=0; }
118 
119  //double ry_sin = pn.n.z();
120  //double ry_cos = pn.n.x();
121 
122  //double ry = xz.Ang(ox);
123  //double rx = yz.Ang(oy);
124 
125  //laPoint3 p2 = p;
126 
127  //rz
128  if( len_xy>=0.001 ){
129  p[0] = sin(rz)*len_xy;
130  p[1] = cos(rz)*len_xy;
131  }
132  //if(n_yz.y()>0) p2[1] = -p2.y();
133 
134  //p2[0] = + sin(ry);//*p2.z();
135  //p2[2] = - cos(ry);//*p2.z();
136 
137  //ry
138  //if(len_xz!=0){
139  // p2[0] = cos(ry)*len_xz; //*p2.z();
140  // p2[2] = sin(ry)*len_xz; //*p2.z();
141  //}
142  //if(n_xz.x()>0) p2[0] = -p2.x();
143 
144  //char c[200];
145  //sprintf(c, "a:%.2f nx:%.2f ny:%.2f", rz*(180/3.14), n_xy.x(), n_xy.y());
146  //TextOut(g_hDC, 0, 0, c, strlen(c));
147 
148  //p = p2;
149 }
150 
151 #define PUSH_LINE(a, b) { arv[vcnt] = b - a; /*arv[vcnt].Minus(a);*/ vcnt++; }
152 
153 // Collisiton detection and repsonse
154 //
155 // t - triangle to collide with
156 // vt - velocity; outputs modified velocity
157 //
158 laPoint3 laTriangle3::collide(laTriangle3 &t, laPoint3 &vt)
159 {
160  //Simple test
161  //NOTE: t.box must be inflated!
162  //if(!t.box.IsBoxSeparate(box) )return vt;
163  //if(!bValid) return vt;
164  //if(!t.bValid) return vt;
165 
166  //Data
167  unsigned i, itri, imy;
168  laPoint3 p;
169  double k;
170  laLine3 ar_tri_procet_lines[3];
171  laLine3 ar_my_lines[3];
172  laTriangle3 tri_proect;
173 
174  //Initial
175  laPoint3 vok;
176  laPoint3 v_norm_minus;
177  laPoint3 v_minus;
178  vok = vt;
179  v_norm_minus = vt;
180  v_norm_minus = -1*v_norm_minus;//.Invert();
181  v_norm_minus = v_norm_minus/v_norm_minus.lenght(); //.Normalise();
182 
183  v_minus = vt;
184  v_minus = -1*v_minus; //.Invert();
185 
186  //Back side removal (NOTE: Normalite sa mi na obrratno!:()
187  laPoint3 b = this->p[0] + vt;
188  if(pn.distance(b)<=0) return vt;
189 
190  //Critical lines list
191  laPoint3 arv[20];
192  unsigned vcnt=0;
193 
194  //Tr Vertex In Me
195  for(i=0; i<3; i++)
196  {
197  laLine3 ln;
198 
199  ln.build_vec(t.p[i], vt);
200  p = ln.intersection(pn, &k);
201  tri_proect.p[i] = p;
202 
203  if((k>=0) && (k<=1)) if(isInsideVolume(p))
204  {
205  //if( (pn.GetDist(t.p[i])<0) )
206  //if(pn.GetDist(t.p[i])<0) //!!!
207  /*if(!l)*/ PUSH_LINE(t.p[i], p);
208  }
209  }
210 
211  //tri_proect.Validate();
212  //if(!tri_proect.bValid)return vt;
213 
214  //My Vertex In Tr
215  for(i=0; i<3; i++)
216  {
217  laLine3 ln;
218 
219  ln.build_vec(this->p[i], v_minus);
220  p = ln.intersection(t.pn, &k);
221 
222  if((k>=0) && (k<=1)) if(t.isInsideVolume(p))
223  {
224  //if( (t.pn.GetDist(this->p[i])<0) )
225  //if(t.pn.GetDist(this->p[i])>0) //!!!
226  /*if(!l)*/ PUSH_LINE(p, this->p[i]);
227  }
228  }
229 
230  //Line
231  laLine3 *p_ln_my;
232  laLine3 *p_ln_pro_tri;
233 
234  getPerimeterLines(ar_my_lines);
235  tri_proect.getPerimeterLines(ar_tri_procet_lines);
236 
237  for(itri=0; itri<3; itri++)
238  {
239  p_ln_pro_tri = ar_tri_procet_lines+itri;
240 
241  for(imy=0; imy<3; imy++)
242  {
243  p_ln_my = ar_my_lines+imy;
244 
245  double k1, k2;
246 
247  laPoint3 p = p_ln_my->intersection(*p_ln_pro_tri, k1);
248  p_ln_pro_tri->intersection(*p_ln_my, k2);
249 
250  if((k1>=0) && (k1<=1)) if((k2>=0) && (k2<=1))
251  {
252  double k;
253  laLine3 l;
254  laPoint3 tr_p;
255 
256  l.build_vec(p, v_minus);
257  tr_p = l.intersection(t.pn, &k);
258 
259  if((k>=0) && (k<=1))
260  {
261  PUSH_LINE(tr_p, p);
262  }
263  }
264  }
265  }
266 
267  for(i=0; i<vcnt; i++)
268  {
269  if(fabs(arv[i].x())<fabs(vok.x()))
270  {
271  vok[0] = arv[i].x() + v_norm_minus.x()*TRIANLE_BACK_DIST;
272  }
273  if(fabs(arv[i].y())<fabs(vok.y()))
274  {
275  vok[1] = arv[i].y() + v_norm_minus.y()*TRIANLE_BACK_DIST;
276  }
277  if(fabs(arv[i].z())<fabs(vok.z()))
278  {
279  vok[2] = arv[i].z() + v_norm_minus.z()*TRIANLE_BACK_DIST;
280  }
281  }
282 
283  // Collision Response
284  //
285  laPoint3 r;
286  r = vt - vok;
287 
288  if( (r.lenght()>TRIANLE_BACK_DIST) /*&& (responce)*/ )
289  {
290 
291  laPoint3 b = r + this->p[0];
292 
293  laLine3 l;
294  l.build_vec(b, this->pn.normal);
295 
296  laPoint3 c;
297  double k;
298  c = l.intersection(pn, &k);
299 
300  laPoint3 vresp = c - this->p[0];
301  vok = vok + vresp;
302 
303  laPoint3 n;
304  n = pn.normal * TRIANLE_BACK_DIST;
305  vok = vok - n;
306 
307  //vok[0] += v_norm_minus.x()*TRIANLE_BACK_DIST;
308  //vok[1] += v_norm_minus.y()*TRIANLE_BACK_DIST;
309  //vok[2] += v_norm_minus.z()*TRIANLE_BACK_DIST;
310  }
311 
312  return vok;
313 }
laPoint3 intersection(laLine3 &l, double &pk1)
Find point of intersection (or nearest point) to another laLine3.
Definition: laLine3.cpp:48
3D line segment
Definition: laLine3.h:40
void build(laPoint3 &a, laPoint3 &b, laPoint3 &c)
Build laPlane3 from three points ( laPoint3 objects )
Definition: laPlane3.h:55
laPoint3 normal
Normal vector.
Definition: laPlane3.h:43
void build_vec(laPoint3 &a, laPoint3 &v)
Build from an end-poind and vector.
Definition: laLine3.h:60
laPoint3 p[3]
Vertices of the triangle.
Definition: laTriangle3.h:44
laPlane3 pn
Parametric 3D plane.
Definition: laTriangle3.h:45
3D plane
Definition: laPlane3.h:39
3D triangle face NOTE: This class has not been tested (NT)
Definition: laTriangle3.h:40
double distance(laPoint3 &p)
Find the shortest distance between a point and the plane.
Definition: laPlane3.h:81