mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-21 12:25:30 +00:00
Add all new AFX files
This commit is contained in:
parent
3d7c1bbbf7
commit
d7a8510756
218 changed files with 54970 additions and 0 deletions
280
Engine/source/afx/util/afxAnimCurve.cpp
Normal file
280
Engine/source/afx/util/afxAnimCurve.cpp
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
#include "afx/util/afxAnimCurve.h"
|
||||
|
||||
afxAnimCurve::afxAnimCurve() : usable( false ), final_value( 0.0f ), start_value( 0.0f )
|
||||
{
|
||||
evaluator = new afxHermiteEval();
|
||||
}
|
||||
|
||||
afxAnimCurve::~afxAnimCurve()
|
||||
{
|
||||
delete evaluator;
|
||||
}
|
||||
|
||||
void afxAnimCurve::addKey( Point2F &v )
|
||||
{
|
||||
Key k;
|
||||
k.time = v.x;
|
||||
k.value = v.y;
|
||||
|
||||
keys.push_back( k );
|
||||
|
||||
usable = false;
|
||||
}
|
||||
|
||||
void afxAnimCurve::addKey( F32 time, F32 value )
|
||||
{
|
||||
Key k;
|
||||
k.time = time;
|
||||
k.value = value;
|
||||
|
||||
keys.push_back( k );
|
||||
|
||||
usable = false;
|
||||
}
|
||||
|
||||
void afxAnimCurve::setKeyTime( int index, F32 t )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= keys.size() ) )
|
||||
return;
|
||||
|
||||
Key &k = keys[index];
|
||||
k.time = t;
|
||||
|
||||
usable = false;
|
||||
}
|
||||
|
||||
void afxAnimCurve::setKeyValue( int index, F32 v )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= keys.size() ) )
|
||||
return;
|
||||
|
||||
Key &k = keys[index];
|
||||
k.value = v;
|
||||
|
||||
if( index == 0 )
|
||||
start_value = v;
|
||||
else if( index == keys.size()-1 )
|
||||
final_value = v;
|
||||
}
|
||||
|
||||
//bool afxAnimCurve::compare_Key( const afxAnimCurve::Key &a, const afxAnimCurve::Key &b )
|
||||
//{
|
||||
// return a.time < b.time;
|
||||
//}
|
||||
|
||||
S32 QSORT_CALLBACK afxAnimCurve::compare_Key( const void* a, const void* b )
|
||||
{
|
||||
const Key *key_a = (Key *)a;
|
||||
const Key *key_b = (Key *)b;
|
||||
|
||||
//Con::printf( "*** %f %f", key_a->time, key_b->time );
|
||||
|
||||
//return key_a->time < key_b->time;
|
||||
|
||||
|
||||
if (key_a->time > key_b->time)
|
||||
return 1;
|
||||
else if (key_a->time < key_b->time)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void afxAnimCurve::sort( )
|
||||
{
|
||||
if( keys.size() == 0 )
|
||||
return;
|
||||
|
||||
//std::sort( keys.begin(), keys.end(), afxAnimCurve::compare_Key );
|
||||
dQsort( keys.address(), keys.size(), sizeof(Key), afxAnimCurve::compare_Key );
|
||||
|
||||
start_value = keys[0].value;
|
||||
final_value = keys[keys.size()-1].value;
|
||||
|
||||
start_time = keys[0].time;
|
||||
final_time = keys[keys.size()-1].time;
|
||||
|
||||
usable = true;
|
||||
}
|
||||
|
||||
int afxAnimCurve::numKeys()
|
||||
{
|
||||
return keys.size();
|
||||
}
|
||||
|
||||
F32 afxAnimCurve::getKeyTime( int index )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= keys.size() ) )
|
||||
return 0.0f;
|
||||
|
||||
Key &k = keys[index];
|
||||
return k.time;
|
||||
}
|
||||
|
||||
F32 afxAnimCurve::getKeyValue( int index )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= keys.size() ) )
|
||||
return 0.0f;
|
||||
|
||||
Key &k = keys[index];
|
||||
return k.value;
|
||||
}
|
||||
|
||||
Point2F afxAnimCurve::getSegment( F32 time )
|
||||
{
|
||||
Point2F segment( 0, 0 );
|
||||
|
||||
if( keys.size() == 0 )
|
||||
return segment;
|
||||
|
||||
int start_index = 0;
|
||||
for( ; start_index < keys.size()-1; start_index++ )
|
||||
{
|
||||
if( time < keys[start_index+1].time )
|
||||
break;
|
||||
}
|
||||
int end_index = start_index+1;
|
||||
|
||||
segment.x = (F32)start_index;
|
||||
segment.y = (F32)end_index;
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
||||
F32 afxAnimCurve::evaluate( F32 time )
|
||||
{
|
||||
if( !usable )
|
||||
return 0.0f;
|
||||
|
||||
if( time <= start_time )
|
||||
return start_value;
|
||||
|
||||
if( time >= final_time )
|
||||
return final_value;
|
||||
|
||||
if( keys.size() == 1 )
|
||||
return start_value;
|
||||
|
||||
int start_index = 0;
|
||||
for( ; start_index < keys.size()-1; start_index++ )
|
||||
{
|
||||
if( time < keys[start_index+1].time )
|
||||
break;
|
||||
}
|
||||
int end_index = start_index+1;
|
||||
|
||||
Key k0 = keys[start_index];
|
||||
Key k1 = keys[end_index];
|
||||
|
||||
Point2F v0( (F32) k0.time, k0.value );
|
||||
Point2F v1( (F32) k1.time, k1.value );
|
||||
|
||||
// Compute tangents
|
||||
Point2F tan0 = computeTangentK0( v0, v1, start_index );
|
||||
Point2F tan1 = computeTangentK1( v0, v1, end_index );
|
||||
|
||||
F32 time_perc = (F32)( time - k0.time ) / (F32)( k1.time - k0.time );
|
||||
|
||||
Point2F vnew = evaluator->evaluateCurve( v0,
|
||||
v1,
|
||||
tan0,
|
||||
tan1,
|
||||
time_perc );
|
||||
|
||||
return vnew.y;
|
||||
}
|
||||
|
||||
Point2F afxAnimCurve::computeTangentK0( Point2F &k0, Point2F &k1, int start_index )
|
||||
{
|
||||
Point2F tan0;
|
||||
|
||||
Point2F k_prev;
|
||||
Point2F k_next;
|
||||
|
||||
// tangent for k0
|
||||
if( start_index == 0 )
|
||||
{
|
||||
k_prev = k0; // Setting previous point to k0, creating a hidden point in
|
||||
// the same spot
|
||||
k_next = k1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Key &k = keys[start_index-1];
|
||||
k_prev.set( k.time, k.value );
|
||||
k_next = k1;
|
||||
}
|
||||
tan0 = k_next-k_prev; //k_next.subtract( k_prev );
|
||||
tan0 *= .5f;
|
||||
|
||||
return tan0;
|
||||
}
|
||||
|
||||
Point2F afxAnimCurve::computeTangentK1( Point2F &k0, Point2F &k1, int end_index )
|
||||
{
|
||||
Point2F tan1;
|
||||
|
||||
Point2F k_prev;
|
||||
Point2F k_next;
|
||||
|
||||
// tangent for k1
|
||||
if( end_index == keys.size()-1 )
|
||||
{
|
||||
k_prev = k0;
|
||||
k_next = k1; // Setting next point to k1, creating a hidden point in
|
||||
// the same spot
|
||||
}
|
||||
else
|
||||
{
|
||||
k_prev = k0;
|
||||
Key &k = keys[end_index+1];
|
||||
k_next.set( k.time, k.value );
|
||||
}
|
||||
tan1 = k_next-k_prev; //k_next.subtract( k_prev );
|
||||
tan1 *= .5f;
|
||||
|
||||
return tan1;
|
||||
}
|
||||
|
||||
void afxAnimCurve::print()
|
||||
{
|
||||
Con::printf( "afxAnimCurve -------------------------" );
|
||||
for( int i = 0; i < keys.size(); i++ )
|
||||
{
|
||||
Key &k = keys[i];
|
||||
Con::printf( "%f: %f", k.time, k.value );
|
||||
}
|
||||
Con::printf( "-----------------------------------" );
|
||||
}
|
||||
|
||||
void afxAnimCurve::printKey( int index )
|
||||
{
|
||||
Key &k = keys[index];
|
||||
Con::printf( "%f: %f", k.time, k.value );
|
||||
}
|
||||
82
Engine/source/afx/util/afxAnimCurve.h
Normal file
82
Engine/source/afx/util/afxAnimCurve.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_ANIM_CURVE_H_
|
||||
#define _AFX_ANIM_CURVE_H_
|
||||
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
#include "afx/util/afxCurveEval.h"
|
||||
|
||||
class afxAnimCurve
|
||||
{
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
F32 time;
|
||||
F32 value;
|
||||
};
|
||||
|
||||
private:
|
||||
afxCurveEval* evaluator;
|
||||
|
||||
F32 final_value;
|
||||
F32 start_value;
|
||||
F32 final_time;
|
||||
F32 start_time;
|
||||
bool usable;
|
||||
|
||||
//std::vector<Key> keys;
|
||||
Vector<Key> keys;
|
||||
|
||||
//static bool compare_Key( const Key &a, const Key &b );
|
||||
static S32 QSORT_CALLBACK compare_Key( const void* a, const void* b );
|
||||
|
||||
public:
|
||||
afxAnimCurve();
|
||||
~afxAnimCurve();
|
||||
|
||||
void addKey( Point2F &v );
|
||||
void addKey( F32 time, F32 value );
|
||||
void setKeyTime( int index, F32 t );
|
||||
void setKeyValue( int index, F32 v );
|
||||
void sort( );
|
||||
int numKeys();
|
||||
F32 getKeyTime( int index );
|
||||
F32 getKeyValue( int index );
|
||||
Point2F getSegment( F32 time );
|
||||
F32 evaluate( F32 time );
|
||||
|
||||
void print();
|
||||
void printKey( int index );
|
||||
|
||||
private:
|
||||
Point2F computeTangentK0( Point2F &k0, Point2F &k1, int start_index );
|
||||
Point2F computeTangentK1( Point2F &k0, Point2F &k1, int end_index );
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_ANIM_CURVE_H_
|
||||
332
Engine/source/afx/util/afxCurve3D.cpp
Normal file
332
Engine/source/afx/util/afxCurve3D.cpp
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
#include "afx/util/afxCurveEval.h"
|
||||
#include "afx/util/afxCurve3D.h"
|
||||
|
||||
afxCurve3D::afxCurve3D() : usable( false ), default_vector( 0, 0, 0 )
|
||||
{
|
||||
evaluator = new afxHermiteEval();
|
||||
}
|
||||
|
||||
afxCurve3D::~afxCurve3D()
|
||||
{
|
||||
delete evaluator;
|
||||
}
|
||||
|
||||
void afxCurve3D::addPoint( F32 param, Point3F &v )
|
||||
{
|
||||
if( param < 0.0f || param > 1.0f )
|
||||
return;
|
||||
|
||||
CurvePoint p;
|
||||
p.parameter = param;
|
||||
p.point.set( v );
|
||||
|
||||
points.push_back( p );
|
||||
|
||||
usable = false;
|
||||
}
|
||||
|
||||
void afxCurve3D::setPoint( int index, Point3F &v )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= points.size() ) )
|
||||
return;
|
||||
|
||||
CurvePoint &p = points[index];
|
||||
p.point = v;
|
||||
|
||||
if( index == 0 )
|
||||
start_value = v;
|
||||
else if( index == points.size()-1 )
|
||||
final_value = v;
|
||||
}
|
||||
|
||||
//bool afxCurve3D::compare_CurvePoint( const afxCurve3D::CurvePoint &a, const afxCurve3D::CurvePoint &b )
|
||||
//{
|
||||
// return a.parameter < b.parameter;
|
||||
//}
|
||||
|
||||
S32 QSORT_CALLBACK afxCurve3D::compare_CurvePoint( const void* a, const void* b )
|
||||
{
|
||||
//CurvePoint *cp_a = *((CurvePoint **)a);
|
||||
//CurvePoint *cp_b = *((CurvePoint **)b);
|
||||
|
||||
const CurvePoint *cp_a = (CurvePoint *)a;
|
||||
const CurvePoint *cp_b = (CurvePoint *)b;
|
||||
|
||||
//Con::printf( "*** %f %f", cp_a->parameter, cp_b->parameter );
|
||||
|
||||
//return cp_a->parameter < cp_b->parameter;
|
||||
//return 1;
|
||||
|
||||
if (cp_a->parameter > cp_b->parameter)
|
||||
return 1;
|
||||
else if (cp_a->parameter < cp_b->parameter)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void afxCurve3D::sort( )
|
||||
{
|
||||
if( points.size() == 0 )
|
||||
return;
|
||||
|
||||
if( points.size() == 1 )
|
||||
{
|
||||
start_value = points[0].point;
|
||||
final_value = start_value;
|
||||
usable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//Con::printf( "*** pre-sort" );
|
||||
//std::sort( points.begin(), points.end(), afxCurve3D::compare_CurvePoint );
|
||||
dQsort( points.address(), points.size(), sizeof(CurvePoint), afxCurve3D::compare_CurvePoint );
|
||||
//Con::printf( "*** post-sort" );
|
||||
|
||||
start_value = points[0].point;
|
||||
final_value = points[points.size()-1].point;
|
||||
|
||||
usable = true;
|
||||
|
||||
start_tangent = evaluateTangent( 0.0f );
|
||||
final_tangent = evaluateTangent( 1.0f );
|
||||
}
|
||||
|
||||
int afxCurve3D::numPoints()
|
||||
{
|
||||
return points.size();
|
||||
}
|
||||
|
||||
F32 afxCurve3D::getParameter( int index )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= points.size() ) )
|
||||
return 0.0f;
|
||||
|
||||
return points[index].parameter;
|
||||
}
|
||||
|
||||
Point3F afxCurve3D::getPoint( int index )
|
||||
{
|
||||
if( ( index < 0 ) || ( index >= points.size() ) )
|
||||
return default_vector;
|
||||
|
||||
return points[index].point;
|
||||
}
|
||||
|
||||
Point3F afxCurve3D::evaluate( F32 param )
|
||||
{
|
||||
if( !usable )
|
||||
return default_vector;
|
||||
|
||||
if( param <= 0.0f )
|
||||
return start_value;
|
||||
|
||||
if( param >= 1.0f )
|
||||
return final_value;
|
||||
|
||||
if( points.size() == 1 )
|
||||
return start_value;
|
||||
|
||||
int start_index = 0;
|
||||
for( ; start_index < points.size()-1; start_index++ )
|
||||
{
|
||||
if( param < points[start_index+1].parameter )
|
||||
break;
|
||||
}
|
||||
int end_index = start_index+1;
|
||||
|
||||
CurvePoint p0 = points[start_index];
|
||||
CurvePoint p1 = points[end_index];
|
||||
|
||||
// Compute tangents
|
||||
//Point3F tan0 = computeTangentP0( p0.point, p1.point, start_index );
|
||||
//Point3F tan1 = computeTangentP1( p0.point, p1.point, end_index );
|
||||
|
||||
|
||||
F32 local_param = ( param - p0.parameter ) / ( p1.parameter - p0.parameter );
|
||||
|
||||
//Point3F vnew = evaluator->evaluateCurve( p0.point,
|
||||
// p1.point,
|
||||
// tan0,
|
||||
// tan1,
|
||||
// local_param );
|
||||
|
||||
Point3F vnew = evaluator->evaluateCurve( p0.point, p1.point,
|
||||
p0.tangent, p1.tangent,
|
||||
local_param );
|
||||
return vnew;
|
||||
}
|
||||
|
||||
Point3F afxCurve3D::evaluateTangent( F32 param )
|
||||
{
|
||||
if( !usable )
|
||||
return default_vector;
|
||||
|
||||
if( param < 0.0f )
|
||||
return start_tangent;
|
||||
|
||||
if( param > 1.0f )
|
||||
return final_tangent;
|
||||
|
||||
if( points.size() == 1 )
|
||||
return start_tangent;
|
||||
|
||||
int start_index = 0;
|
||||
for( ; start_index < points.size()-1; start_index++ )
|
||||
{
|
||||
if( param < points[start_index+1].parameter )
|
||||
break;
|
||||
}
|
||||
int end_index = start_index+1;
|
||||
|
||||
if( param == 1.0f )
|
||||
{
|
||||
end_index = points.size()-1;
|
||||
start_index = end_index - 1;
|
||||
}
|
||||
|
||||
CurvePoint p0 = points[start_index];
|
||||
CurvePoint p1 = points[end_index];
|
||||
|
||||
// Compute tangents
|
||||
//Point3F tan0 = computeTangentP0( p0.point, p1.point, start_index );
|
||||
//Point3F tan1 = computeTangentP1( p0.point, p1.point, end_index );
|
||||
|
||||
F32 local_param = ( param - p0.parameter ) / ( p1.parameter - p0.parameter );
|
||||
|
||||
//Point3F vnew = evaluator->evaluateCurveTangent( p0.point,
|
||||
// p1.point,
|
||||
// tan0,
|
||||
// tan1,
|
||||
// local_param );
|
||||
Point3F vnew = evaluator->evaluateCurveTangent( p0.point, p1.point,
|
||||
p0.tangent, p1.tangent,
|
||||
local_param );
|
||||
|
||||
return vnew;
|
||||
}
|
||||
|
||||
Point3F afxCurve3D::computeTangentP0( Point3F &p0, Point3F &p1, int start_index )
|
||||
{
|
||||
Point3F tan0;
|
||||
|
||||
Point3F p_prev;
|
||||
Point3F p_next;
|
||||
|
||||
// tangent for p0
|
||||
if( start_index == 0 )
|
||||
{
|
||||
p_prev = p0; // Setting previous point to p0, creating a hidden point in
|
||||
// the same spot
|
||||
p_next = p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurvePoint &p = points[start_index-1];
|
||||
p_prev = p.point;
|
||||
p_next = p1;
|
||||
}
|
||||
tan0 = p_next-p_prev; //p_next.subtract( p_prev );
|
||||
tan0 *= .5f; //= tan0.scale( .5f );
|
||||
|
||||
return tan0;
|
||||
}
|
||||
|
||||
Point3F afxCurve3D::computeTangentP1( Point3F &p0, Point3F &p1, int end_index )
|
||||
{
|
||||
Point3F tan1;
|
||||
|
||||
Point3F p_prev;
|
||||
Point3F p_next;
|
||||
|
||||
// tangent for p1
|
||||
if( end_index == points.size()-1 )
|
||||
{
|
||||
p_prev = p0;
|
||||
p_next = p1; // Setting next point to p1, creating a hidden point in
|
||||
// the same spot
|
||||
}
|
||||
else
|
||||
{
|
||||
p_prev = p0;
|
||||
CurvePoint &p = points[end_index+1];
|
||||
p_next = p.point;
|
||||
}
|
||||
tan1 = p_next-p_prev; //p_next.subtract( p_prev );
|
||||
tan1 *= .5f; //= tan1.scale( .5f );
|
||||
|
||||
//Con::printf("UPDATE");
|
||||
return tan1;
|
||||
}
|
||||
|
||||
void afxCurve3D::computeTangents()
|
||||
{
|
||||
CurvePoint *p_prev;
|
||||
CurvePoint *p_next;
|
||||
|
||||
for( int i = 0; i < points.size(); i++ )
|
||||
{
|
||||
CurvePoint *p = &points[i];
|
||||
|
||||
if( i == 0 )
|
||||
{
|
||||
p_prev = p; // Setting previous point to p0, creating a hidden point in
|
||||
// the same spot
|
||||
p_next = &points[i+1];
|
||||
}
|
||||
else if( i == points.size()-1 )
|
||||
{
|
||||
p_prev = &points[i-1];
|
||||
p_next = p; // Setting next point to p1, creating a hidden point in
|
||||
// the same spot
|
||||
}
|
||||
else
|
||||
{
|
||||
p_prev = &points[i-1];
|
||||
p_next = &points[i+1];
|
||||
}
|
||||
|
||||
p->tangent = p_next->point - p_prev->point;
|
||||
//(p->tangent).normalize();
|
||||
p->tangent *= .5f;
|
||||
|
||||
//Con::printf( "%d: %f %f %f", i, p->tangent.x, p->tangent.y, p->tangent.z );
|
||||
}
|
||||
}
|
||||
|
||||
void afxCurve3D::print()
|
||||
{
|
||||
Con::printf( "afxCurve3D -------------------------" );
|
||||
for( int i = 0; i < points.size(); i++ )
|
||||
{
|
||||
CurvePoint &p = points[i];
|
||||
Con::printf( "%f: %f %f %f", p.parameter, p.point.x, p.point.y, p.point.z );
|
||||
}
|
||||
Con::printf( "---------------------------------" );
|
||||
}
|
||||
92
Engine/source/afx/util/afxCurve3D.h
Normal file
92
Engine/source/afx/util/afxCurve3D.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_CURVE_3D_H_
|
||||
#define _AFX_CURVE_3D_H_
|
||||
|
||||
#include "core/util/tVector.h"
|
||||
#include "math/mPoint3.h"
|
||||
|
||||
class afxCurveEval;
|
||||
|
||||
class afxCurve3D
|
||||
{
|
||||
class CurvePoint
|
||||
{
|
||||
public:
|
||||
F32 parameter;
|
||||
Point3F point;
|
||||
|
||||
// new:
|
||||
Point3F tangent;
|
||||
};
|
||||
|
||||
private:
|
||||
afxCurveEval* evaluator;
|
||||
Point3F start_value;
|
||||
Point3F final_value;
|
||||
Point3F start_tangent;
|
||||
Point3F final_tangent;
|
||||
bool usable;
|
||||
|
||||
//std::vector<CurvePoint> points;
|
||||
Vector<CurvePoint> points;
|
||||
|
||||
Point3F default_vector;
|
||||
|
||||
//static bool compare_CurvePoint( const CurvePoint &a, const CurvePoint &b );
|
||||
static S32 QSORT_CALLBACK compare_CurvePoint( const void* a, const void* b );
|
||||
|
||||
// new
|
||||
Point3F last_tangent;
|
||||
bool flip;
|
||||
|
||||
public:
|
||||
afxCurve3D();
|
||||
~afxCurve3D();
|
||||
|
||||
void addPoint( F32 param, Point3F &v );
|
||||
void setPoint( int index, Point3F &v );
|
||||
void sort( );
|
||||
int numPoints();
|
||||
F32 getParameter( int index );
|
||||
Point3F getPoint( int index );
|
||||
Point3F evaluate( F32 param );
|
||||
Point3F evaluateTangent( F32 param );
|
||||
|
||||
void print();
|
||||
|
||||
void computeTangents();
|
||||
|
||||
//MatrixF createOrientFromDir( Point3F &direction );
|
||||
|
||||
private:
|
||||
Point3F computeTangentP0( Point3F &p0, Point3F &p1, int start_index );
|
||||
Point3F computeTangentP1( Point3F &p0, Point3F &p1, int end_index );
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_CURVE_3D_H_
|
||||
122
Engine/source/afx/util/afxCurveEval.cpp
Normal file
122
Engine/source/afx/util/afxCurveEval.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
#include "afx/util/afxCurveEval.h"
|
||||
|
||||
Point2F afxHermiteEval::evaluateCurve( Point2F &v0, Point2F &v1,
|
||||
Point2F &t0, Point2F &t1, F32 t )
|
||||
{
|
||||
F32 t_3 = t*t*t;
|
||||
F32 t_2 = t*t;
|
||||
F32 h1 = ( 2.0f * t_3 ) - ( 3.0f * t_2 ) + 1;
|
||||
F32 h2 = (-2.0f * t_3 ) + ( 3.0f * t_2 );
|
||||
F32 h3 = t_3 - ( 2.0f * t_2 ) + t;
|
||||
F32 h4 = t_3 - t_2;
|
||||
|
||||
Point2F v(
|
||||
(h1*v0.x)+(h2*v1.x)+(h3*t0.x)+(h4*t1.x),
|
||||
(h1*v0.y)+(h2*v1.y)+(h3*t0.y)+(h4*t1.y) );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Point2F afxHermiteEval::evaluateCurve( Point2F &v0, Point2F &v1, F32 t )
|
||||
{
|
||||
Point2F tangent( 1, 0 );
|
||||
return( evaluateCurve( v0, v1, tangent, tangent, t ) );
|
||||
}
|
||||
|
||||
Point2F afxHermiteEval::evaluateCurveTangent( Point2F &v0, Point2F &v1,
|
||||
Point2F &t0, Point2F &t1, F32 t )
|
||||
{
|
||||
F32 t_2 = t*t;
|
||||
F32 h1_der = ( 6.0f * t_2 ) - ( 6.0f * t );
|
||||
F32 h2_der = (-6.0f * t_2 ) + ( 6.0f * t );
|
||||
F32 h3_der = ( 3.0f * t_2 ) - ( 4.0f * t ) + 1;
|
||||
F32 h4_der = ( 3.0f * t_2 ) - ( 2.0f * t );
|
||||
|
||||
Point2F tangent(
|
||||
(h1_der*v0.x)+(h2_der*v1.x)+(h3_der*t0.x)+(h4_der*t1.x),
|
||||
(h1_der*v0.y)+(h2_der*v1.y)+(h3_der*t0.y)+(h4_der*t1.y) );
|
||||
|
||||
return tangent;
|
||||
}
|
||||
|
||||
Point2F afxHermiteEval::evaluateCurveTangent( Point2F &v0, Point2F &v1, F32 t )
|
||||
{
|
||||
Point2F tangent( 1, 0 );
|
||||
return( evaluateCurveTangent( v0, v1, tangent, tangent, t ) );
|
||||
}
|
||||
|
||||
Point3F afxHermiteEval::evaluateCurve( Point3F &v0, Point3F &v1,
|
||||
Point3F &t0, Point3F &t1, F32 t )
|
||||
{
|
||||
F32 t_3 = t*t*t;
|
||||
F32 t_2 = t*t;
|
||||
F32 h1 = ( 2.0f * t_3 ) - ( 3.0f * t_2 ) + 1;
|
||||
F32 h2 = (-2.0f * t_3 ) + ( 3.0f * t_2 );
|
||||
F32 h3 = t_3 - ( 2.0f * t_2 ) + t;
|
||||
F32 h4 = t_3 - t_2;
|
||||
|
||||
Point3F v(
|
||||
(h1*v0.x)+(h2*v1.x)+(h3*t0.x)+(h4*t1.x),
|
||||
(h1*v0.y)+(h2*v1.y)+(h3*t0.y)+(h4*t1.y),
|
||||
(h1*v0.z)+(h2*v1.z)+(h3*t0.z)+(h4*t1.z) );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Point3F afxHermiteEval::evaluateCurve( Point3F &v0, Point3F &v1, F32 t )
|
||||
{
|
||||
Point3F tangent( 1, 0, 0 );
|
||||
return( evaluateCurve( v0, v1, tangent, tangent, t ) );
|
||||
}
|
||||
|
||||
Point3F afxHermiteEval::evaluateCurveTangent( Point3F &v0, Point3F &v1,
|
||||
Point3F &t0, Point3F &t1, F32 t )
|
||||
{
|
||||
F32 t_2 = t*t;
|
||||
F32 h1_der = ( 6.0f * t_2 ) - ( 6.0f * t );
|
||||
F32 h2_der = (-6.0f * t_2 ) + ( 6.0f * t );
|
||||
F32 h3_der = ( 3.0f * t_2 ) - ( 4.0f * t ) + 1;
|
||||
F32 h4_der = ( 3.0f * t_2 ) - ( 2.0f * t );
|
||||
|
||||
Point3F tangent(
|
||||
(h1_der*v0.x)+(h2_der*v1.x)+(h3_der*t0.x)+(h4_der*t1.x),
|
||||
(h1_der*v0.y)+(h2_der*v1.y)+(h3_der*t0.y)+(h4_der*t1.y),
|
||||
(h1_der*v0.z)+(h2_der*v1.z)+(h3_der*t0.z)+(h4_der*t1.z) );
|
||||
|
||||
return tangent;
|
||||
}
|
||||
|
||||
Point3F afxHermiteEval::evaluateCurveTangent( Point3F &v0, Point3F &v1, F32 t )
|
||||
{
|
||||
Point3F tangent( 1, 0, 0 );
|
||||
return( evaluateCurveTangent( v0, v1, tangent, tangent, t ) );
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
62
Engine/source/afx/util/afxCurveEval.h
Normal file
62
Engine/source/afx/util/afxCurveEval.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_CURVE_EVAL_BASE_H_
|
||||
#define _AFX_CURVE_EVAL_BASE_H_
|
||||
|
||||
#include "math/mPoint2.h"
|
||||
#include "math/mPoint3.h"
|
||||
|
||||
class afxCurveEval
|
||||
{
|
||||
public:
|
||||
virtual Point2F evaluateCurve(Point2F& v0, Point2F& v1, F32 t)=0;
|
||||
virtual Point2F evaluateCurve(Point2F& v0, Point2F& v1, Point2F& t0, Point2F& t1, F32 t)=0;
|
||||
virtual Point2F evaluateCurveTangent(Point2F& v0, Point2F& v1, F32 t)=0;
|
||||
virtual Point2F evaluateCurveTangent(Point2F& v0, Point2F& v1, Point2F& t0, Point2F& t1, F32 t)=0;
|
||||
|
||||
virtual Point3F evaluateCurve(Point3F& v0, Point3F& v1, F32 t)=0;
|
||||
virtual Point3F evaluateCurve(Point3F& v0, Point3F& v1, Point3F& t0, Point3F& t1, F32 t)=0;
|
||||
virtual Point3F evaluateCurveTangent(Point3F& v0, Point3F& v1, F32 t)=0;
|
||||
virtual Point3F evaluateCurveTangent(Point3F& v0, Point3F& v1, Point3F& t0, Point3F& t1, F32 t)=0;
|
||||
};
|
||||
|
||||
class afxHermiteEval : public afxCurveEval
|
||||
{
|
||||
public:
|
||||
Point2F evaluateCurve(Point2F& v0, Point2F& v1, F32 t);
|
||||
Point2F evaluateCurve(Point2F& v0, Point2F& v1, Point2F& t0, Point2F& t1, F32 t);
|
||||
Point2F evaluateCurveTangent(Point2F& v0, Point2F& v1, F32 t);
|
||||
Point2F evaluateCurveTangent(Point2F& v0, Point2F& v1, Point2F& t0, Point2F& t1, F32 t);
|
||||
|
||||
Point3F evaluateCurve(Point3F& v0, Point3F& v1, F32 t);
|
||||
Point3F evaluateCurve(Point3F& v0, Point3F& v1, Point3F& t0, Point3F& t1, F32 t);
|
||||
Point3F evaluateCurveTangent(Point3F& v0, Point3F& v1, F32 t);
|
||||
Point3F evaluateCurveTangent(Point3F& v0, Point3F& v1, Point3F& t0, Point3F& t1, F32 t);
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_CURVE_EVAL_BASE_H_
|
||||
98
Engine/source/afx/util/afxEase.cpp
Normal file
98
Engine/source/afx/util/afxEase.cpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
#include "afxEase.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
F32
|
||||
afxEase::t(F32 t, F32 ein, F32 eout)
|
||||
{
|
||||
if (t == 0.0)
|
||||
return 0.0;
|
||||
|
||||
if (t == 1.0)
|
||||
return 1.0;
|
||||
|
||||
F32 ee = eout - ein + 1.0;
|
||||
|
||||
// ease in section
|
||||
if (t <= ein)
|
||||
{
|
||||
F32 tin = t/ein;
|
||||
return (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ein*(1.0/M_PI_F)/ee;
|
||||
}
|
||||
|
||||
// middle linear section
|
||||
else if (t <= eout)
|
||||
{
|
||||
return (2.0*t - ein)/ee;
|
||||
}
|
||||
|
||||
// ease out section
|
||||
else
|
||||
{
|
||||
F32 iout = 1.0 - eout;
|
||||
F32 g = (t - eout)*M_PI_F/iout;
|
||||
return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*1.0/ee + 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
F32
|
||||
afxEase::eq(F32 t, F32 a, F32 b, F32 ein, F32 eout)
|
||||
{
|
||||
if (t == 0.0)
|
||||
return a;
|
||||
|
||||
if (t == 1.0)
|
||||
return b;
|
||||
|
||||
F32 ab = b - a;
|
||||
F32 ee = eout - ein + 1.0;
|
||||
|
||||
// ease in section
|
||||
if (t <= ein)
|
||||
{
|
||||
F32 tin = t/ein;
|
||||
return a + (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ab*ein*(1.0/M_PI_F)/ee;
|
||||
}
|
||||
|
||||
// middle linear section
|
||||
else if (t <= eout)
|
||||
{
|
||||
return a + ab*(2.0*t - ein)/ee;
|
||||
}
|
||||
|
||||
// ease out section
|
||||
else
|
||||
{
|
||||
F32 iout = 1.0 - eout;
|
||||
F32 g = (t - eout)*M_PI_F/iout;
|
||||
return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*ab/ee + a;
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
41
Engine/source/afx/util/afxEase.h
Normal file
41
Engine/source/afx/util/afxEase.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_EASE_H_
|
||||
#define _AFX_EASE_H_
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
class afxEase
|
||||
{
|
||||
public:
|
||||
static F32 t(F32 t, F32 ein, F32 eout);
|
||||
static F32 eq(F32 t, F32 a, F32 b, F32 ein, F32 eout);
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_EASE_H_
|
||||
|
||||
233
Engine/source/afx/util/afxParticlePool.cpp
Normal file
233
Engine/source/afx/util/afxParticlePool.cpp
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
|
||||
#include "T3D/fx/particleEmitter.h"
|
||||
|
||||
#include "afx/afxChoreographer.h"
|
||||
#include "afx/util/afxParticlePool.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1(afxParticlePoolData);
|
||||
|
||||
ConsoleDocClass( afxParticlePoolData,
|
||||
"@brief A ParticlePool datablock.\n\n"
|
||||
|
||||
"@ingroup afxUtil\n"
|
||||
"@ingroup AFX\n"
|
||||
);
|
||||
|
||||
Vector<afxParticlePool::SortParticlePool> afxParticlePool::orderedVector;
|
||||
|
||||
afxParticlePoolData::afxParticlePoolData()
|
||||
{
|
||||
pool_type = POOL_NORMAL;
|
||||
base_color.set(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
blend_weight = 1.0f;
|
||||
}
|
||||
|
||||
afxParticlePoolData::afxParticlePoolData(const afxParticlePoolData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
pool_type = other.pool_type;
|
||||
base_color = other.base_color;
|
||||
blend_weight = other.blend_weight;
|
||||
}
|
||||
|
||||
ImplementEnumType( afxParticlePool_PoolType, "Possible particle pool types.\n" "@ingroup afxParticlePool\n\n" )
|
||||
{ afxParticlePoolData::POOL_NORMAL, "normal", "..." },
|
||||
{ afxParticlePoolData::POOL_TWOPASS, "two-pass", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
afxParticlePoolData::~afxParticlePoolData()
|
||||
{
|
||||
}
|
||||
|
||||
void afxParticlePoolData::initPersistFields()
|
||||
{
|
||||
addField("poolType", TYPEID< afxParticlePoolData::PoolType >(), Offset(pool_type, afxParticlePoolData),
|
||||
"...");
|
||||
addField("baseColor", TypeColorF, Offset(base_color, afxParticlePoolData),
|
||||
"...");
|
||||
addField("blendWeight", TypeF32, Offset(blend_weight, afxParticlePoolData),
|
||||
"...");
|
||||
|
||||
Parent::initPersistFields();
|
||||
};
|
||||
|
||||
void afxParticlePoolData::packData(BitStream* stream)
|
||||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
stream->write(pool_type);
|
||||
stream->write(base_color);
|
||||
stream->write(blend_weight);
|
||||
};
|
||||
|
||||
void afxParticlePoolData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
stream->read(&pool_type);
|
||||
stream->read(&base_color);
|
||||
stream->read(&blend_weight);
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(afxParticlePool);
|
||||
|
||||
ConsoleDocClass( afxParticlePool,
|
||||
"@brief A ParticlePool object as defined by an afxParticlePoolData datablock.\n\n"
|
||||
|
||||
"@ingroup afxUtil\n"
|
||||
"@ingroup AFX\n"
|
||||
);
|
||||
|
||||
afxParticlePool::afxParticlePool()
|
||||
{
|
||||
mDataBlock = 0;
|
||||
key_block = 0;
|
||||
key_index = 0;
|
||||
choreographer = 0;
|
||||
sort_priority = S8_MAX;
|
||||
|
||||
mNetFlags.set(IsGhost);
|
||||
mTypeMask |= StaticObjectType;
|
||||
|
||||
mCurBuffSize = mCurBuffSize2 = 0;
|
||||
};
|
||||
|
||||
afxParticlePool::~afxParticlePool()
|
||||
{
|
||||
for (S32 i = 0; i < emitters.size(); i++)
|
||||
if (emitters[i])
|
||||
emitters[i]->clearPool();
|
||||
|
||||
if (choreographer)
|
||||
choreographer->unregisterParticlePool(this);
|
||||
|
||||
if (mDataBlock && mDataBlock->isTempClone())
|
||||
{
|
||||
delete mDataBlock;
|
||||
mDataBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool afxParticlePool::onNewDataBlock(GameBaseData* dptr, bool reload)
|
||||
{
|
||||
mDataBlock = dynamic_cast<afxParticlePoolData*>(dptr);
|
||||
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool afxParticlePool::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
mObjBox.minExtents.set(-0.5, -0.5, -0.5);
|
||||
mObjBox.maxExtents.set( 0.5, 0.5, 0.5);
|
||||
|
||||
resetWorldBox();
|
||||
|
||||
addToScene();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void afxParticlePool::onRemove()
|
||||
{
|
||||
removeFromScene();
|
||||
|
||||
Parent::onRemove();
|
||||
};
|
||||
|
||||
void afxParticlePool::addParticleEmitter(ParticleEmitter* emitter)
|
||||
{
|
||||
emitters.push_back(emitter);
|
||||
}
|
||||
|
||||
void afxParticlePool::removeParticleEmitter(ParticleEmitter* emitter)
|
||||
{
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
if (emitters[i] == emitter)
|
||||
{
|
||||
emitters.erase(i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (emitters.empty())
|
||||
{
|
||||
if (choreographer)
|
||||
{
|
||||
choreographer->unregisterParticlePool(this);
|
||||
choreographer = 0;
|
||||
}
|
||||
Sim::postEvent(this, new ObjectDeleteEvent, Sim::getCurrentTime() + 500);
|
||||
}
|
||||
}
|
||||
|
||||
void afxParticlePool::updatePoolBBox(ParticleEmitter* emitter)
|
||||
{
|
||||
if (emitter->mObjBox.minExtents.x < mObjBox.minExtents.x)
|
||||
mObjBox.minExtents.x = emitter->mObjBox.minExtents.x;
|
||||
if (emitter->mObjBox.minExtents.y < mObjBox.minExtents.y)
|
||||
mObjBox.minExtents.y = emitter->mObjBox.minExtents.y;
|
||||
if (emitter->mObjBox.minExtents.z < mObjBox.minExtents.z)
|
||||
mObjBox.minExtents.z = emitter->mObjBox.minExtents.z;
|
||||
if (emitter->mObjBox.maxExtents.x > mObjBox.maxExtents.x)
|
||||
mObjBox.maxExtents.x = emitter->mObjBox.maxExtents.x;
|
||||
if (emitter->mObjBox.maxExtents.y > mObjBox.maxExtents.y)
|
||||
mObjBox.maxExtents.y = emitter->mObjBox.maxExtents.y;
|
||||
if (emitter->mObjBox.maxExtents.z > mObjBox.maxExtents.z)
|
||||
mObjBox.maxExtents.z = emitter->mObjBox.maxExtents.z;
|
||||
|
||||
resetWorldBox();
|
||||
}
|
||||
|
||||
void afxParticlePool::setSortPriority(S8 priority)
|
||||
{
|
||||
if (priority < sort_priority)
|
||||
sort_priority = (priority == 0) ? 1 : priority;
|
||||
}
|
||||
|
||||
int QSORT_CALLBACK afxParticlePool::cmpSortParticlePool(const void* p1, const void* p2)
|
||||
{
|
||||
const SortParticlePool* sp1 = (const SortParticlePool*)p1;
|
||||
const SortParticlePool* sp2 = (const SortParticlePool*)p2;
|
||||
if (sp2->k > sp1->k)
|
||||
return 1;
|
||||
else if (sp2->k == sp1->k)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
143
Engine/source/afx/util/afxParticlePool.h
Normal file
143
Engine/source/afx/util/afxParticlePool.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_PARTICLE_POOL_H_
|
||||
#define _AFX_PARTICLE_POOL_H_
|
||||
|
||||
class afxParticlePoolData : public GameBaseData
|
||||
{
|
||||
private:
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
enum PoolType
|
||||
{
|
||||
POOL_NORMAL,
|
||||
POOL_TWOPASS
|
||||
};
|
||||
|
||||
U32 pool_type;
|
||||
LinearColorF base_color;
|
||||
F32 blend_weight;
|
||||
|
||||
public:
|
||||
/*C*/ afxParticlePoolData();
|
||||
/*C*/ afxParticlePoolData(const afxParticlePoolData&, bool = false);
|
||||
/*D*/ ~afxParticlePoolData();
|
||||
|
||||
virtual void packData(BitStream*);
|
||||
virtual void unpackData(BitStream*);
|
||||
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(afxParticlePoolData);
|
||||
DECLARE_CATEGORY("AFX");
|
||||
};
|
||||
|
||||
typedef afxParticlePoolData::PoolType afxParticlePool_PoolType;
|
||||
DefineEnumType( afxParticlePool_PoolType );
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
struct Particle;
|
||||
class ParticleEmitter;
|
||||
class afxChoreographer;
|
||||
|
||||
typedef Vector<ParticleEmitter*> ParticleEmitterList;
|
||||
|
||||
class afxParticlePool : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
class ObjectDeleteEvent : public SimEvent
|
||||
{
|
||||
public:
|
||||
void process(SimObject *obj) { if (obj) obj->deleteObject(); }
|
||||
};
|
||||
|
||||
struct SortParticlePool
|
||||
{
|
||||
Particle* p;
|
||||
F32 k; // interpreted differently depending on rendering method
|
||||
ParticleEmitter* emitter;
|
||||
};
|
||||
|
||||
private:
|
||||
afxParticlePoolData* mDataBlock;
|
||||
afxParticlePoolData* key_block;
|
||||
U32 key_index;
|
||||
ParticleEmitterList emitters;
|
||||
afxChoreographer* choreographer;
|
||||
S8 sort_priority;
|
||||
|
||||
static Vector<SortParticlePool> orderedVector;
|
||||
static int QSORT_CALLBACK cmpSortParticlePool(const void* p1, const void* p2);
|
||||
|
||||
S32 mCurBuffSize;
|
||||
GFXVertexBufferHandle<GFXVertexPCT> mVertBuff;
|
||||
S32 mCurBuffSize2;
|
||||
GFXVertexBufferHandle<GFXVertexPCT> mVertBuff2;
|
||||
|
||||
protected:
|
||||
virtual void prepRenderImage(SceneRenderState*);
|
||||
|
||||
void pool_prepBatchRender(RenderPassManager*, const Point3F &camPos, const LinearColorF &ambientColor);
|
||||
void pool_renderObject_Normal(RenderPassManager*, const Point3F &camPos, const LinearColorF &ambientColor);
|
||||
void pool_renderObject_TwoPass(RenderPassManager*, const Point3F &camPos, const LinearColorF &ambientColor);
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
void renderBillboardParticle_blend(Particle&, const Point3F* basePnts, const MatrixF& camView, const F32 spinFactor,
|
||||
const F32 blend_factor, ParticleEmitter*);
|
||||
void renderBillboardParticle_color(Particle&, const Point3F* basePnts, const MatrixF& camView, const F32 spinFactor,
|
||||
const LinearColorF& color, ParticleEmitter*);
|
||||
|
||||
public:
|
||||
/*C*/ afxParticlePool();
|
||||
/*D*/ ~afxParticlePool();
|
||||
|
||||
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
|
||||
|
||||
void addParticleEmitter(ParticleEmitter*);
|
||||
void removeParticleEmitter(ParticleEmitter*);
|
||||
|
||||
void setChoreographer(afxChoreographer* ch) { choreographer = ch; }
|
||||
void setKeyBlock(afxParticlePoolData* db, U32 idx) { key_block = db; key_index = idx; }
|
||||
bool hasMatchingKeyBlock(const afxParticlePoolData* db, U32 idx) const { return (db == key_block && idx == key_index); }
|
||||
|
||||
void updatePoolBBox(ParticleEmitter*);
|
||||
|
||||
void setSortPriority(S8 priority);
|
||||
|
||||
DECLARE_CONOBJECT(afxParticlePool);
|
||||
DECLARE_CATEGORY("AFX");
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_PARTICLE_POOL_H_
|
||||
491
Engine/source/afx/util/afxParticlePool_T3D.cpp
Normal file
491
Engine/source/afx/util/afxParticlePool_T3D.cpp
Normal file
|
|
@ -0,0 +1,491 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "T3D/fx/particleEmitter.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "lighting/lightinfo.h"
|
||||
#include "lighting/lightManager.h"
|
||||
|
||||
#include "afx/util/afxParticlePool.h"
|
||||
|
||||
void afxParticlePool::prepRenderImage(SceneRenderState* state)
|
||||
{
|
||||
const LightInfo *sunlight = LIGHTMGR->getSpecialLight( LightManager::slSunLightType );
|
||||
pool_prepBatchRender(state->getRenderPass(), state->getCameraPosition(), sunlight->getAmbient());
|
||||
};
|
||||
|
||||
void afxParticlePool::pool_prepBatchRender(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
if (emitters.empty())
|
||||
return;
|
||||
|
||||
switch (mDataBlock->pool_type)
|
||||
{
|
||||
case afxParticlePoolData::POOL_TWOPASS :
|
||||
pool_renderObject_TwoPass(renderManager, camPos, ambientColor);
|
||||
break;
|
||||
case afxParticlePoolData::POOL_NORMAL :
|
||||
default:
|
||||
pool_renderObject_Normal(renderManager, camPos, ambientColor);
|
||||
}
|
||||
}
|
||||
|
||||
void afxParticlePool::pool_renderObject_Normal(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
S32 n_parts = 0;
|
||||
for (S32 i = 0; i < emitters.size(); i++)
|
||||
n_parts += emitters[i]->n_parts;
|
||||
|
||||
if (n_parts == 0)
|
||||
return;
|
||||
|
||||
ParticleEmitterData* main_emitter_data = emitters[0]->mDataBlock;
|
||||
|
||||
main_emitter_data->allocPrimBuffer(n_parts);
|
||||
|
||||
orderedVector.clear();
|
||||
|
||||
MatrixF modelview = GFX->getWorldMatrix();
|
||||
Point3F viewvec; modelview.getRow(1, &viewvec);
|
||||
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
// add each particle and a distance based sort key to orderedVector
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = mDot(pp->pos, viewvec);
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// qsort the list into far to near ordering
|
||||
dQsort(orderedVector.address(), orderedVector.size(), sizeof(SortParticlePool), cmpSortParticlePool);
|
||||
|
||||
static Vector<GFXVertexPCT> tempBuff(2048);
|
||||
tempBuff.reserve(n_parts*4 + 64); // make sure tempBuff is big enough
|
||||
GFXVertexPCT *buffPtr = tempBuff.address(); // use direct pointer (faster)
|
||||
|
||||
Point3F basePoints[4];
|
||||
basePoints[0] = Point3F(-1.0, 0.0, -1.0);
|
||||
basePoints[1] = Point3F( 1.0, 0.0, -1.0);
|
||||
basePoints[2] = Point3F( 1.0, 0.0, 1.0);
|
||||
basePoints[3] = Point3F(-1.0, 0.0, 1.0);
|
||||
|
||||
MatrixF camView = GFX->getWorldMatrix();
|
||||
camView.transpose(); // inverse - this gets the particles facing camera
|
||||
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
if (emitter->mDataBlock->orientParticles)
|
||||
emitter->setupOriented(particle, camPos, ambientColor, buffPtr);
|
||||
else
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
buffPtr+=4;
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff || n_parts > mCurBuffSize )
|
||||
{
|
||||
mCurBuffSize = n_parts;
|
||||
mVertBuff.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
// lock and copy tempBuff to video RAM
|
||||
GFXVertexPCT *verts = mVertBuff.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff.unlock();
|
||||
|
||||
//MeshRenderInst *ri = gRenderInstManager->allocInst<MeshRenderInst>();
|
||||
ParticleRenderInst *ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( camPos );
|
||||
|
||||
ri->defaultKey = (-sort_priority*100);
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = main_emitter_data->blendStyle;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
if (main_emitter_data->textureHandle)
|
||||
ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureHandle);
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
// Sort by texture too.
|
||||
//ri->defaultKey = ri->diffuseTex ? (U32)ri->diffuseTex : (U32)ri->vertBuff;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
}
|
||||
|
||||
void afxParticlePool::pool_renderObject_TwoPass(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
S32 n_parts = 0;
|
||||
for (S32 i = 0; i < emitters.size(); i++)
|
||||
n_parts += emitters[i]->n_parts;
|
||||
|
||||
if (n_parts == 0)
|
||||
return;
|
||||
|
||||
ParticleEmitterData* main_emitter_data = emitters[0]->mDataBlock;
|
||||
|
||||
main_emitter_data->allocPrimBuffer(n_parts);
|
||||
|
||||
orderedVector.clear();
|
||||
|
||||
F32 min_d=0.0f, max_d=0.0f;
|
||||
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
if (!emitters[i]->mDataBlock->pool_depth_fade || !emitters[i]->mDataBlock->pool_radial_fade)
|
||||
continue;
|
||||
|
||||
// add particles to orderedVector and calc distance and min/max distance
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
F32 dist = (pp->pos-camPos).len();
|
||||
if (dist > max_d)
|
||||
max_d = dist;
|
||||
else if (dist < min_d)
|
||||
min_d = dist;
|
||||
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = dist;
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Add remaining emitters particles to the orderedVector that do not participate in the
|
||||
// above depth computations:
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
if (emitters[i]->mDataBlock->pool_depth_fade || emitters[i]->mDataBlock->pool_radial_fade)
|
||||
continue;
|
||||
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = 0; // no need to compute depth here
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
static Vector<GFXVertexPCT> tempBuff(2048);
|
||||
tempBuff.reserve(n_parts*4 + 64); // make sure tempBuff is big enough
|
||||
GFXVertexPCT *buffPtr = tempBuff.address(); // use direct pointer (faster)
|
||||
|
||||
Point3F basePoints[4];
|
||||
basePoints[0] = Point3F(-1.0, 0.0, -1.0);
|
||||
basePoints[1] = Point3F( 1.0, 0.0, -1.0);
|
||||
basePoints[2] = Point3F( 1.0, 0.0, 1.0);
|
||||
basePoints[3] = Point3F(-1.0, 0.0, 1.0);
|
||||
|
||||
MatrixF camView = GFX->getWorldMatrix();
|
||||
camView.transpose(); // inverse - this gets the particles facing camera
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
Point3F bbox_center; mObjBox.getCenter(&bbox_center);
|
||||
F32 d_range = max_d - min_d;
|
||||
bool d_safe = (d_range>0.0001);
|
||||
F32 d_half = min_d + (d_range*0.5f);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color.set(mDataBlock->base_color.red, mDataBlock->base_color.green, mDataBlock->base_color.blue, mDataBlock->base_color.alpha*particle->color.alpha);
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff || n_parts > mCurBuffSize )
|
||||
{
|
||||
mCurBuffSize = n_parts;
|
||||
mVertBuff.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
// lock and copy tempBuff to video RAM
|
||||
GFXVertexPCT *verts = mVertBuff.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff.unlock();
|
||||
|
||||
ParticleRenderInst *ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( camPos );
|
||||
|
||||
ri->defaultKey = (-sort_priority*100);
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = ParticleRenderInst::BlendNormal;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
//if (main_emitter_data->textureHandle)
|
||||
// ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
//else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureExtHandle);
|
||||
|
||||
F32 save_sort_dist = ri->sortDistSq;
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
|
||||
// 2nd-pass
|
||||
|
||||
buffPtr = tempBuff.address();
|
||||
|
||||
bbox_center.z = mObjBox.minExtents.z;
|
||||
F32 max_radius = (max_d-min_d)*0.5f;
|
||||
|
||||
// gather fade settings
|
||||
bool do_mixed_fades = false;
|
||||
bool do_radial_fades = (emitters[0]->mDataBlock->pool_radial_fade && (max_radius>0.0001f));
|
||||
bool do_depth_fades = (emitters[0]->mDataBlock->pool_depth_fade && d_safe);
|
||||
for (U32 i = 1; i < emitters.size(); i++)
|
||||
{
|
||||
if ( (do_radial_fades != (emitters[i]->mDataBlock->pool_radial_fade && (max_radius>0.0001f))) ||
|
||||
(do_depth_fades != (emitters[i]->mDataBlock->pool_depth_fade && d_safe)))
|
||||
{
|
||||
do_mixed_fades = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_mixed_fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
if (emitter->mDataBlock->pool_radial_fade && (max_radius>0.0001f))
|
||||
{
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
}
|
||||
|
||||
// blend factor, depth based
|
||||
if (emitter->mDataBlock->pool_depth_fade && d_safe && (orderedVector[i].k > d_half))
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_radial_fades && do_depth_fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
|
||||
// blend factor, depth based
|
||||
if (orderedVector[i].k > d_half)
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_radial_fades) // && !do_depth_fades
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_depth_fades) // && !do_radial_fades
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor, depth based
|
||||
if (orderedVector[i].k > d_half)
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else // (no fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = mDataBlock->blend_weight; // blend factor
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff2 || n_parts > mCurBuffSize2 )
|
||||
{
|
||||
mCurBuffSize2 = n_parts;
|
||||
mVertBuff2.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
|
||||
// lock and copy tempBuff to video RAM
|
||||
verts = mVertBuff2.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff2.unlock();
|
||||
|
||||
ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff2;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = save_sort_dist;
|
||||
|
||||
ri->defaultKey = (-sort_priority*100) + 1;
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = ParticleRenderInst::BlendAdditive;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
if (main_emitter_data->textureHandle)
|
||||
ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureHandle);
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
530
Engine/source/afx/util/afxPath.cpp
Normal file
530
Engine/source/afx/util/afxPath.cpp
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "math/mathIO.h"
|
||||
|
||||
#include "afx/util/afxPath.h"
|
||||
#include "afx/util/afxPath3D.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// afxPathData
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1(afxPathData);
|
||||
|
||||
ConsoleDocClass( afxPathData,
|
||||
"@brief A datablock for specifiying a 3D path for use with AFX.\n\n"
|
||||
|
||||
"@ingroup afxUtil\n"
|
||||
"@ingroup AFX\n"
|
||||
"@ingroup Datablocks\n"
|
||||
);
|
||||
|
||||
StringTableEntry afxPathData::POINTS_FIELD;
|
||||
StringTableEntry afxPathData::ROLL_FIELD;
|
||||
StringTableEntry afxPathData::TIMES_FIELD;
|
||||
|
||||
ImplementEnumType( afxPath3DLoopType, "Possible loop types for an afxPath.\n" "@ingroup afxPath\n\n" )
|
||||
{ afxPath3D::LOOP_CONSTANT, "constant", "..." },
|
||||
{ afxPath3D::LOOP_CYCLE, "cycle", "..." },
|
||||
{ afxPath3D::LOOP_OSCILLATE, "oscillate", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
afxPathData::afxPathData()
|
||||
{
|
||||
if (POINTS_FIELD == 0)
|
||||
{
|
||||
POINTS_FIELD = StringTable->insert("points");
|
||||
ROLL_FIELD = StringTable->insert("roll");
|
||||
TIMES_FIELD = StringTable->insert("times");
|
||||
}
|
||||
|
||||
loop_string = ST_NULLSTRING;
|
||||
delay = 0;
|
||||
lifetime = 0;
|
||||
loop_type = 0;
|
||||
mult = 1.0f;
|
||||
time_offset = 0.0f;
|
||||
resolved = false;
|
||||
reverse = false;
|
||||
offset.zero();
|
||||
echo = false;
|
||||
concentric = false;
|
||||
|
||||
points_string = ST_NULLSTRING;
|
||||
points = 0;
|
||||
num_points = 0;
|
||||
update_points = true;
|
||||
|
||||
roll_string = ST_NULLSTRING;
|
||||
rolls = 0;
|
||||
update_rolls = true;
|
||||
|
||||
times_string = ST_NULLSTRING;
|
||||
times = 0;
|
||||
update_times = true;
|
||||
}
|
||||
|
||||
afxPathData::afxPathData(const afxPathData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
points_string = other.points_string;
|
||||
roll_string = other.roll_string;
|
||||
loop_string = other.loop_string;
|
||||
delay = other.delay;
|
||||
lifetime = other.lifetime;
|
||||
loop_type = other.loop_type; // --
|
||||
mult = other.mult;
|
||||
time_offset = other.time_offset;
|
||||
resolved = other.resolved; // --
|
||||
reverse = other.reverse;
|
||||
offset = other.offset;
|
||||
echo = other.echo;
|
||||
concentric = other.concentric;
|
||||
times_string = other.times_string;
|
||||
|
||||
num_points = other.num_points; // --
|
||||
if (other.points && num_points > 0)
|
||||
{
|
||||
points = new Point3F[num_points];
|
||||
dMemcpy(points, other.points, sizeof(Point3F)*num_points); // --
|
||||
}
|
||||
else
|
||||
points = 0;
|
||||
if (other.rolls && num_points > 0)
|
||||
{
|
||||
rolls = new F32[num_points];
|
||||
dMemcpy(rolls, other.rolls, sizeof(F32)*num_points); // --
|
||||
}
|
||||
else
|
||||
rolls = 0;
|
||||
if (other.times && num_points > 0)
|
||||
{
|
||||
times = new F32[num_points];
|
||||
dMemcpy(times, other.times, sizeof(F32)*num_points); // --
|
||||
}
|
||||
else
|
||||
times = 0;
|
||||
|
||||
update_points = other.update_points; // --
|
||||
update_rolls = other.update_rolls; // --
|
||||
update_times = other.update_times; // --
|
||||
}
|
||||
|
||||
afxPathData::~afxPathData()
|
||||
{
|
||||
clear_arrays();
|
||||
}
|
||||
|
||||
void afxPathData::initPersistFields()
|
||||
{
|
||||
addField("points", TypeString, Offset(points_string, afxPathData),
|
||||
"...");
|
||||
addField("roll", TypeString, Offset(roll_string, afxPathData),
|
||||
"...");
|
||||
addField("times", TypeString, Offset(times_string, afxPathData),
|
||||
"...");
|
||||
addField("loop", TypeString, Offset(loop_string, afxPathData),
|
||||
"...");
|
||||
addField("mult", TypeF32, Offset(mult, afxPathData),
|
||||
"...");
|
||||
addField("delay", TypeF32, Offset(delay, afxPathData),
|
||||
"...");
|
||||
addField("lifetime", TypeF32, Offset(lifetime, afxPathData),
|
||||
"...");
|
||||
addField("timeOffset", TypeF32, Offset(time_offset, afxPathData),
|
||||
"...");
|
||||
addField("reverse", TypeBool, Offset(reverse, afxPathData),
|
||||
"...");
|
||||
addField("offset", TypePoint3F, Offset(offset, afxPathData),
|
||||
"...");
|
||||
addField("echo", TypeBool, Offset(echo, afxPathData),
|
||||
"...");
|
||||
addField("concentric", TypeBool, Offset(concentric, afxPathData),
|
||||
"...");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
bool afxPathData::onAdd()
|
||||
{
|
||||
if (Parent::onAdd() == false)
|
||||
return false;
|
||||
|
||||
update_derived_values();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void afxPathData::onRemove()
|
||||
{
|
||||
clear_arrays();
|
||||
loop_type = 0;
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void afxPathData::packData(BitStream* stream)
|
||||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
stream->write(num_points);
|
||||
if (num_points > 0)
|
||||
{
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
mathWrite(*stream, points[i]);
|
||||
if (stream->writeFlag(rolls != 0))
|
||||
{
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
stream->write(rolls[i]);
|
||||
}
|
||||
if (stream->writeFlag(times != 0))
|
||||
{
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
stream->write(times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
stream->writeString(loop_string);
|
||||
stream->write(delay);
|
||||
stream->write(lifetime);
|
||||
stream->write(time_offset);
|
||||
stream->write(mult);
|
||||
stream->writeFlag(reverse);
|
||||
mathWrite(*stream, offset);
|
||||
stream->writeFlag(echo);
|
||||
stream->writeFlag(concentric);
|
||||
}
|
||||
|
||||
void afxPathData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
clear_arrays();
|
||||
|
||||
// read the points and rolls
|
||||
stream->read(&num_points);
|
||||
if (num_points > 0)
|
||||
{
|
||||
points = new Point3F[num_points];
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
mathRead(*stream, &points[i]);
|
||||
update_points = false;
|
||||
if (stream->readFlag())
|
||||
{
|
||||
rolls = new F32[num_points];
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
stream->read(&rolls[i]);
|
||||
update_rolls = false;
|
||||
}
|
||||
if (stream->readFlag())
|
||||
{
|
||||
times = new F32[num_points];
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
stream->read(×[i]);
|
||||
update_times = false;
|
||||
}
|
||||
}
|
||||
|
||||
loop_string = stream->readSTString();
|
||||
stream->read(&delay);
|
||||
stream->read(&lifetime);
|
||||
stream->read(&time_offset);
|
||||
stream->read(&mult);
|
||||
reverse = stream->readFlag();
|
||||
mathRead(*stream, &offset);
|
||||
echo = stream->readFlag();
|
||||
concentric = stream->readFlag();
|
||||
}
|
||||
|
||||
void afxPathData::update_derived_values()
|
||||
{
|
||||
U32 num_rolls = (rolls != 0) ? num_points : 0;
|
||||
U32 num_times = (times != 0) ? num_points : 0;
|
||||
|
||||
if (update_points)
|
||||
{
|
||||
derive_points_array();
|
||||
update_points = false;
|
||||
}
|
||||
|
||||
if (update_rolls || num_rolls != num_points)
|
||||
{
|
||||
derive_rolls_array();
|
||||
update_rolls = false;
|
||||
}
|
||||
|
||||
if (update_times || num_times != num_points)
|
||||
{
|
||||
derive_times_array();
|
||||
update_times = false;
|
||||
}
|
||||
|
||||
// CAUTION: The following block of code is fragile and tricky since it depends
|
||||
// on the underlying structures defined by ImplementEnumType/EndImplementEnumType.
|
||||
// This done because the enum text is parsed from a longer string.
|
||||
if (loop_string != ST_NULLSTRING)
|
||||
{
|
||||
for (unsigned int i = 0; i < _afxPath3DLoopType::_sEnumTable.getNumValues(); i++)
|
||||
{
|
||||
if (dStricmp(_afxPath3DLoopType::_sEnumTable[i].mName, loop_string) == 0)
|
||||
{
|
||||
loop_type = _afxPath3DLoopType::_sEnumTable[i].mInt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
loop_string = _afxPath3DLoopType::_sEnumTable[0].mName;
|
||||
loop_type = _afxPath3DLoopType::_sEnumTable[0].mInt;
|
||||
}
|
||||
}
|
||||
|
||||
bool afxPathData::preload(bool server, String &errorStr)
|
||||
{
|
||||
if (!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
|
||||
update_derived_values();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void afxPathData::onStaticModified(const char* slot, const char* newValue)
|
||||
{
|
||||
Parent::onStaticModified(slot, newValue);
|
||||
|
||||
if (slot == POINTS_FIELD)
|
||||
{
|
||||
update_points = true;
|
||||
return;
|
||||
}
|
||||
if (slot == ROLL_FIELD)
|
||||
{
|
||||
update_rolls = true;
|
||||
return;
|
||||
}
|
||||
if (slot == TIMES_FIELD)
|
||||
{
|
||||
update_times = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void afxPathData::extract_floats_from_string(Vector<F32>& values, const char* points_str)
|
||||
{
|
||||
values.clear();
|
||||
|
||||
if (!points_str)
|
||||
return;
|
||||
|
||||
// make a copy of points_str for tokenizing
|
||||
char* tokCopy = dStrdup(points_str);
|
||||
|
||||
// extract each token, convert to float, add to values[]
|
||||
char* currTok = dStrtok(tokCopy, " \t");
|
||||
while (currTok != NULL)
|
||||
{
|
||||
F32 value = dAtof(currTok);
|
||||
values.push_back(value);
|
||||
currTok = dStrtok(NULL, " \t");
|
||||
}
|
||||
|
||||
dFree(tokCopy);
|
||||
}
|
||||
|
||||
Point3F* afxPathData::build_points_array(Vector<F32>& values, U32& n_points, bool reverse)
|
||||
{
|
||||
AssertFatal(values.size() > 0, "Values array is empty.");
|
||||
AssertFatal(values.size()%3 == 0, "Values array is not a multiple of 3.");
|
||||
|
||||
n_points = values.size()/3;
|
||||
Point3F* points = new Point3F[n_points];
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
U32 p_i = 0;
|
||||
for (S32 i = values.size()-1; i > 1; i-=3)
|
||||
points[p_i++].set(values[i-2], values[i-1], values[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
U32 p_i = 0;
|
||||
for (U32 i = 0; i < values.size(); i+=3)
|
||||
points[p_i++].set(values[i], values[i+1], values[i+2]);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
F32* afxPathData::build_floats_array(Vector<F32>& values, U32& n_floats, bool reverse)
|
||||
{
|
||||
AssertFatal(values.size() > 0, "Values array is empty.");
|
||||
|
||||
n_floats = values.size();
|
||||
F32* floats = new F32[n_floats];
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
F32* f = floats;
|
||||
for (S32 i = values.size()-1; i >= 0; i--)
|
||||
{
|
||||
*f = values[i];
|
||||
f++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < values.size(); i++)
|
||||
floats[i] = values[i];
|
||||
}
|
||||
|
||||
return floats;
|
||||
}
|
||||
|
||||
void afxPathData::clear_arrays()
|
||||
{
|
||||
num_points = 0;
|
||||
if (points)
|
||||
{
|
||||
delete [] points;
|
||||
points = 0;
|
||||
}
|
||||
if (rolls)
|
||||
{
|
||||
delete [] rolls;
|
||||
rolls = 0;
|
||||
}
|
||||
if (times)
|
||||
{
|
||||
delete [] times;
|
||||
times = 0;
|
||||
}
|
||||
update_points = true;
|
||||
update_rolls = true;
|
||||
update_times = true;
|
||||
}
|
||||
|
||||
void afxPathData::derive_points_array()
|
||||
{
|
||||
if (points_string == ST_NULLSTRING)
|
||||
return;
|
||||
|
||||
if (points)
|
||||
{
|
||||
delete [] points;
|
||||
points = 0;
|
||||
}
|
||||
num_points = 0;
|
||||
|
||||
Vector<F32> values;
|
||||
extract_floats_from_string(values, points_string);
|
||||
if (values.size() == 0)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "afxPathData(%s) empty points field, datablock is invalid.", getName());
|
||||
return;
|
||||
}
|
||||
if (values.size()%3 != 0)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "afxPathData(%s) total points values is not a multiple of 3, datablock is invalid.", getName());
|
||||
return;
|
||||
}
|
||||
|
||||
points = build_points_array(values, num_points, reverse);
|
||||
|
||||
if (offset.x != 0.0f || offset.y != 0.0f || offset.z != 0.0f)
|
||||
{
|
||||
// add offset here for efficiency (saves an addition from afxXM_PathConform)
|
||||
for (U32 i = 0; i < num_points; i++)
|
||||
points[i] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void afxPathData::derive_rolls_array()
|
||||
{
|
||||
if (roll_string == ST_NULLSTRING)
|
||||
return;
|
||||
|
||||
if (rolls)
|
||||
{
|
||||
delete [] rolls;
|
||||
rolls = 0;
|
||||
}
|
||||
|
||||
Vector<F32> values;
|
||||
extract_floats_from_string(values, roll_string);
|
||||
if (values.size() == 0)
|
||||
return;
|
||||
|
||||
if (values.size() != num_points)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "afxPathData(%s) total roll values is not equal to total points, rolls ignored.", getName());
|
||||
return;
|
||||
}
|
||||
|
||||
U32 num_rolls = 0;
|
||||
rolls = build_floats_array(values, num_rolls, reverse);
|
||||
|
||||
AssertFatal(num_rolls == num_points, "Unexpected error: num_rolls disagrees with num_points.");
|
||||
}
|
||||
|
||||
void afxPathData::derive_times_array()
|
||||
{
|
||||
if (times_string == ST_NULLSTRING)
|
||||
return;
|
||||
|
||||
if (times)
|
||||
{
|
||||
delete [] times;
|
||||
times = 0;
|
||||
}
|
||||
|
||||
Vector<F32> values;
|
||||
extract_floats_from_string(values, times_string);
|
||||
if (values.size() == 0)
|
||||
return;
|
||||
|
||||
if (values.size() != num_points)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "afxPathData(%s) total time values is not equal to total points, times ignored", getName());
|
||||
return;
|
||||
}
|
||||
|
||||
U32 num_times = 0;
|
||||
times = build_floats_array(values, num_times, reverse);
|
||||
|
||||
AssertFatal(num_times == num_points, "Unexpected error: num_times disagrees with num_points.");
|
||||
}
|
||||
|
||||
void afxPathData::onPerformSubstitutions()
|
||||
{
|
||||
Parent::onPerformSubstitutions();
|
||||
update_derived_values();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
102
Engine/source/afx/util/afxPath.h
Normal file
102
Engine/source/afx/util/afxPath.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_PATH_H_
|
||||
#define _AFX_PATH_H_
|
||||
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
class afxPathData : public GameBaseData
|
||||
{
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
static StringTableEntry POINTS_FIELD;
|
||||
static StringTableEntry ROLL_FIELD;
|
||||
static StringTableEntry TIMES_FIELD;
|
||||
|
||||
bool resolved;
|
||||
bool update_points;
|
||||
bool update_rolls;
|
||||
bool update_times;
|
||||
|
||||
void update_derived_values();
|
||||
|
||||
void clear_arrays();
|
||||
void derive_points_array();
|
||||
void derive_rolls_array();
|
||||
void derive_times_array();
|
||||
|
||||
static void extract_floats_from_string(Vector<F32>& values, const char* points_str);
|
||||
static Point3F* build_points_array(Vector<F32>& values, U32& n_points, bool reverse=false);
|
||||
static F32* build_floats_array(Vector<F32>& values, U32& n_floats, bool reverse=false);
|
||||
|
||||
public:
|
||||
U32 num_points;
|
||||
StringTableEntry points_string;
|
||||
Point3F* points;
|
||||
|
||||
StringTableEntry roll_string;
|
||||
F32* rolls;
|
||||
|
||||
StringTableEntry times_string;
|
||||
F32* times;
|
||||
|
||||
StringTableEntry loop_string;
|
||||
F32 delay;
|
||||
F32 lifetime;
|
||||
|
||||
U32 loop_type;
|
||||
F32 mult;
|
||||
F32 time_offset;
|
||||
bool reverse;
|
||||
Point3F offset;
|
||||
bool echo;
|
||||
bool concentric;
|
||||
|
||||
public:
|
||||
/*C*/ afxPathData();
|
||||
/*C*/ afxPathData(const afxPathData&, bool = false);
|
||||
/*D*/ ~afxPathData();
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
virtual void packData(BitStream*);
|
||||
virtual void unpackData(BitStream*);
|
||||
|
||||
bool preload(bool server, String &errorStr);
|
||||
|
||||
virtual void onStaticModified(const char* slotName, const char* newValue = NULL);
|
||||
virtual void onPerformSubstitutions();
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(afxPathData);
|
||||
DECLARE_CATEGORY("AFX");
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_PATH_H_
|
||||
342
Engine/source/afx/util/afxPath3D.cpp
Normal file
342
Engine/source/afx/util/afxPath3D.cpp
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
|
||||
#include "console/console.h"
|
||||
|
||||
#include "afx/util/afxPath3D.h"
|
||||
|
||||
afxPath3D::afxPath3D() : start_time(0), num_points(0), loop_type(LOOP_CONSTANT)
|
||||
{
|
||||
}
|
||||
|
||||
afxPath3D::~afxPath3D()
|
||||
{
|
||||
}
|
||||
|
||||
void afxPath3D::sortAll()
|
||||
{
|
||||
curve.sort();
|
||||
curve_parameters.sort();
|
||||
}
|
||||
|
||||
void afxPath3D::setStartTime( F32 time )
|
||||
{
|
||||
start_time = time;
|
||||
}
|
||||
|
||||
void afxPath3D::setLoopType( U32 loop_type )
|
||||
{
|
||||
this->loop_type = loop_type;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
F32 afxPath3D::getEndTime()
|
||||
{
|
||||
return end_time;
|
||||
}
|
||||
|
||||
int afxPath3D::getNumPoints()
|
||||
{
|
||||
return num_points;
|
||||
}
|
||||
|
||||
Point3F afxPath3D::getPointPosition( int index )
|
||||
{
|
||||
if (index < 0 || index >= num_points)
|
||||
return Point3F(0.0f, 0.0f, 0.0f);
|
||||
|
||||
return curve.getPoint(index);
|
||||
}
|
||||
|
||||
F32 afxPath3D::getPointTime( int index )
|
||||
{
|
||||
if (index < 0 || index >= num_points)
|
||||
return 0.0f;
|
||||
|
||||
return curve_parameters.getKeyTime(index);
|
||||
}
|
||||
|
||||
F32 afxPath3D::getPointParameter( int index )
|
||||
{
|
||||
if (index < 0 || index >= num_points)
|
||||
return 0.0f;
|
||||
|
||||
return curve_parameters.getKeyValue(index);
|
||||
}
|
||||
|
||||
Point2F afxPath3D::getParameterSegment( F32 time )
|
||||
{
|
||||
return curve_parameters.getSegment(time);
|
||||
}
|
||||
|
||||
void afxPath3D::setPointPosition( int index, Point3F &p )
|
||||
{
|
||||
if (index < 0 || index >= num_points)
|
||||
return;
|
||||
|
||||
curve.setPoint(index, p);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
F32 afxPath3D::calcCurveTime( F32 time )
|
||||
{
|
||||
if( time <= start_time )
|
||||
return 0.0f;
|
||||
if( time <= end_time )
|
||||
return time-start_time;
|
||||
|
||||
switch( loop_type )
|
||||
{
|
||||
case LOOP_CYCLE :
|
||||
{
|
||||
return mFmod( time-start_time, end_time-start_time );
|
||||
}
|
||||
case LOOP_OSCILLATE :
|
||||
{
|
||||
F32 t1 = time-start_time;
|
||||
F32 t2 = end_time-start_time;
|
||||
|
||||
if( (int)(t1/t2) % 2 ) // odd segment
|
||||
return t2 - mFmod( t1, t2 );
|
||||
else // even segment
|
||||
return mFmod( t1, t2 );
|
||||
}
|
||||
case LOOP_CONSTANT :
|
||||
default:
|
||||
return end_time;
|
||||
}
|
||||
}
|
||||
|
||||
Point3F afxPath3D::evaluateAtTime( F32 time )
|
||||
{
|
||||
F32 ctime = calcCurveTime( time );
|
||||
F32 param = curve_parameters.evaluate( ctime );
|
||||
return curve.evaluate(param);
|
||||
}
|
||||
|
||||
Point3F afxPath3D::evaluateAtTime(F32 t0, F32 t1)
|
||||
{
|
||||
F32 ctime = calcCurveTime(t0);
|
||||
F32 param = curve_parameters.evaluate( ctime );
|
||||
Point3F p0 = curve.evaluate(param);
|
||||
|
||||
ctime = calcCurveTime(t1);
|
||||
param = curve_parameters.evaluate( ctime );
|
||||
Point3F p1 = curve.evaluate(param);
|
||||
|
||||
return p1-p0;
|
||||
}
|
||||
|
||||
Point3F afxPath3D::evaluateTangentAtTime( F32 time )
|
||||
{
|
||||
F32 ctime = calcCurveTime( time );
|
||||
F32 param = curve_parameters.evaluate( ctime );
|
||||
return curve.evaluateTangent(param);
|
||||
}
|
||||
|
||||
Point3F afxPath3D::evaluateTangentAtPoint( int index )
|
||||
{
|
||||
F32 param = curve_parameters.getKeyValue(index);
|
||||
return curve.evaluateTangent(param);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
void afxPath3D::buildPath( int num_points, Point3F curve_points[], F32 start_time, F32 end_time )
|
||||
{
|
||||
this->num_points = num_points;
|
||||
|
||||
// Add points to path
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f;
|
||||
for( int i = 0; i < num_points; i++, param += param_inc )
|
||||
{
|
||||
if( i == num_points-1 )
|
||||
param = 1.0f;
|
||||
curve.addPoint( param, curve_points[i] );
|
||||
}
|
||||
|
||||
curve.computeTangents();
|
||||
|
||||
initPathParametersNEW( curve_points, start_time, end_time );
|
||||
|
||||
sortAll();
|
||||
}
|
||||
|
||||
void afxPath3D::buildPath( int num_points, Point3F curve_points[], F32 speed )
|
||||
{
|
||||
this->num_points = num_points;
|
||||
|
||||
// Add points to path
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f;
|
||||
for( int i = 0; i < num_points; i++, param += param_inc )
|
||||
{
|
||||
if( i == num_points-1 )
|
||||
param = 1.0f;
|
||||
curve.addPoint( param, curve_points[i] );
|
||||
}
|
||||
|
||||
initPathParameters( curve_points, speed );
|
||||
|
||||
sortAll();
|
||||
}
|
||||
|
||||
void afxPath3D::buildPath( int num_points, Point3F curve_points[],
|
||||
F32 point_times[], F32 time_offset, F32 time_factor )
|
||||
{
|
||||
this->num_points = num_points;
|
||||
|
||||
// Add points to path
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f;
|
||||
for( int i = 0; i < num_points; i++, param += param_inc )
|
||||
{
|
||||
if( i == num_points-1 )
|
||||
param = 1.0f;
|
||||
curve.addPoint( param, curve_points[i] );
|
||||
|
||||
curve_parameters.addKey( (point_times[i]+time_offset)*time_factor, param );
|
||||
}
|
||||
|
||||
// Set end time
|
||||
end_time = (point_times[num_points-1]+time_offset)*time_factor;
|
||||
|
||||
sortAll();
|
||||
}
|
||||
|
||||
void afxPath3D::buildPath( int num_points, Point3F curve_points[], Point2F curve_params[] )
|
||||
{
|
||||
this->num_points = num_points;
|
||||
|
||||
// Add points to path
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f;
|
||||
for( int i = 0; i < num_points; i++, param += param_inc )
|
||||
{
|
||||
if( i == num_points-1 )
|
||||
param = 1.0f;
|
||||
curve.addPoint( param, curve_points[i] );
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < num_points; i++)
|
||||
curve_parameters.addKey( curve_params[i] );
|
||||
|
||||
// Set end time
|
||||
end_time = curve_params[num_points - 1].x;
|
||||
|
||||
sortAll();
|
||||
}
|
||||
|
||||
void afxPath3D::reBuildPath()
|
||||
{
|
||||
curve.computeTangents();
|
||||
sortAll();
|
||||
}
|
||||
|
||||
void afxPath3D::initPathParameters( Point3F curve_points[], F32 speed )
|
||||
{
|
||||
// Compute the time for each point dependent on the speed of the character and the
|
||||
// distance it must travel (approximately!)
|
||||
int num_segments = num_points - 1;
|
||||
F32 *point_distances = new F32[num_segments];
|
||||
for( int i = 0; i < num_segments; i++ )
|
||||
{
|
||||
Point3F p1 = curve_points[i+1];
|
||||
Point3F p0 = curve_points[i];
|
||||
|
||||
point_distances[i] = (p1-p0).len();
|
||||
}
|
||||
|
||||
F32 *times = new F32[num_segments];
|
||||
F32 last_time = 0;//start_time;
|
||||
for( int i = 0; i < num_segments; i++ )
|
||||
{
|
||||
times[i] = last_time + (point_distances[i] / speed);
|
||||
last_time = times[i];
|
||||
}
|
||||
|
||||
curve_parameters.addKey( 0, 0.0f );//start_time, 0.0f );
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f + param_inc;
|
||||
for( int i = 0; i < num_segments; i++, param += param_inc )
|
||||
curve_parameters.addKey( times[i], param );
|
||||
|
||||
// Set end time
|
||||
end_time = times[num_segments-1];
|
||||
|
||||
if (point_distances)
|
||||
delete [] point_distances;
|
||||
if (times)
|
||||
delete [] times;
|
||||
}
|
||||
|
||||
void afxPath3D::initPathParametersNEW( Point3F curve_points[], F32 start_time, F32 end_time )
|
||||
{
|
||||
int num_segments = num_points - 1;
|
||||
F32 *point_distances = new F32[num_segments];
|
||||
F32 total_distance = 0.0f;
|
||||
for( int i = 0; i < num_segments; i++ )
|
||||
{
|
||||
Point3F p1 = curve_points[i+1];
|
||||
Point3F p0 = curve_points[i];
|
||||
|
||||
point_distances[i] = (p1-p0).len();
|
||||
total_distance += point_distances[i];
|
||||
}
|
||||
|
||||
F32 duration = end_time - start_time;
|
||||
|
||||
F32 time = 0.0f; //start_time;
|
||||
curve_parameters.addKey( time, 0.0f );
|
||||
F32 param_inc = 1.0f / (F32)(num_points - 1);
|
||||
F32 param = 0.0f + param_inc;
|
||||
for( int i=0; i < num_segments; i++, param += param_inc )
|
||||
{
|
||||
time += (point_distances[i]/total_distance) * duration;
|
||||
curve_parameters.addKey( time, param );
|
||||
}
|
||||
|
||||
// Set end time ????
|
||||
//end_time = time;
|
||||
this->start_time = start_time;
|
||||
this->end_time = end_time;
|
||||
|
||||
if (point_distances)
|
||||
delete [] point_distances;
|
||||
}
|
||||
|
||||
void afxPath3D::print()
|
||||
{
|
||||
// curve.print();
|
||||
curve_parameters.print();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
101
Engine/source/afx/util/afxPath3D.h
Normal file
101
Engine/source/afx/util/afxPath3D.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AFX_PATH3D_UTIL_H_
|
||||
#define _AFX_PATH3D_UTIL_H_
|
||||
|
||||
#include "afx/util/afxCurve3D.h"
|
||||
#include "afx/util/afxAnimCurve.h"
|
||||
|
||||
#include "math/mMatrix.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
class afxPath3D : public EngineObject
|
||||
{
|
||||
private:
|
||||
// Path-related data
|
||||
afxCurve3D curve;
|
||||
afxAnimCurve curve_parameters;
|
||||
int num_points;
|
||||
|
||||
// Time data
|
||||
F32 start_time;
|
||||
F32 end_time;
|
||||
|
||||
public:
|
||||
/*C*/ afxPath3D( );
|
||||
/*D*/ ~afxPath3D();
|
||||
|
||||
void sortAll();
|
||||
|
||||
void setStartTime(F32 time);
|
||||
|
||||
F32 getEndTime();
|
||||
int getNumPoints();
|
||||
Point3F getPointPosition(int index);
|
||||
F32 getPointTime(int index);
|
||||
F32 getPointParameter(int index);
|
||||
Point2F getParameterSegment(F32 time);
|
||||
|
||||
void setPointPosition(int index, Point3F &p);
|
||||
|
||||
Point3F evaluateAtTime(F32 time);
|
||||
Point3F evaluateAtTime(F32 t0, F32 t1); // returns delta
|
||||
Point3F evaluateTangentAtTime(F32 time);
|
||||
Point3F evaluateTangentAtPoint(int index);
|
||||
|
||||
void buildPath(int num_points, Point3F curve_points[], F32 start_time, F32 end_time);
|
||||
void buildPath(int num_points, Point3F curve_points[], F32 speed);
|
||||
void buildPath(int num_points, Point3F curve_points[], F32 point_times[], F32 time_offset, F32 time_factor);
|
||||
void buildPath(int num_points, Point3F curve_points[], Point2F curve_params[]);
|
||||
|
||||
void reBuildPath();
|
||||
|
||||
void print();
|
||||
|
||||
enum LoopType
|
||||
{
|
||||
LOOP_CONSTANT,
|
||||
LOOP_CYCLE,
|
||||
LOOP_OSCILLATE
|
||||
};
|
||||
|
||||
U32 loop_type;
|
||||
void setLoopType(U32);
|
||||
|
||||
private:
|
||||
void initPathParameters(Point3F curve_points[], F32 speed);
|
||||
void initPathParametersNEW(Point3F curve_points[], F32 start_time, F32 end_time);
|
||||
|
||||
F32 calcCurveTime(F32 time);
|
||||
};
|
||||
|
||||
typedef afxPath3D::LoopType afxPath3DLoopType;
|
||||
DefineEnumType( afxPath3DLoopType );
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#endif // _AFX_PATH3D_UTIL_H_
|
||||
115
Engine/source/afx/util/afxTriBoxCheck2D_T3D.cpp
Normal file
115
Engine/source/afx/util/afxTriBoxCheck2D_T3D.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Adapted to a 2D test for intersecting atlas triangles with zodiacs.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AABB-triangle overlap test code originally by Tomas Akenine-Möller
|
||||
// Assisted by Pierre Terdiman and David Hunt
|
||||
// http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/
|
||||
// Ported to TSE by BJG, 2005-4-14
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
#include "afx/util/afxTriBoxCheck2D_T3D.h"
|
||||
|
||||
#define FINDMINMAX(x0,x1,x2,min,max) \
|
||||
min = max = x0; \
|
||||
if(x1<min) min=x1;\
|
||||
if(x1>max) max=x1;\
|
||||
if(x2<min) min=x2;\
|
||||
if(x2>max) max=x2;
|
||||
|
||||
/*======================== Z-tests ========================*/
|
||||
|
||||
#define AXISTEST_Z12(a, b, fa, fb) \
|
||||
p1 = a*v1.x - b*v1.y; \
|
||||
p2 = a*v2.x - b*v2.y; \
|
||||
if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
|
||||
if(min>rad || max<-rad) return false;
|
||||
|
||||
#define AXISTEST_Z0(a, b, fa, fb) \
|
||||
p0 = a*v0.x - b*v0.y; \
|
||||
p1 = a*v1.x - b*v1.y; \
|
||||
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
|
||||
if(min>rad || max<-rad) return false;
|
||||
|
||||
bool afxTriBoxOverlap2D(const Point3F& boxcenter, const Point3F& boxhalfsize, const Point3F& a, const Point3F& b, const Point3F& c)
|
||||
{
|
||||
/* use separating axis theorem to test overlap between triangle and box */
|
||||
/* need to test for overlap in these directions: */
|
||||
/* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
|
||||
/* we do not even need to test these) */
|
||||
/* 2) normal of the triangle */
|
||||
/* 3) crossproduct(edge from tri, {x,y,z}-directin) */
|
||||
/* this gives 3x3=9 more tests */
|
||||
|
||||
F32 min,max,p0,p1,p2,rad;
|
||||
|
||||
/* move everything so that the boxcenter is in (0,0,0) */
|
||||
Point3F v0 = a - boxcenter;
|
||||
Point3F v1 = b - boxcenter;
|
||||
Point3F v2 = c - boxcenter;
|
||||
|
||||
/* compute triangle edges */
|
||||
Point3F e0 = v1 - v0; /* tri edge 0 */
|
||||
Point3F e1 = v2 - v1; /* tri edge 1 */
|
||||
Point3F e2 = v0 - v2; /* tri edge 2 */
|
||||
|
||||
/* Bullet 3: */
|
||||
/* test the 3 tests first */
|
||||
F32 fex = mFabs(e0.x);
|
||||
F32 fey = mFabs(e0.y);
|
||||
AXISTEST_Z12(e0.y, e0.x, fey, fex);
|
||||
|
||||
fex = mFabs(e1.x);
|
||||
fey = mFabs(e1.y);
|
||||
AXISTEST_Z0(e1.y, e1.x, fey, fex);
|
||||
|
||||
fex = mFabs(e2.x);
|
||||
fey = mFabs(e2.y);
|
||||
AXISTEST_Z12(e2.y, e2.x, fey, fex);
|
||||
|
||||
/* Bullet 1: */
|
||||
/* first test overlap in the {x,y,z}-directions */
|
||||
/* find min, max of the triangle each direction, and test for overlap in */
|
||||
/* that direction -- this is equivalent to testing a minimal AABB around */
|
||||
/* the triangle against the AABB */
|
||||
|
||||
/* test in X-direction */
|
||||
FINDMINMAX(v0.x,v1.x,v2.x,min,max);
|
||||
if(min>boxhalfsize.x || max<-boxhalfsize.x) return false;
|
||||
|
||||
/* test in Y-direction */
|
||||
FINDMINMAX(v0.y,v1.y,v2.y,min,max);
|
||||
if(min>boxhalfsize.y || max<-boxhalfsize.y) return false;
|
||||
|
||||
return true; /* box and triangle overlaps */
|
||||
}
|
||||
|
||||
45
Engine/source/afx/util/afxTriBoxCheck2D_T3D.h
Normal file
45
Engine/source/afx/util/afxTriBoxCheck2D_T3D.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Adapted to a 2D test for intersecting atlas triangles with zodiacs.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AABB-triangle overlap test code originally by Tomas Akenine-Möller
|
||||
// Assisted by Pierre Terdiman and David Hunt
|
||||
// http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/
|
||||
// Ported to TSE by BJG, 2005-4-14
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _AFX_TRIBOXCHECK_2D_H_
|
||||
#define _AFX_TRIBOXCHECK_2D_H_
|
||||
|
||||
#include "math/mPoint3.h"
|
||||
#include "math/mBox.h"
|
||||
|
||||
bool afxTriBoxOverlap2D(const Point3F& boxcenter, const Point3F& boxhalfsize, const Point3F& a, const Point3F& b, const Point3F& c);
|
||||
|
||||
#endif // _AFX_TRIBOXCHECK_2D_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue