afxCurve3D.cpp

Engine/source/afx/util/afxCurve3D.cpp

More...

Detailed Description

  1
  2
  3//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  4// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  5// Copyright (C) 2015 Faust Logic, Inc.
  6//
  7// Permission is hereby granted, free of charge, to any person obtaining a copy
  8// of this software and associated documentation files (the "Software"), to
  9// deal in the Software without restriction, including without limitation the
 10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 11// sell copies of the Software, and to permit persons to whom the Software is
 12// furnished to do so, subject to the following conditions:
 13//
 14// The above copyright notice and this permission notice shall be included in
 15// all copies or substantial portions of the Software.
 16//
 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 23// IN THE SOFTWARE.
 24//
 25//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 26
 27#include "afx/arcaneFX.h"
 28#include "afx/util/afxCurveEval.h"
 29#include "afx/util/afxCurve3D.h"
 30
 31afxCurve3D::afxCurve3D() : usable( false ), default_vector( 0, 0, 0 ), flip(false)
 32{
 33   evaluator = new afxHermiteEval();
 34}
 35
 36afxCurve3D::~afxCurve3D()
 37{
 38   delete evaluator;
 39}
 40
 41void afxCurve3D::addPoint( F32 param, Point3F &v )
 42{
 43   if( param < 0.0f || param > 1.0f )
 44      return;
 45
 46   CurvePoint p;
 47   p.parameter = param;
 48   p.point.set( v );
 49   
 50   points.push_back( p );  
 51
 52   usable = false;   
 53}  
 54
 55void afxCurve3D::setPoint( int index, Point3F &v )
 56{
 57   if( ( index < 0 ) || ( index >= points.size() ) )
 58      return;
 59
 60   CurvePoint &p = points[index];
 61   p.point = v;
 62
 63   if( index == 0 )
 64      start_value = v;
 65   else if( index == points.size()-1 )
 66      final_value = v;
 67}
 68
 69//bool afxCurve3D::compare_CurvePoint( const afxCurve3D::CurvePoint &a, const afxCurve3D::CurvePoint &b ) 
 70//{
 71// return a.parameter < b.parameter;
 72//}
 73
 74S32 QSORT_CALLBACK afxCurve3D::compare_CurvePoint( const void* a, const void* b )
 75{
 76   //CurvePoint *cp_a = *((CurvePoint **)a);
 77  //CurvePoint *cp_b = *((CurvePoint **)b);
 78  
 79   const CurvePoint *cp_a = (CurvePoint *)a;
 80   const CurvePoint *cp_b = (CurvePoint *)b;
 81
 82  //Con::printf( "*** %f %f", cp_a->parameter, cp_b->parameter  );
 83
 84   //return cp_a->parameter < cp_b->parameter;
 85   //return 1;
 86
 87   if (cp_a->parameter > cp_b->parameter)
 88      return 1;
 89   else if (cp_a->parameter < cp_b->parameter)
 90      return -1;
 91   else
 92      return 0;
 93}
 94
 95void afxCurve3D::sort( )
 96{
 97   if( points.size() == 0 )
 98      return;
 99
100   if( points.size() == 1 )
101   {
102      start_value   = points[0].point;
103      final_value   = start_value;
104      usable = true;
105      return;
106   }
107
108   //Con::printf( "*** pre-sort" );
109   //std::sort( points.begin(), points.end(), afxCurve3D::compare_CurvePoint );
110   dQsort( points.address(), points.size(), sizeof(CurvePoint), afxCurve3D::compare_CurvePoint );
111   //Con::printf( "*** post-sort" );
112
113   start_value = points[0].point;
114   final_value = points[points.size()-1].point;
115
116   usable = true;
117
118   start_tangent = evaluateTangent( 0.0f );
119   final_tangent = evaluateTangent( 1.0f );
120}  
121
122int afxCurve3D::numPoints()
123{
124   return points.size();
125}
126
127F32 afxCurve3D::getParameter( int index )
128{
129   if( ( index < 0 ) || ( index >= points.size() ) )
130      return 0.0f;
131
132   return points[index].parameter;
133}
134
135Point3F afxCurve3D::getPoint( int index )
136{
137   if( ( index < 0 ) || ( index >= points.size() ) )
138      return default_vector;
139
140   return points[index].point;
141}
142
143Point3F afxCurve3D::evaluate( F32 param )
144{
145   if( !usable )
146      return default_vector;
147
148   if( param <= 0.0f )
149      return start_value;
150   
151   if( param >= 1.0f )
152      return final_value;
153
154   if( points.size() == 1 )
155      return start_value;
156
157   int start_index = 0;
158   for( ; start_index < points.size()-1; start_index++ )
159   {
160      if( param < points[start_index+1].parameter )
161         break;
162   }
163   int end_index = start_index+1;
164
165   CurvePoint p0 = points[start_index];
166   CurvePoint p1 = points[end_index];
167
168   // Compute tangents
169   //Point3F tan0 = computeTangentP0( p0.point, p1.point, start_index );
170   //Point3F tan1 = computeTangentP1( p0.point, p1.point, end_index );
171   
172
173   F32 local_param = ( param - p0.parameter ) / ( p1.parameter - p0.parameter );
174
175   //Point3F vnew = evaluator->evaluateCurve( p0.point,
176   //                                                          p1.point,
177   //                                                          tan0,
178   //                                                          tan1,
179   //                                                          local_param );
180
181   Point3F vnew = evaluator->evaluateCurve( p0.point,   p1.point,
182                                            p0.tangent, p1.tangent,
183                                            local_param );
184   return vnew;
185}
186
187Point3F afxCurve3D::evaluateTangent( F32 param )
188{
189   if( !usable )
190      return default_vector;
191
192   if( param < 0.0f )
193      return start_tangent;
194   
195   if( param > 1.0f )
196      return final_tangent;
197
198   if( points.size() == 1 )
199      return start_tangent;
200
201   int start_index = 0;
202   for( ; start_index < points.size()-1; start_index++ )
203   {
204      if( param < points[start_index+1].parameter )
205         break;
206   }
207   int end_index = start_index+1;
208
209   if( param == 1.0f )
210   {
211      end_index = points.size()-1;
212      start_index = end_index - 1;
213   }
214
215   CurvePoint p0 = points[start_index];
216   CurvePoint p1 = points[end_index];
217   
218   // Compute tangents
219   //Point3F tan0 = computeTangentP0( p0.point, p1.point, start_index );
220   //Point3F tan1 = computeTangentP1( p0.point, p1.point, end_index );
221
222   F32 local_param = ( param - p0.parameter ) / ( p1.parameter - p0.parameter );
223
224   //Point3F vnew = evaluator->evaluateCurveTangent( p0.point,
225   //                                                                      p1.point,
226   //                                                                      tan0,
227   //                                                                      tan1,
228   //                                                                      local_param );
229   Point3F vnew = evaluator->evaluateCurveTangent( p0.point,   p1.point,
230                                                   p0.tangent, p1.tangent,
231                                                   local_param );
232
233   return vnew;
234}
235
236Point3F afxCurve3D::computeTangentP0( Point3F &p0, Point3F &p1, int start_index )
237{
238   Point3F tan0;
239   
240   Point3F p_prev;
241   Point3F p_next;
242
243      // tangent for p0
244   if( start_index == 0 )
245   {
246      p_prev = p0;   // Setting previous point to p0, creating a hidden point in
247                              //  the same spot
248      p_next = p1;
249   }
250   else
251   {
252      CurvePoint &p = points[start_index-1];
253      p_prev = p.point;
254      p_next = p1;
255   }
256   tan0 = p_next-p_prev; //p_next.subtract( p_prev );
257   tan0 *= .5f; //= tan0.scale( .5f );
258
259   return tan0;
260}
261
262Point3F afxCurve3D::computeTangentP1( Point3F &p0, Point3F &p1, int end_index )
263{
264   Point3F tan1;
265   
266   Point3F p_prev;
267   Point3F p_next;
268
269      // tangent for p1
270   if( end_index == points.size()-1 )
271   {
272      p_prev = p0;  
273      p_next = p1;   // Setting next point to p1, creating a hidden point in
274                           //  the same spot
275   }
276   else
277   {
278      p_prev = p0;
279      CurvePoint &p = points[end_index+1];
280      p_next = p.point;
281   }
282   tan1 = p_next-p_prev; //p_next.subtract( p_prev );
283   tan1 *= .5f; //= tan1.scale( .5f );
284
285   //Con::printf("UPDATE");
286   return tan1;
287}
288
289void afxCurve3D::computeTangents()
290{
291   CurvePoint *p_prev;
292   CurvePoint *p_next;
293
294   for( int i = 0; i < points.size(); i++ )
295   {
296      CurvePoint *p = &points[i];
297      
298      if( i == 0 )
299      {
300         p_prev = p;    // Setting previous point to p0, creating a hidden point in
301                        //  the same spot
302         p_next = &points[i+1];
303      }
304      else if( i == points.size()-1 )
305      {
306         p_prev = &points[i-1];  
307         p_next = p;    // Setting next point to p1, creating a hidden point in
308                        //  the same spot
309      }
310      else
311      {        
312         p_prev = &points[i-1];
313         p_next = &points[i+1];
314      }
315
316      p->tangent = p_next->point - p_prev->point;
317      //(p->tangent).normalize();
318      p->tangent *= .5f;
319
320      //Con::printf( "%d: %f %f %f", i, p->tangent.x, p->tangent.y, p->tangent.z );
321   }
322}
323
324void afxCurve3D::print()
325{
326   Con::printf( "afxCurve3D -------------------------" );
327   for( int i = 0; i < points.size(); i++ )
328   {
329      CurvePoint &p = points[i];
330      Con::printf( "%f: %f %f %f", p.parameter, p.point.x, p.point.y, p.point.z );
331   }
332   Con::printf( "---------------------------------" );
333}
334