afxXM_PathConform.cpp
Engine/source/afx/xm/afxXM_PathConform.cpp
Classes:
class
Public Functions
ConsoleDocClass(afxXM_PathConformData , "@brief An xmod <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxXMods\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(afxXM_PathConformData , "@brief An xmod <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxXMods\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
IMPLEMENT_CO_DATABLOCK_V1(afxXM_PathConformData )
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 29#include "math/mathIO.h" 30#include "math/mathUtils.h" 31 32#include "afx/afxEffectWrapper.h" 33#include "afx/afxChoreographer.h" 34#include "afx/xm/afxXfmMod.h" 35#include "afx/util/afxPath3D.h" 36#include "afx/util/afxPath.h" 37 38//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 39// PATH CONFORM 40 41class afxPathData; 42 43class afxXM_PathConformData : public afxXM_WeightedBaseData 44{ 45 typedef afxXM_WeightedBaseData Parent; 46 47public: 48 StringTableEntry paths_string; // 49 Vector<afxPathData*> pathDataBlocks; // datablocks for paths 50 Vector<U32> pathDataBlockIds; // datablock IDs which correspond to the pathDataBlocks 51 F32 path_mult; 52 F32 path_time_offset; 53 bool orient_to_path; 54 55public: 56 /*C*/ afxXM_PathConformData(); 57 /*C*/ afxXM_PathConformData(const afxXM_PathConformData&, bool = false); 58 59 bool onAdd(); 60 bool preload(bool server, String &errorStr); 61 void packData(BitStream* stream); 62 void unpackData(BitStream* stream); 63 64 virtual bool allowSubstitutions() const { return true; } 65 66 static void initPersistFields(); 67 68 afxXM_Base* create(afxEffectWrapper* fx, bool on_server); 69 70 DECLARE_CONOBJECT(afxXM_PathConformData); 71 DECLARE_CATEGORY("AFX"); 72}; 73 74class afxPath3D; 75class afxAnimCurve; 76 77class afxXM_PathConform : public afxXM_WeightedBase 78{ 79 typedef afxXM_WeightedBase Parent; 80 81 afxXM_PathConformData* db; 82 83 Vector<afxPath3D*> paths; 84 Vector<F32> path_mults; 85 Vector<F32> path_time_offsets; 86 Vector<afxAnimCurve*> rolls; 87 88 void init_paths(F32 lifetime); 89 90public: 91 /*C*/ afxXM_PathConform(afxXM_PathConformData*, afxEffectWrapper*); 92 /*D*/ ~afxXM_PathConform(); 93 94 virtual void start(F32 timestamp); 95 virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params); 96}; 97 98//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 99 100IMPLEMENT_CO_DATABLOCK_V1(afxXM_PathConformData); 101 102ConsoleDocClass( afxXM_PathConformData, 103 "@brief An xmod datablock.\n\n" 104 105 "@ingroup afxXMods\n" 106 "@ingroup AFX\n" 107 "@ingroup Datablocks\n" 108); 109 110afxXM_PathConformData::afxXM_PathConformData() 111{ 112 paths_string = ST_NULLSTRING; 113 pathDataBlocks.clear(); 114 pathDataBlockIds.clear(); 115 path_mult = 1.0f; 116 path_time_offset = 0.0f; 117 orient_to_path = false; 118} 119 120afxXM_PathConformData::afxXM_PathConformData(const afxXM_PathConformData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone) 121{ 122 paths_string = other.paths_string; 123 pathDataBlocks = other.pathDataBlocks; 124 pathDataBlockIds = other.pathDataBlockIds; 125 path_mult = other.path_mult; 126 path_time_offset = other.path_time_offset; 127 orient_to_path = other.orient_to_path; 128} 129 130void afxXM_PathConformData::initPersistFields() 131{ 132 addField("paths", TypeString, Offset(paths_string, afxXM_PathConformData), 133 "..."); 134 addField("pathMult", TypeF32, Offset(path_mult, afxXM_PathConformData), 135 "..."); 136 addField("pathTimeOffset", TypeF32, Offset(path_time_offset, afxXM_PathConformData), 137 "..."); 138 addField("orientToPath", TypeBool, Offset(orient_to_path, afxXM_PathConformData), 139 "..."); 140 141 Parent::initPersistFields(); 142 143 // disallow some field substitutions 144 disableFieldSubstitutions("paths"); 145} 146 147void afxXM_PathConformData::packData(BitStream* stream) 148{ 149 Parent::packData(stream); 150 151 stream->write(pathDataBlockIds.size()); 152 for (int i = 0; i < pathDataBlockIds.size(); i++) 153 stream->write(pathDataBlockIds[i]); 154 stream->write(path_mult); 155 stream->write(path_time_offset); 156 stream->write(orient_to_path); 157} 158 159void afxXM_PathConformData::unpackData(BitStream* stream) 160{ 161 Parent::unpackData(stream); 162 163 U32 n_db; 164 stream->read(&n_db); 165 pathDataBlockIds.setSize(n_db); 166 for (U32 i = 0; i < n_db; i++) 167 stream->read(&pathDataBlockIds[i]); 168 stream->read(&path_mult); 169 stream->read(&path_time_offset); 170 stream->read(&orient_to_path); 171} 172 173bool afxXM_PathConformData::onAdd() 174{ 175 if (Parent::onAdd() == false) 176 return false; 177 178 if (paths_string != ST_NULLSTRING) 179 { 180 //Con::printf("afxEffectWrapperData: Path string found: %s", paths_string); 181 } 182 183 if (paths_string != ST_NULLSTRING && paths_string[0] == '\0') 184 { 185 Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) empty paths string, invalid datablock", getName()); 186 return false; 187 } 188 189 if (paths_string != ST_NULLSTRING && dStrlen(paths_string) > 255) 190 { 191 Con::errorf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) paths string too long [> 255 chars]", getName()); 192 return false; 193 } 194 195 if (paths_string != ST_NULLSTRING) 196 { 197 Vector<char*> dataBlocks(__FILE__, __LINE__); 198 dsize_t tokCopyLen = dStrlen(paths_string) + 1; 199 char* tokCopy = new char[tokCopyLen]; 200 dStrcpy(tokCopy, paths_string, tokCopyLen); 201 202 char* currTok = dStrtok(tokCopy, " \t"); 203 while (currTok != NULL) 204 { 205 dataBlocks.push_back(currTok); 206 currTok = dStrtok(NULL, " \t"); 207 } 208 if (dataBlocks.size() == 0) 209 { 210 Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) invalid paths string. No datablocks found", getName()); 211 delete [] tokCopy; 212 return false; 213 } 214 pathDataBlocks.clear(); 215 pathDataBlockIds.clear(); 216 217 for (U32 i = 0; i < dataBlocks.size(); i++) 218 { 219 afxPathData* pData = NULL; 220 if (Sim::findObject(dataBlocks[i], pData) == false) 221 { 222 Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) unable to find path datablock: %s", getName(), dataBlocks[i]); 223 } 224 else 225 { 226 pathDataBlocks.push_back(pData); 227 pathDataBlockIds.push_back(pData->getId()); 228 } 229 } 230 delete [] tokCopy; 231 if (pathDataBlocks.size() == 0) 232 { 233 Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) unable to find any path datablocks", getName()); 234 return false; 235 } 236 } 237 238 239 return true; 240} 241 242bool afxXM_PathConformData::preload(bool server, String &errorStr) 243{ 244 if (!Parent::preload(server, errorStr)) 245 return false; 246 247 pathDataBlocks.clear(); 248 for (U32 i = 0; i < pathDataBlockIds.size(); i++) 249 { 250 afxPathData* pData = NULL; 251 if (Sim::findObject(pathDataBlockIds[i], pData) == false) 252 { 253 Con::warnf(ConsoleLogEntry::General, 254 "afxEffectWrapperData(%s) unable to find path datablock: %d", 255 getName(), pathDataBlockIds[i]); 256 } 257 else 258 pathDataBlocks.push_back(pData); 259 } 260 261 return true; 262} 263 264afxXM_Base* afxXM_PathConformData::create(afxEffectWrapper* fx, bool on_server) 265{ 266 afxXM_PathConformData* datablock = this; 267 268 if (getSubstitutionCount() > 0) 269 { 270 datablock = new afxXM_PathConformData(*this, true); 271 this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex()); 272 } 273 274 return new afxXM_PathConform(datablock, fx); 275} 276 277//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// 278 279afxXM_PathConform::afxXM_PathConform(afxXM_PathConformData* db, afxEffectWrapper* fxw) 280 : afxXM_WeightedBase(db, fxw) 281{ 282 this->db = db; 283} 284 285afxXM_PathConform::~afxXM_PathConform() 286{ 287 for (S32 i = 0; i < paths.size(); i++) 288 if (paths[i]) 289 delete paths[i]; 290 291 for (S32 j = 0; j < paths.size(); j++) 292 if (rolls[j]) 293 delete rolls[j]; 294} 295 296void afxXM_PathConform::start(F32 timestamp) 297{ 298 init_paths(fx_wrapper->getFullLifetime()); 299} 300 301void afxXM_PathConform::init_paths(F32 lifetime) 302{ 303 for( U32 i=0; i < db->pathDataBlocks.size(); i++ ) 304 { 305 afxPathData* pd = db->pathDataBlocks[i]; 306 if (!pd) 307 continue; 308 309 if (pd->getSubstitutionCount() > 0) 310 { 311 afxPathData* orig_db = pd; 312 pd = new afxPathData(*orig_db, true); 313 orig_db->performSubstitutions(pd, fx_wrapper->getChoreographer(), fx_wrapper->getGroupIndex()); 314 } 315 316 if (pd->num_points > 0) 317 { 318 if (pd->lifetime == 0) 319 { 320 if (lifetime <= 0) 321 { 322 // Is this possible or is the lifetime always inherited properly??? 323 } 324 else 325 { 326 pd->lifetime = lifetime; 327 } 328 } 329 330 F32 pd_delay = pd->delay*time_factor; 331 F32 pd_lifetime = pd->lifetime*time_factor; 332 F32 pd_time_offset = pd->time_offset*time_factor; 333 334 afxPath3D* path = new afxPath3D(); 335 if (pd->times) 336 path->buildPath( pd->num_points, pd->points, pd->times, pd_delay, time_factor ); 337 else 338 path->buildPath( pd->num_points, pd->points, pd_delay, pd_delay+pd_lifetime ); 339 340 path->setLoopType( pd->loop_type ); 341 342 paths.push_back(path); 343 // path->print(); 344 345 path_mults.push_back( db->path_mult * pd->mult ); 346 347 path_time_offsets.push_back( db->path_time_offset + pd_time_offset ); 348 349 if (pd->roll_string != ST_NULLSTRING && pd->rolls != NULL) 350 { 351 afxAnimCurve* roll_curve = new afxAnimCurve(); 352 for (U32 j=0; j<pd->num_points; j++ ) 353 { 354 roll_curve->addKey( path->getPointTime(j), pd->rolls[j] ); 355 } 356 roll_curve->sort(); 357 // roll_curve->print(); 358 359 rolls.push_back(roll_curve); 360 } 361 else 362 { 363 rolls.push_back( NULL ); 364 } 365 } 366 else 367 { 368 Con::warnf("afxXM_PathConform::init_paths() -- paths datablock (%d) has no points.", i); 369 } 370 371 if (pd->isTempClone()) 372 delete pd; 373 } 374} 375 376void afxXM_PathConform::updateParams(F32 dt, F32 elapsed, afxXM_Params& params) 377{ 378 F32 wt_factor = calc_weight_factor(elapsed); 379 380 // compute path offset 381 VectorF path_offset(0,0,0); 382 for( U32 i=0; i < paths.size(); i++ ) 383 path_offset += path_mults[i]*paths[i]->evaluateAtTime(elapsed + path_time_offsets[i])*wt_factor; 384 385 params.ori.mulV(path_offset); 386 params.pos += path_offset; 387 388 if (db->orient_to_path && paths.size()) 389 { 390 VectorF path_v = paths[0]->evaluateTangentAtTime(elapsed+path_time_offsets[0]); 391 path_v.normalize(); 392 393 MatrixF mat(true); 394 395 if( rolls[0] ) 396 { 397 F32 roll_angle = rolls[0]->evaluate(elapsed+path_time_offsets[0]); 398 roll_angle = mDegToRad( roll_angle ); 399 //Con::printf( "roll: %f", roll_angle ); 400 401 Point3F roll_axis = path_v; 402 AngAxisF rollRot(roll_axis, roll_angle); 403 MatrixF roll_mat(true); 404 rollRot.setMatrix(&roll_mat); 405 406 mat.mul(roll_mat); 407 } 408 409 mat.mul(MathUtils::createOrientFromDir(path_v)); 410 params.ori.mul(mat); 411 } 412} 413 414//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 415