afxCurve3D.cpp
Engine/source/afx/util/afxCurve3D.cpp
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