Torque3D Documentation / _generateds / afxXM_PathConform.cpp

afxXM_PathConform.cpp

Engine/source/afx/xm/afxXM_PathConform.cpp

More...

Classes:

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