Add all new AFX files

This commit is contained in:
Marc Chapman 2017-07-26 09:35:44 +01:00
parent f2b86b7df3
commit ace877b409
218 changed files with 54970 additions and 0 deletions

View file

@ -0,0 +1,261 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_AimData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
bool aim_z_only;
public:
/*C*/ afxXM_AimData();
/*C*/ afxXM_AimData(const afxXM_AimData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_AimData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxConstraint;
class afxXM_Aim_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
public:
/*C*/ afxXM_Aim_weighted(afxXM_AimData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Aim_weighted_z : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
public:
/*C*/ afxXM_Aim_weighted_z(afxXM_AimData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Aim_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
public:
/*C*/ afxXM_Aim_fixed(afxXM_AimData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Aim_fixed_z : public afxXM_Base
{
typedef afxXM_Base Parent;
public:
/*C*/ afxXM_Aim_fixed_z(afxXM_AimData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_AimData);
ConsoleDocClass( afxXM_AimData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_AimData::afxXM_AimData()
{
aim_z_only = false;
}
afxXM_AimData::afxXM_AimData(const afxXM_AimData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
aim_z_only = other.aim_z_only;
}
void afxXM_AimData::initPersistFields()
{
addField("aimZOnly", TypeBool, Offset(aim_z_only, afxXM_AimData),
"...");
Parent::initPersistFields();
}
void afxXM_AimData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeFlag(aim_z_only);
}
void afxXM_AimData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
aim_z_only = stream->readFlag();
}
afxXM_Base* afxXM_AimData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_AimData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_AimData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->aim_z_only)
{
if (datablock->hasFixedWeight())
return new afxXM_Aim_fixed_z(datablock, fx);
else
return new afxXM_Aim_weighted_z(datablock, fx);
}
else
{
if (datablock->hasFixedWeight())
return new afxXM_Aim_fixed(datablock, fx);
else
return new afxXM_Aim_weighted(datablock, fx);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Aim_weighted::afxXM_Aim_weighted(afxXM_AimData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
}
void afxXM_Aim_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
VectorF line_of_sight = params.pos2 - params.pos;
line_of_sight.normalize();
F32 wt_factor = calc_weight_factor(elapsed);
QuatF qt_ori_incoming(params.ori);
MatrixF ori_outgoing = MathUtils::createOrientFromDir(line_of_sight);
QuatF qt_ori_outgoing(ori_outgoing);
QuatF qt_ori = qt_ori_incoming.slerp(qt_ori_outgoing, wt_factor);
qt_ori.setMatrix(&params.ori);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Aim_weighted_z::afxXM_Aim_weighted_z(afxXM_AimData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
}
void afxXM_Aim_weighted_z::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
Point3F aim_at_pos = params.pos2;
aim_at_pos.z = params.pos.z;
VectorF line_of_sight = aim_at_pos - params.pos;
line_of_sight.normalize();
F32 wt_factor = calc_weight_factor(elapsed);
QuatF qt_ori_incoming(params.ori);
MatrixF ori_outgoing = MathUtils::createOrientFromDir(line_of_sight);
QuatF qt_ori_outgoing( ori_outgoing );
QuatF qt_ori = qt_ori_incoming.slerp(qt_ori_outgoing, wt_factor);
qt_ori.setMatrix(&params.ori);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Aim_fixed::afxXM_Aim_fixed(afxXM_AimData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
}
void afxXM_Aim_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
VectorF line_of_sight = params.pos2 - params.pos;
line_of_sight.normalize();
params.ori = MathUtils::createOrientFromDir(line_of_sight);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Aim_fixed_z::afxXM_Aim_fixed_z(afxXM_AimData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
}
void afxXM_Aim_fixed_z::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
Point3F aim_at_pos = params.pos2;
aim_at_pos.z = params.pos.z;
VectorF line_of_sight = aim_at_pos - params.pos;
line_of_sight.normalize();
params.ori = MathUtils::createOrientFromDir(line_of_sight);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,262 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_AltitudeConformData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
F32 height;
bool do_terrain;
bool do_interiors;
U32 interior_types;
U32 terrain_types;
bool do_freeze;
public:
/*C*/ afxXM_AltitudeConformData();
/*C*/ afxXM_AltitudeConformData(const afxXM_AltitudeConformData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_AltitudeConformData);
DECLARE_CATEGORY("AFX");
};
class afxXM_AltitudeConform : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_AltitudeConformData* db;
SceneContainer* container;
bool do_freeze;
bool is_frozen;
F32 terrain_alt;
F32 interior_alt;
Point3F conformed_pos;
public:
/*C*/ afxXM_AltitudeConform(afxXM_AltitudeConformData*, afxEffectWrapper*, bool on_server);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_AltitudeConformData);
ConsoleDocClass( afxXM_AltitudeConformData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_AltitudeConformData::afxXM_AltitudeConformData()
{
height = 0.0f;
do_terrain = false;
do_interiors = true;
do_freeze = false;
interior_types = InteriorLikeObjectType;
terrain_types = TerrainObjectType | TerrainLikeObjectType;
}
afxXM_AltitudeConformData::afxXM_AltitudeConformData(const afxXM_AltitudeConformData& other, bool temp_clone)
: afxXM_WeightedBaseData(other, temp_clone)
{
height = other.height;
do_terrain = other.do_terrain;
do_interiors = other.do_interiors;
do_freeze = other.do_freeze;
interior_types = other.interior_types;
terrain_types = other.terrain_types;
}
void afxXM_AltitudeConformData::initPersistFields()
{
addField("height", TypeF32, Offset(height, afxXM_AltitudeConformData),
"...");
addField("conformToTerrain", TypeBool, Offset(do_terrain, afxXM_AltitudeConformData),
"...");
addField("conformToInteriors", TypeBool, Offset(do_interiors, afxXM_AltitudeConformData),
"...");
addField("freeze", TypeBool, Offset(do_freeze, afxXM_AltitudeConformData),
"...");
addField("interiorTypes", TypeS32, Offset(interior_types, afxXM_AltitudeConformData),
"...");
addField("terrainTypes", TypeS32, Offset(terrain_types, afxXM_AltitudeConformData),
"...");
Parent::initPersistFields();
}
void afxXM_AltitudeConformData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(height);
stream->writeFlag(do_terrain);
stream->writeFlag(do_interiors);
stream->writeFlag(do_freeze);
stream->write(interior_types);
stream->write(terrain_types);
}
void afxXM_AltitudeConformData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&height);
do_terrain = stream->readFlag();
do_interiors = stream->readFlag();
do_freeze = stream->readFlag();
stream->read(&interior_types);
stream->read(&terrain_types);
}
afxXM_Base* afxXM_AltitudeConformData::create(afxEffectWrapper* fx, bool on_server)
{
return new afxXM_AltitudeConform(this, fx, on_server);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_AltitudeConform::afxXM_AltitudeConform(afxXM_AltitudeConformData* db, afxEffectWrapper* fxw, bool on_server)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
container = (on_server) ? &gServerContainer : &gClientContainer;
do_freeze = db->do_freeze;
is_frozen = false;
terrain_alt = -1.0f;
interior_alt = -1.0f;
conformed_pos.zero();
}
void afxXM_AltitudeConform::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (is_frozen)
{
if (terrain_alt >= 0.0f)
fx_wrapper->setTerrainAltitude(terrain_alt);
if (interior_alt >= 0.0f)
fx_wrapper->setInteriorAltitude(interior_alt);
params.pos = conformed_pos;
return;
}
RayInfo rInfo1, rInfo2;
bool hit1 = false, hit2 = false;
bool hit1_is_interior = false;
// find primary ground
Point3F above_pos(params.pos); above_pos.z += 0.1f;
Point3F below_pos(params.pos); below_pos.z -= 10000;
hit1 = container->castRay(above_pos, below_pos, db->interior_types | db->terrain_types, &rInfo1);
// find secondary ground
if (hit1 && rInfo1.object)
{
hit1_is_interior = ((rInfo1.object->getTypeMask() & db->interior_types) != 0);
U32 mask = (hit1_is_interior) ? db->terrain_types : db->interior_types;
Point3F above_pos(params.pos); above_pos.z += 0.1f;
Point3F below_pos(params.pos); below_pos.z -= 10000;
hit2 = container->castRay(above_pos, below_pos, mask, &rInfo2);
}
if (hit1)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 incoming_z = params.pos.z;
F32 ground1_z = rInfo1.point.z + db->height;
F32 pos_z = ground1_z + (1.0f - wt_factor)*(incoming_z - ground1_z);
if (hit1_is_interior)
{
interior_alt = incoming_z - pos_z;
fx_wrapper->setInteriorAltitude(interior_alt);
if (db->do_interiors)
params.pos.z = pos_z;
}
else
{
terrain_alt = incoming_z - pos_z;
fx_wrapper->setTerrainAltitude(terrain_alt);
if (db->do_terrain)
params.pos.z = pos_z;
}
if (hit2)
{
F32 ground2_z = rInfo2.point.z + db->height;
F32 z2 = ground2_z + (1.0f - wt_factor)*(incoming_z - ground2_z);
if (hit1_is_interior)
{
terrain_alt = incoming_z - z2;
fx_wrapper->setTerrainAltitude(terrain_alt);
}
else
{
interior_alt = incoming_z - z2;
fx_wrapper->setInteriorAltitude(interior_alt);
}
}
// check for case where interior is underground
else if (hit1_is_interior)
{
RayInfo rInfo0;
Point3F lookup_from_pos(params.pos); lookup_from_pos.z -= 0.1f;
Point3F lookup_to_pos(params.pos); lookup_to_pos.z += 10000;
if (container->castRay(lookup_from_pos, lookup_to_pos, TerrainObjectType, &rInfo0))
{
F32 ground2_z = rInfo0.point.z + db->height;
F32 z2 = ground2_z + (1.0f - wt_factor)*(incoming_z - ground2_z);
terrain_alt = z2 - incoming_z;
fx_wrapper->setTerrainAltitude(terrain_alt);
}
}
if (do_freeze)
{
conformed_pos = params.pos;
is_frozen = true;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,175 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_BoxAdaptData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
F32 scale_factor;
Point2F dim_range;
public:
/*C*/ afxXM_BoxAdaptData();
/*C*/ afxXM_BoxAdaptData(const afxXM_BoxAdaptData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_BoxAdaptData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxConstraint;
class afxXM_BoxAdapt : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
F32 scale_factor;
Point2F dim_range;
public:
/*C*/ afxXM_BoxAdapt(afxXM_BoxAdaptData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_BoxAdaptData);
ConsoleDocClass( afxXM_BoxAdaptData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_BoxAdaptData::afxXM_BoxAdaptData()
{
scale_factor = 1.0f;
dim_range.set(0.1f, 1000.0f);
}
afxXM_BoxAdaptData::afxXM_BoxAdaptData(const afxXM_BoxAdaptData& other, bool temp_clone)
: afxXM_WeightedBaseData(other, temp_clone)
{
scale_factor = other.scale_factor;
dim_range = other.dim_range;
}
void afxXM_BoxAdaptData::initPersistFields()
{
addField("scaleFactor", TypeF32, Offset(scale_factor, afxXM_BoxAdaptData),
"...");
addField("dimensionRange", TypePoint2F, Offset(dim_range, afxXM_BoxAdaptData),
"...");
Parent::initPersistFields();
}
void afxXM_BoxAdaptData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(scale_factor);
mathWrite(*stream, dim_range);
}
void afxXM_BoxAdaptData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&scale_factor);
mathRead(*stream, &dim_range);
}
afxXM_Base* afxXM_BoxAdaptData::create(afxEffectWrapper* fx, bool on_server)
{
return new afxXM_BoxAdapt(this, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_BoxAdapt::afxXM_BoxAdapt(afxXM_BoxAdaptData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
scale_factor = db->scale_factor;
dim_range = db->dim_range;
dim_range.x = getMax(0.001f, dim_range.x);
dim_range.y = getMax(0.001f, dim_range.y);
if (dim_range.x > dim_range.y)
{
F32 tmp = dim_range.y;
dim_range.y = dim_range.x;
dim_range.x = tmp;
}
}
void afxXM_BoxAdapt::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
afxConstraint* pos_cons = fx_wrapper->getPosConstraint();
if (!pos_cons)
return;
SceneObject* obj = pos_cons->getSceneObject();
if (!obj)
return;
F32 wt_factor = calc_weight_factor(elapsed);
const Box3F& obj_box = obj->getObjBox();
const VectorF obj_scale = obj->getScale();
F32 x_dim = obj_box.len_x()*obj_scale.x;
F32 y_dim = obj_box.len_y()*obj_scale.y;
F32 dim = mClampF(getMax(x_dim, y_dim), dim_range.x, dim_range.y);
dim *= scale_factor*wt_factor*0.5f;
//Con::printf("SET liveScaleFactor=%g x_dim=%g, y_dim=%g", dim, obj_box.len_x(), obj_box.len_y());
fx_wrapper->setField("liveScaleFactor", avar("%g", dim));
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,175 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
enum afxXM_BoxConformType
{
X_POS, X_NEG, Y_POS, Y_NEG, Z_POS, Z_NEG
};
DefineEnumType( afxXM_BoxConformType );
class afxXM_BoxConformData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
S32 aabb_alignment;
public:
/*C*/ afxXM_BoxConformData();
/*C*/ afxXM_BoxConformData(const afxXM_BoxConformData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_BoxConformData);
DECLARE_CATEGORY("AFX");
};
class afxXM_BoxConform : public afxXM_Base
{
typedef afxXM_Base Parent;
afxXM_BoxConformData* db;
public:
/*C*/ afxXM_BoxConform(afxXM_BoxConformData*, afxEffectWrapper*, bool on_server);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_BoxConformData);
ConsoleDocClass( afxXM_BoxConformData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_BoxConformData::afxXM_BoxConformData()
{
aabb_alignment = Z_NEG;
}
afxXM_BoxConformData::afxXM_BoxConformData(const afxXM_BoxConformData& other, bool temp_clone)
: afxXM_BaseData(other, temp_clone)
{
aabb_alignment = other.aabb_alignment;
}
ImplementEnumType( afxXM_BoxConformType, "Possible box conform alignment types.\n" "@ingroup afxXM_BoxConform\n\n" )
{ X_POS, "+x", "..." },
{ X_NEG, "-x", "..." },
{ Y_POS, "+y", "..." },
{ Y_NEG, "-y", "..." },
{ Z_POS, "+z", "..." },
{ Z_NEG, "-z", "..." },
{ X_POS, "x", "..." },
{ Y_POS, "y", "..." },
{ Z_POS, "z", "..." },
EndImplementEnumType;
void afxXM_BoxConformData::initPersistFields()
{
addField("boxAlignment", TYPEID< afxXM_BoxConformType >(), Offset(aabb_alignment, afxXM_BoxConformData),
"...");
Parent::initPersistFields();
}
void afxXM_BoxConformData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(aabb_alignment);
}
void afxXM_BoxConformData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&aabb_alignment);
}
afxXM_Base* afxXM_BoxConformData::create(afxEffectWrapper* fx, bool on_server)
{
return new afxXM_BoxConform(this, fx, on_server);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_BoxConform::afxXM_BoxConform(afxXM_BoxConformData* db, afxEffectWrapper* fxw, bool on_server)
: afxXM_Base(db, fxw)
{
this->db = db;
}
void afxXM_BoxConform::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
afxConstraint* pos_cons = fx_wrapper->getPosConstraint();
if (!pos_cons)
return;
SceneObject* obj = pos_cons->getSceneObject();
if (!obj)
return;
const Box3F& box = obj->getWorldBox();
switch (db->aabb_alignment)
{
case X_POS:
params.pos.x = box.maxExtents.x;
break;
case X_NEG:
params.pos.x = box.minExtents.x;
break;
case Y_POS:
params.pos.y = box.maxExtents.y;
break;
case Y_NEG:
params.pos.y = box.minExtents.y;
break;
case Z_POS:
params.pos.z = box.maxExtents.z;
break;
case Z_NEG:
params.pos.z = box.minExtents.z;
break;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,145 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "afx/afxEffectWrapper.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// BOX HEIGHT OFFSET
class afxXM_BoxHeightOffsetData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
Point3F offset;
public:
/*C*/ afxXM_BoxHeightOffsetData();
/*C*/ afxXM_BoxHeightOffsetData(const afxXM_BoxHeightOffsetData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
#if defined(AFX_VERSION)
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
#else
afxXM_Base* create(afxEffectWrapper* fx);
#endif
DECLARE_CONOBJECT(afxXM_BoxHeightOffsetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_BoxHeightOffset : public afxXM_Base
{
typedef afxXM_Base Parent;
Point3F offset;
public:
/*C*/ afxXM_BoxHeightOffset(afxXM_BoxHeightOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// BOX HEIGHT OFFSET
IMPLEMENT_CO_DATABLOCK_V1(afxXM_BoxHeightOffsetData);
ConsoleDocClass( afxXM_BoxHeightOffsetData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_BoxHeightOffsetData::afxXM_BoxHeightOffsetData()
{
offset.zero();
}
afxXM_BoxHeightOffsetData::afxXM_BoxHeightOffsetData(const afxXM_BoxHeightOffsetData& other, bool temp_clone)
: afxXM_BaseData(other, temp_clone)
{
offset = other.offset;
}
void afxXM_BoxHeightOffsetData::initPersistFields()
{
addField("offset", TypePoint3F, Offset(offset, afxXM_BoxHeightOffsetData));
Parent::initPersistFields();
}
void afxXM_BoxHeightOffsetData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, offset);
}
void afxXM_BoxHeightOffsetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &offset);
}
#if defined(AFX_VERSION)
afxXM_Base* afxXM_BoxHeightOffsetData::create(afxEffectWrapper* fx, bool on_server)
#else
afxXM_Base* afxXM_BoxHeightOffsetData::create(afxEffectWrapper* fx)
#endif
{
return new afxXM_BoxHeightOffset(this, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_BoxHeightOffset::afxXM_BoxHeightOffset(afxXM_BoxHeightOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
offset = db->offset;
}
void afxXM_BoxHeightOffset::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
afxConstraint* pos_cons = fx_wrapper->getPosConstraint();
SceneObject* scn_obj = (pos_cons) ? pos_cons->getSceneObject() : 0;
if (scn_obj)
params.pos.z += scn_obj->getWorldBox().maxExtents.z - scn_obj->getWorldBox().minExtents.z;
params.pos += offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,336 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_FreezeData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
U32 mask;
F32 delay;
public:
/*C*/ afxXM_FreezeData() : mask(POSITION | ORIENTATION | POSITION2), delay(0.0f) { }
/*C*/ afxXM_FreezeData(const afxXM_FreezeData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_FreezeData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Freeze : public afxXM_Base
{
typedef afxXM_Base Parent;
U32 mask;
bool first;
Point3F frozen_pos;
MatrixF frozen_ori;
Point3F frozen_aim;
F32 delay;
public:
/*C*/ afxXM_Freeze(afxXM_FreezeData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Freeze_all_but_scale : public afxXM_Base
{
typedef afxXM_Base Parent;
bool first;
Point3F frozen_pos;
MatrixF frozen_ori;
Point3F frozen_aim;
F32 delay;
public:
/*C*/ afxXM_Freeze_all_but_scale(afxXM_FreezeData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Freeze_pos : public afxXM_Base
{
typedef afxXM_Base Parent;
bool first;
Point3F frozen_pos;
F32 delay;
public:
/*C*/ afxXM_Freeze_pos(afxXM_FreezeData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Freeze_pos2 : public afxXM_Base
{
typedef afxXM_Base Parent;
bool first;
Point3F frozen_pos2;
F32 delay;
public:
/*C*/ afxXM_Freeze_pos2(afxXM_FreezeData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Freeze_ori : public afxXM_Base
{
typedef afxXM_Base Parent;
bool first;
MatrixF frozen_ori;
F32 delay;
public:
/*C*/ afxXM_Freeze_ori(afxXM_FreezeData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_FreezeData);
ConsoleDocClass( afxXM_FreezeData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_FreezeData::afxXM_FreezeData(const afxXM_FreezeData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
mask = other.mask;
delay = other.delay;
}
void afxXM_FreezeData::initPersistFields()
{
addField("mask", TypeS32, Offset(mask, afxXM_FreezeData),
"...");
addField("delay", TypeF32, Offset(delay, afxXM_FreezeData),
"...");
Parent::initPersistFields();
}
void afxXM_FreezeData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(mask);
stream->write(delay);
}
void afxXM_FreezeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&mask);
stream->read(&delay);
}
afxXM_Base* afxXM_FreezeData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_FreezeData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_FreezeData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->mask == ALL_BUT_SCALE)
return new afxXM_Freeze_all_but_scale(datablock, fx);
if (datablock->mask == POSITION)
return new afxXM_Freeze_pos(datablock, fx);
if (datablock->mask == ORIENTATION)
return new afxXM_Freeze_ori(datablock, fx);
if (datablock->mask == POSITION2)
return new afxXM_Freeze_pos2(datablock, fx);
return new afxXM_Freeze(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Freeze::afxXM_Freeze(afxXM_FreezeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
mask = db->mask;
first = true;
delay = db->delay;
}
void afxXM_Freeze::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (elapsed < delay) return;
if (first)
{
if (mask & POSITION)
frozen_pos = params.pos;
if (mask & ORIENTATION)
frozen_ori = params.ori;
if (mask & POSITION2)
frozen_aim = params.pos2;
first = false;
}
else
{
if (mask & POSITION)
params.pos = frozen_pos;
if (mask & ORIENTATION)
params.ori = frozen_ori;
if (mask & POSITION2)
params.pos2 = frozen_aim;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Freeze_all_but_scale::afxXM_Freeze_all_but_scale(afxXM_FreezeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
first = true;
delay = db->delay;
}
void afxXM_Freeze_all_but_scale::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (elapsed < delay) return;
if (first)
{
frozen_pos = params.pos;
frozen_ori = params.ori;
frozen_aim = params.pos2;
first = false;
}
else
{
params.pos = frozen_pos;
params.ori = frozen_ori;
params.pos2 = frozen_aim;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Freeze_pos::afxXM_Freeze_pos(afxXM_FreezeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
first = true;
delay = db->delay;
}
void afxXM_Freeze_pos::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (elapsed < delay) return;
if (first)
{
frozen_pos = params.pos;
first = false;
}
else
params.pos = frozen_pos;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Freeze_pos2::afxXM_Freeze_pos2(afxXM_FreezeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
first = true;
delay = db->delay;
}
void afxXM_Freeze_pos2::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (elapsed < delay) return;
if (first)
{
frozen_pos2 = params.pos2;
first = false;
}
else
params.pos2 = frozen_pos2;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Freeze_ori::afxXM_Freeze_ori(afxXM_FreezeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
first = true;
delay = db->delay;
}
void afxXM_Freeze_ori::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (elapsed < delay) return;
if (first)
{
frozen_ori = params.ori;
first = false;
}
else
params.ori = frozen_ori;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,212 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_GroundConformData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
F32 height;
bool do_terrain;
bool do_interiors;
bool do_orientation;
public:
/*C*/ afxXM_GroundConformData();
/*C*/ afxXM_GroundConformData(const afxXM_GroundConformData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_GroundConformData);
DECLARE_CATEGORY("AFX");
};
class afxXM_GroundConform : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_GroundConformData* db;
SceneContainer* container;
public:
/*C*/ afxXM_GroundConform(afxXM_GroundConformData*, afxEffectWrapper*, bool on_server);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_GroundConformData);
ConsoleDocClass( afxXM_GroundConformData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_GroundConformData::afxXM_GroundConformData()
{
height = 0.0f;
do_terrain = true;
do_interiors = true;
do_orientation = false;
}
afxXM_GroundConformData::afxXM_GroundConformData(const afxXM_GroundConformData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
height = other.height;
do_terrain = other.do_terrain;
do_interiors = other.do_interiors;
do_orientation = other.do_orientation;
}
void afxXM_GroundConformData::initPersistFields()
{
addField("height", TypeF32, Offset(height, afxXM_GroundConformData),
"...");
addField("conformToTerrain", TypeBool, Offset(do_terrain, afxXM_GroundConformData),
"...");
addField("conformToInteriors", TypeBool, Offset(do_interiors, afxXM_GroundConformData),
"...");
addField("conformOrientation", TypeBool, Offset(do_orientation, afxXM_GroundConformData),
"...");
Parent::initPersistFields();
}
void afxXM_GroundConformData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(height);
stream->write(do_terrain);
stream->write(do_interiors);
stream->write(do_orientation);
}
void afxXM_GroundConformData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&height);
stream->read(&do_terrain);
stream->read(&do_interiors);
stream->read(&do_orientation);
}
afxXM_Base* afxXM_GroundConformData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_GroundConformData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_GroundConformData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_GroundConform(datablock, fx, on_server);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_GroundConform::afxXM_GroundConform(afxXM_GroundConformData* db, afxEffectWrapper* fxw, bool on_server)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
this->container = (on_server) ? &gServerContainer : &gClientContainer;
}
void afxXM_GroundConform::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
RayInfo rInfo;
bool hit = false;
if (db->do_interiors)
{
U32 mask = InteriorLikeObjectType;
if (db->do_terrain)
{
mask |= TerrainObjectType | TerrainLikeObjectType;
}
Point3F above_pos(params.pos); above_pos.z += 0.1f;
Point3F below_pos(params.pos); below_pos.z -= 10000;
hit = container->castRay(above_pos, below_pos, mask, &rInfo);
if (!hit)
{
above_pos.z = params.pos.z + 10000;
below_pos.z = params.pos.z - 0.1f;
hit = container->castRay(below_pos, above_pos, mask, &rInfo);
}
}
else if (db->do_terrain)
{
U32 mask = TerrainObjectType | TerrainLikeObjectType;
Point3F above_pos(params.pos); above_pos.z += 10000;
Point3F below_pos(params.pos); below_pos.z -= 10000;
hit = container->castRay(above_pos, below_pos, mask, &rInfo);
}
if (hit)
{
F32 terrain_z = rInfo.point.z;
F32 wt_factor = calc_weight_factor(elapsed);
F32 old_z = params.pos.z;
F32 new_z = terrain_z + db->height;
params.pos.z = ((1-wt_factor)*old_z) + ((wt_factor)*new_z);
if (db->do_orientation)
{
Point3F x,y,z;
z = rInfo.normal;
z.normalize();
params.ori.getColumn(1,&y);
mCross(y,z,&x);
x.normalize();
mCross(z,x,&y);
params.ori.setColumn(0,x);
params.ori.setColumn(1,y);
params.ori.setColumn(2,z);
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,146 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_HeightSamplerData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
/*C*/ afxXM_HeightSamplerData();
/*C*/ afxXM_HeightSamplerData(const afxXM_HeightSamplerData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_HeightSamplerData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxConstraint;
class afxXM_HeightSampler : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
public:
/*C*/ afxXM_HeightSampler(afxXM_HeightSamplerData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_HeightSamplerData);
ConsoleDocClass( afxXM_HeightSamplerData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_HeightSamplerData::afxXM_HeightSamplerData()
{
}
afxXM_HeightSamplerData::afxXM_HeightSamplerData(const afxXM_HeightSamplerData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
}
void afxXM_HeightSamplerData::initPersistFields()
{
Parent::initPersistFields();
}
void afxXM_HeightSamplerData::packData(BitStream* stream)
{
Parent::packData(stream);
}
void afxXM_HeightSamplerData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
}
afxXM_Base* afxXM_HeightSamplerData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_HeightSamplerData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_HeightSamplerData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_HeightSampler(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_HeightSampler::afxXM_HeightSampler(afxXM_HeightSamplerData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
}
void afxXM_HeightSampler::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
afxConstraint* pos_cons = fx_wrapper->getPosConstraint();
if (!pos_cons)
return;
Point3F base_pos;
pos_cons->getPosition(base_pos);
F32 range = 0.5f;
F32 height = (base_pos.z > params.pos.z) ? (base_pos.z - params.pos.z) : 0.0f;
F32 factor = mClampF(1.0f - (height/range), 0.0f, 1.0f);
//Con::printf("SET height=%g liveScaleFactor=%g", height, factor);
fx_wrapper->setField("liveScaleFactor", avar("%g", factor));
fx_wrapper->setField("liveFadeFactor", avar("%g", factor));
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,231 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_MountedImageNodeData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
StringTableEntry node_name; // name of a mounted-image node
U32 image_slot; // which mounted-image?
// (0 <= image_slot < MaxMountedImages)
public:
/*C*/ afxXM_MountedImageNodeData();
/*C*/ afxXM_MountedImageNodeData(const afxXM_MountedImageNodeData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_MountedImageNodeData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_MountedImageNode : public afxXM_Base
{
typedef afxXM_Base Parent;
StringTableEntry node_name;
U32 image_slot;
S32 node_ID;
ShapeBase* shape;
afxConstraint* cons;
afxConstraint* find_constraint();
public:
/*C*/ afxXM_MountedImageNode(afxXM_MountedImageNodeData*, afxEffectWrapper*);
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_MountedImageNodeData);
ConsoleDocClass( afxXM_MountedImageNodeData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_MountedImageNodeData::afxXM_MountedImageNodeData()
{
image_slot = 0;
node_name = ST_NULLSTRING;
}
afxXM_MountedImageNodeData::afxXM_MountedImageNodeData(const afxXM_MountedImageNodeData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
image_slot = other.image_slot;
node_name = other.node_name;
}
void afxXM_MountedImageNodeData::initPersistFields()
{
addField("imageSlot", TypeS32, Offset(image_slot, afxXM_MountedImageNodeData),
"...");
addField("nodeName", TypeString, Offset(node_name, afxXM_MountedImageNodeData),
"...");
Parent::initPersistFields();
}
void afxXM_MountedImageNodeData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(image_slot);
stream->writeString(node_name);
}
void afxXM_MountedImageNodeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&image_slot);
node_name = stream->readSTString();
}
bool afxXM_MountedImageNodeData::onAdd()
{
if (Parent::onAdd() == false)
return false;
if (image_slot >= ShapeBase::MaxMountedImages)
{
// datablock will not be added if imageSlot is out-of-bounds
Con::errorf(ConsoleLogEntry::General,
"afxXM_MountedImageNodeData(%s): imageSlot (%u) >= MaxMountedImages (%d)",
getName(),
image_slot,
ShapeBase::MaxMountedImages);
return false;
}
return true;
}
afxXM_Base* afxXM_MountedImageNodeData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_MountedImageNodeData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_MountedImageNodeData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_MountedImageNode(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_MountedImageNode::afxXM_MountedImageNode(afxXM_MountedImageNodeData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
image_slot = db->image_slot;
node_name = db->node_name;
cons = 0;
node_ID = -1;
shape = 0;
}
// find the first constraint with a shape by checking pos
// then orient constraints in that order.
afxConstraint* afxXM_MountedImageNode::find_constraint()
{
afxConstraint* cons = fx_wrapper->getOrientConstraint();
if (cons && dynamic_cast<ShapeBase*>(cons->getSceneObject()))
return cons;
cons = fx_wrapper->getPosConstraint();
if (cons && dynamic_cast<ShapeBase*>(cons->getSceneObject()))
return cons;
return 0;
}
void afxXM_MountedImageNode::start(F32 timestamp)
{
// constraint won't change over the modifier's
// lifetime so we find it here in start().
cons = find_constraint();
if (!cons)
Con::errorf(ConsoleLogEntry::General,
"afxXM_MountedImageNode: failed to find a ShapeBase derived constraint source.");
}
void afxXM_MountedImageNode::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (!cons)
return;
// validate shape
// The shape must be validated in case it gets deleted
// of goes out scope.
SceneObject* scene_object = cons->getSceneObject();
if (scene_object != (SceneObject*)shape)
{
shape = dynamic_cast<ShapeBase*>(scene_object);
if (shape && node_name != ST_NULLSTRING)
{
node_ID = shape->getNodeIndex(image_slot, node_name);
if (node_ID < 0)
{
Con::errorf(ConsoleLogEntry::General,
"afxXM_MountedImageNode: failed to find nodeName, \"%s\".",
node_name);
}
}
else
node_ID = -1;
}
if (shape)
{
shape->getImageTransform(image_slot, node_ID, &params.ori);
params.pos = params.ori.getPosition();
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,489 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// LOCAL OFFSET
class afxXM_LocalOffsetData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
Point3F local_offset;
bool offset_pos2;
public:
/*C*/ afxXM_LocalOffsetData();
/*C*/ afxXM_LocalOffsetData(const afxXM_LocalOffsetData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_LocalOffsetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_LocalOffset_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F local_offset;
public:
/*C*/ afxXM_LocalOffset_weighted(afxXM_LocalOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_LocalOffset_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
Point3F local_offset;
public:
/*C*/ afxXM_LocalOffset_fixed(afxXM_LocalOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_LocalOffset2_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F local_offset;
public:
/*C*/ afxXM_LocalOffset2_weighted(afxXM_LocalOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_LocalOffset2_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
Point3F local_offset;
public:
/*C*/ afxXM_LocalOffset2_fixed(afxXM_LocalOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WORLD OFFSET
class afxXM_WorldOffsetData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
Point3F world_offset;
bool offset_pos2;
public:
/*C*/ afxXM_WorldOffsetData();
/*C*/ afxXM_WorldOffsetData(const afxXM_WorldOffsetData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_WorldOffsetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WorldOffset_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F world_offset;
public:
/*C*/ afxXM_WorldOffset_weighted(afxXM_WorldOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_WorldOffset_fixed : public afxXM_Base
{
typedef afxXM_WeightedBase Parent;
Point3F world_offset;
public:
/*C*/ afxXM_WorldOffset_fixed(afxXM_WorldOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WorldOffset2_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F world_offset;
public:
/*C*/ afxXM_WorldOffset2_weighted(afxXM_WorldOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_WorldOffset2_fixed : public afxXM_Base
{
typedef afxXM_WeightedBase Parent;
Point3F world_offset;
public:
/*C*/ afxXM_WorldOffset2_fixed(afxXM_WorldOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// LOCAL OFFSET
IMPLEMENT_CO_DATABLOCK_V1(afxXM_LocalOffsetData);
ConsoleDocClass( afxXM_LocalOffsetData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_LocalOffsetData::afxXM_LocalOffsetData()
{
local_offset.zero();
offset_pos2 = false;
}
afxXM_LocalOffsetData::afxXM_LocalOffsetData(const afxXM_LocalOffsetData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
local_offset = other.local_offset;
offset_pos2 = other.offset_pos2;
}
void afxXM_LocalOffsetData::initPersistFields()
{
addField("localOffset", TypePoint3F, Offset(local_offset, afxXM_LocalOffsetData),
"...");
addField("offsetPos2", TypeBool, Offset(offset_pos2, afxXM_LocalOffsetData),
"...");
Parent::initPersistFields();
}
void afxXM_LocalOffsetData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, local_offset);
stream->writeFlag(offset_pos2);
}
void afxXM_LocalOffsetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &local_offset);
offset_pos2 = stream->readFlag();
}
afxXM_Base* afxXM_LocalOffsetData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_LocalOffsetData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_LocalOffsetData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->offset_pos2)
{
if (datablock->hasFixedWeight())
return new afxXM_LocalOffset2_fixed(datablock, fx);
else
return new afxXM_LocalOffset2_weighted(datablock, fx);
}
else
{
if (datablock->hasFixedWeight())
return new afxXM_LocalOffset_fixed(datablock, fx);
else
return new afxXM_LocalOffset_weighted(datablock, fx);
}
}
//~~~~~~~~~~~~~~~~~~~~//
afxXM_LocalOffset_weighted::afxXM_LocalOffset_weighted(afxXM_LocalOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
local_offset = db->local_offset*db->getWeightFactor();
}
void afxXM_LocalOffset_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
Point3F offset(local_offset*wt_factor);
params.ori.mulV(offset);
params.pos += offset;
}
//~~~~~~~~~~~~~~~~~~~~//
afxXM_LocalOffset_fixed::afxXM_LocalOffset_fixed(afxXM_LocalOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
local_offset = db->local_offset*db->getWeightFactor();
}
void afxXM_LocalOffset_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
Point3F offset(local_offset);
params.ori.mulV(offset);
params.pos += offset;
}
//~~~~~~~~~~~~~~~~~~~~//
afxXM_LocalOffset2_weighted::afxXM_LocalOffset2_weighted(afxXM_LocalOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
local_offset = db->local_offset*db->getWeightFactor();
}
void afxXM_LocalOffset2_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
Point3F offset(local_offset*wt_factor);
afxConstraint* pos2_cons = fx_wrapper->getAimConstraint();
if (pos2_cons)
{
MatrixF ori2;
pos2_cons->getTransform(ori2);
ori2.mulV(offset);
}
params.pos2 += offset;
}
//~~~~~~~~~~~~~~~~~~~~//
afxXM_LocalOffset2_fixed::afxXM_LocalOffset2_fixed(afxXM_LocalOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
local_offset = db->local_offset*db->getWeightFactor();
}
void afxXM_LocalOffset2_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
Point3F offset(local_offset);
afxConstraint* pos2_cons = fx_wrapper->getAimConstraint();
if (pos2_cons)
{
MatrixF ori2;
pos2_cons->getTransform(ori2);
ori2.mulV(offset);
}
params.pos2 += offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WORLD OFFSET
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WorldOffsetData);
ConsoleDocClass( afxXM_WorldOffsetData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WorldOffsetData::afxXM_WorldOffsetData()
{
world_offset.zero();
offset_pos2 = false;
}
afxXM_WorldOffsetData::afxXM_WorldOffsetData(const afxXM_WorldOffsetData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
world_offset = other.world_offset;
offset_pos2 = other.offset_pos2;
}
void afxXM_WorldOffsetData::initPersistFields()
{
addField("worldOffset", TypePoint3F, Offset(world_offset, afxXM_WorldOffsetData),
"...");
addField("offsetPos2", TypeBool, Offset(offset_pos2, afxXM_WorldOffsetData),
"...");
Parent::initPersistFields();
}
void afxXM_WorldOffsetData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, world_offset);
stream->writeFlag(offset_pos2);
}
void afxXM_WorldOffsetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &world_offset);
offset_pos2 = stream->readFlag();
}
afxXM_Base* afxXM_WorldOffsetData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_WorldOffsetData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_WorldOffsetData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->offset_pos2)
{
if (datablock->hasFixedWeight())
return new afxXM_WorldOffset2_fixed(datablock, fx);
else
return new afxXM_WorldOffset2_weighted(datablock, fx);
}
else
{
if (datablock->hasFixedWeight())
return new afxXM_WorldOffset_fixed(datablock, fx);
else
return new afxXM_WorldOffset_weighted(datablock, fx);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_WorldOffset_weighted::afxXM_WorldOffset_weighted(afxXM_WorldOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
world_offset = db->world_offset*db->getWeightFactor();
}
void afxXM_WorldOffset_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
params.pos += world_offset*wt_factor;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_WorldOffset_fixed::afxXM_WorldOffset_fixed(afxXM_WorldOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
world_offset = db->world_offset*db->getWeightFactor();
}
void afxXM_WorldOffset_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
params.pos += world_offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_WorldOffset2_weighted::afxXM_WorldOffset2_weighted(afxXM_WorldOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
world_offset = db->world_offset*db->getWeightFactor();
}
void afxXM_WorldOffset2_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
params.pos2 += world_offset*wt_factor;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_WorldOffset2_fixed::afxXM_WorldOffset2_fixed(afxXM_WorldOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
world_offset = db->world_offset*db->getWeightFactor();
}
void afxXM_WorldOffset2_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
params.pos2 += world_offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,379 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_OscillateData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
U32 mask;
Point3F min;
Point3F max;
F32 speed;
Point3F axis;
bool additive_scale;
bool local_offset;
public:
/*C*/ afxXM_OscillateData();
/*C*/ afxXM_OscillateData(const afxXM_OscillateData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_OscillateData);
DECLARE_CATEGORY("AFX");
};
class afxXM_Oscillate_rot : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_OscillateData* db;
public:
/*C*/ afxXM_Oscillate_rot(afxXM_OscillateData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
class afxXM_Oscillate_scale : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_OscillateData* db;
public:
/*C*/ afxXM_Oscillate_scale(afxXM_OscillateData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
class afxXM_Oscillate_position : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_OscillateData* db;
public:
/*C*/ afxXM_Oscillate_position(afxXM_OscillateData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
class afxXM_Oscillate_position2 : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_OscillateData* db;
public:
/*C*/ afxXM_Oscillate_position2(afxXM_OscillateData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
class afxXM_Oscillate : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_OscillateData* db;
public:
/*C*/ afxXM_Oscillate(afxXM_OscillateData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_OscillateData);
ConsoleDocClass( afxXM_OscillateData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_OscillateData::afxXM_OscillateData()
{
mask = POSITION;
min.set(0,0,0);
max.set(1,1,1);
speed = 1.0f;
axis.set(0,0,1);
additive_scale = false;
local_offset = true;
}
afxXM_OscillateData::afxXM_OscillateData(const afxXM_OscillateData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
mask = other.mask;
min = other.min;
max = other.max;
speed = other.speed;
axis = other.axis;
additive_scale = other.additive_scale;
local_offset = other.local_offset;
}
void afxXM_OscillateData::initPersistFields()
{
addField("mask", TypeS32, Offset(mask, afxXM_OscillateData),
"...");
addField("min", TypePoint3F, Offset(min, afxXM_OscillateData),
"...");
addField("max", TypePoint3F, Offset(max, afxXM_OscillateData),
"...");
addField("speed", TypeF32, Offset(speed, afxXM_OscillateData),
"...");
addField("axis", TypePoint3F, Offset(axis, afxXM_OscillateData),
"...");
addField("additiveScale", TypeBool, Offset(additive_scale, afxXM_OscillateData),
"...");
addField("localOffset", TypeBool, Offset(local_offset, afxXM_OscillateData),
"...");
Parent::initPersistFields();
}
void afxXM_OscillateData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(mask);
mathWrite(*stream, min);
mathWrite(*stream, max);
stream->write(speed);
mathWrite(*stream, axis);
stream->writeFlag(additive_scale);
stream->writeFlag(local_offset);
}
void afxXM_OscillateData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&mask);
mathRead(*stream, &min);
mathRead(*stream, &max);
stream->read(&speed);
mathRead(*stream, &axis);
additive_scale = stream->readFlag();
local_offset = stream->readFlag();
}
afxXM_Base* afxXM_OscillateData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_OscillateData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_OscillateData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->mask == ORIENTATION)
return new afxXM_Oscillate_rot(datablock, fx);
if (datablock->mask == SCALE)
return new afxXM_Oscillate_scale(datablock, fx);
if (datablock->mask == POSITION)
return new afxXM_Oscillate_position(datablock, fx);
if (datablock->mask == POSITION2)
return new afxXM_Oscillate_position2(datablock, fx);
return new afxXM_Oscillate(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
inline F32 lerp(F32 t, F32 a, F32 b)
{
return a + t * (b - a);
}
inline Point3F lerpV(F32 t, const Point3F& a, const Point3F& b)
{
return Point3F( a.x + t * (b.x - a.x),
a.y + t * (b.y - a.y),
a.z + t * (b.z - a.z) );
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Oscillate_rot::afxXM_Oscillate_rot(afxXM_OscillateData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
void afxXM_Oscillate_rot::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 t = mSin(db->speed*elapsed); // [-1,1]
F32 theta = lerp((t+1)/2, db->min.x*wt_factor, db->max.x*wt_factor);
theta = mDegToRad(theta);
AngAxisF rot_aa(db->axis, theta);
MatrixF rot_xfm; rot_aa.setMatrix(&rot_xfm);
params.ori.mul(rot_xfm);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Oscillate_scale::afxXM_Oscillate_scale(afxXM_OscillateData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
void afxXM_Oscillate_scale::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 t = mSin(db->speed*elapsed); // [-1,1]
F32 s = lerp((t+1)/2, db->min.x*wt_factor, db->max.x*wt_factor);
Point3F xm_scale = db->axis*s;
if (db->additive_scale)
params.scale += xm_scale;
else
params.scale *= xm_scale;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Oscillate_position::afxXM_Oscillate_position(afxXM_OscillateData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
void afxXM_Oscillate_position::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 t = mSin(db->speed*elapsed); // [-1,1]
Point3F offset = lerpV(t, db->min*wt_factor, db->max*wt_factor);
if (db->local_offset)
{
params.ori.mulV(offset);
params.pos += offset;
}
else
params.pos += offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Oscillate_position2::afxXM_Oscillate_position2(afxXM_OscillateData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
void afxXM_Oscillate_position2::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 t = mSin(db->speed*elapsed); // [-1,1]
Point3F offset = lerpV(t, db->min*wt_factor, db->max*wt_factor);
params.pos2 += offset;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Oscillate::afxXM_Oscillate(afxXM_OscillateData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
void afxXM_Oscillate::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 t = mSin(db->speed*elapsed); // [-1,1]
if (db->mask & POSITION)
{
Point3F offset = lerpV(t, db->min*wt_factor, db->max*wt_factor);
if (db->local_offset)
{
params.ori.mulV(offset);
params.pos += offset;
}
else
params.pos += offset;
}
if (db->mask & POSITION2)
{
Point3F offset = lerpV(t, db->min*wt_factor, db->max*wt_factor);
params.pos2 += offset;
}
if (db->mask & SCALE)
{
F32 s = lerp((t+1)/2, db->min.x*wt_factor, db->max.x*wt_factor);
Point3F xm_scale = db->axis*s;
if (db->additive_scale)
params.scale += xm_scale;
else
params.scale *= xm_scale;
}
if (db->mask & ORIENTATION)
{
F32 theta = lerp((t+1)/2, db->min.x*wt_factor, db->max.x*wt_factor);
theta = mDegToRad(theta);
AngAxisF rot_aa(db->axis, theta);
MatrixF rot_xfm; rot_aa.setMatrix(&rot_xfm);
params.ori.mul(rot_xfm);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,161 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_OscillateZodiacColorData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
LinearColorF color_a;
LinearColorF color_b;
F32 speed;
public:
/*C*/ afxXM_OscillateZodiacColorData();
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_OscillateZodiacColorData);
DECLARE_CATEGORY("AFX");
};
class afxXM_OscillateZodiacColor : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
LinearColorF color_a;
LinearColorF color_b;
F32 speed;
LinearColorF* liveColor_ptr;
F32* liveColorFactor_ptr;
public:
/*C*/ afxXM_OscillateZodiacColor(afxXM_OscillateZodiacColorData*, afxEffectWrapper*);
virtual void update(F32 dt, F32 elapsed, Point3F& pos, MatrixF& ori, Point3F& pos2,
Point3F& scale);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_OscillateZodiacColorData);
ConsoleDocClass( afxXM_OscillateZodiacColorData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_OscillateZodiacColorData::afxXM_OscillateZodiacColorData()
{
color_a.set(0.0f, 0.0f, 0.0f, 0.0f);
color_b.set(1.0f, 1.0f, 1.0f, 1.0f);
speed = 1.0f;
}
void afxXM_OscillateZodiacColorData::initPersistFields()
{
addField("colorA", TypeColorF, Offset(color_a, afxXM_OscillateZodiacColorData),
"...");
addField("colorB", TypeColorF, Offset(color_b, afxXM_OscillateZodiacColorData),
"...");
addField("speed", TypeF32, Offset(speed, afxXM_OscillateZodiacColorData),
"...");
Parent::initPersistFields();
}
void afxXM_OscillateZodiacColorData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(color_a);
stream->write(color_b);
stream->write(speed);
}
void afxXM_OscillateZodiacColorData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&color_a);
stream->read(&color_b);
stream->read(&speed);
}
afxXM_Base* afxXM_OscillateZodiacColorData::create(afxEffectWrapper* fx, bool on_server)
{
return new afxXM_OscillateZodiacColor(this, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_OscillateZodiacColor::afxXM_OscillateZodiacColor(afxXM_OscillateZodiacColorData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
color_a = db->color_a;
color_b = db->color_b;
speed = db->speed;
const AbstractClassRep::Field* field;
field = fxw->getClassRep()->findField(StringTable->insert("liveColor"));
if (field && field->type == TypeColorF)
liveColor_ptr = (LinearColorF*)(((const char *)(fxw)) + field->offset);
else
liveColor_ptr = 0;
field = fxw->getClassRep()->findField(StringTable->insert("liveColorFactor"));
if (field && field->type == TypeF32)
liveColorFactor_ptr = (F32*)(((const char *)(fxw)) + field->offset);
else
liveColorFactor_ptr = 0;
}
void afxXM_OscillateZodiacColor::update(F32 dt, F32 elapsed, Point3F& pos, MatrixF& ori, Point3F& pos2, Point3F& scale)
{
F32 wt_factor = calc_weight_factor(elapsed);
if (liveColor_ptr)
{
F32 t = (1.0f + mSin((3.0f*M_PI_F)/2.0f + speed*elapsed*M_2PI_F))*0.5f;
liveColor_ptr->interpolate(color_a, color_b, t);
}
if (liveColorFactor_ptr)
*liveColorFactor_ptr = wt_factor;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,412 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// PATH CONFORM
class afxPathData;
class afxXM_PathConformData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
StringTableEntry paths_string; //
Vector<afxPathData*> pathDataBlocks; // datablocks for paths
Vector<U32> pathDataBlockIds; // datablock IDs which correspond to the pathDataBlocks
F32 path_mult;
F32 path_time_offset;
bool orient_to_path;
public:
/*C*/ afxXM_PathConformData();
/*C*/ afxXM_PathConformData(const afxXM_PathConformData&, bool = false);
bool onAdd();
bool preload(bool server, String &errorStr);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_PathConformData);
DECLARE_CATEGORY("AFX");
};
class afxPath3D;
class afxAnimCurve;
class afxXM_PathConform : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxXM_PathConformData* db;
Vector<afxPath3D*> paths;
Vector<F32> path_mults;
Vector<F32> path_time_offsets;
Vector<afxAnimCurve*> rolls;
void init_paths(F32 lifetime);
public:
/*C*/ afxXM_PathConform(afxXM_PathConformData*, afxEffectWrapper*);
/*D*/ ~afxXM_PathConform();
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_PathConformData);
ConsoleDocClass( afxXM_PathConformData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_PathConformData::afxXM_PathConformData()
{
paths_string = ST_NULLSTRING;
pathDataBlocks.clear();
pathDataBlockIds.clear();
path_mult = 1.0f;
path_time_offset = 0.0f;
orient_to_path = false;
}
afxXM_PathConformData::afxXM_PathConformData(const afxXM_PathConformData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
paths_string = other.paths_string;
pathDataBlocks = other.pathDataBlocks;
pathDataBlockIds = other.pathDataBlockIds;
path_mult = other.path_mult;
path_time_offset = other.path_time_offset;
orient_to_path = other.orient_to_path;
}
void afxXM_PathConformData::initPersistFields()
{
addField("paths", TypeString, Offset(paths_string, afxXM_PathConformData),
"...");
addField("pathMult", TypeF32, Offset(path_mult, afxXM_PathConformData),
"...");
addField("pathTimeOffset", TypeF32, Offset(path_time_offset, afxXM_PathConformData),
"...");
addField("orientToPath", TypeBool, Offset(orient_to_path, afxXM_PathConformData),
"...");
Parent::initPersistFields();
// disallow some field substitutions
disableFieldSubstitutions("paths");
}
void afxXM_PathConformData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(pathDataBlockIds.size());
for (int i = 0; i < pathDataBlockIds.size(); i++)
stream->write(pathDataBlockIds[i]);
stream->write(path_mult);
stream->write(path_time_offset);
stream->write(orient_to_path);
}
void afxXM_PathConformData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
U32 n_db;
stream->read(&n_db);
pathDataBlockIds.setSize(n_db);
for (U32 i = 0; i < n_db; i++)
stream->read(&pathDataBlockIds[i]);
stream->read(&path_mult);
stream->read(&path_time_offset);
stream->read(&orient_to_path);
}
bool afxXM_PathConformData::onAdd()
{
if (Parent::onAdd() == false)
return false;
if (paths_string != ST_NULLSTRING)
{
//Con::printf("afxEffectWrapperData: Path string found: %s", paths_string);
}
if (paths_string != ST_NULLSTRING && paths_string[0] == '\0')
{
Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) empty paths string, invalid datablock", getName());
return false;
}
if (paths_string != ST_NULLSTRING && dStrlen(paths_string) > 255)
{
Con::errorf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) paths string too long [> 255 chars]", getName());
return false;
}
if (paths_string != ST_NULLSTRING)
{
Vector<char*> dataBlocks(__FILE__, __LINE__);
char* tokCopy = new char[dStrlen(paths_string) + 1];
dStrcpy(tokCopy, paths_string);
char* currTok = dStrtok(tokCopy, " \t");
while (currTok != NULL)
{
dataBlocks.push_back(currTok);
currTok = dStrtok(NULL, " \t");
}
if (dataBlocks.size() == 0)
{
Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) invalid paths string. No datablocks found", getName());
delete [] tokCopy;
return false;
}
pathDataBlocks.clear();
pathDataBlockIds.clear();
for (U32 i = 0; i < dataBlocks.size(); i++)
{
afxPathData* pData = NULL;
if (Sim::findObject(dataBlocks[i], pData) == false)
{
Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) unable to find path datablock: %s", getName(), dataBlocks[i]);
}
else
{
pathDataBlocks.push_back(pData);
pathDataBlockIds.push_back(pData->getId());
}
}
delete [] tokCopy;
if (pathDataBlocks.size() == 0)
{
Con::warnf(ConsoleLogEntry::General, "afxEffectWrapperData(%s) unable to find any path datablocks", getName());
return false;
}
}
return true;
}
bool afxXM_PathConformData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
pathDataBlocks.clear();
for (U32 i = 0; i < pathDataBlockIds.size(); i++)
{
afxPathData* pData = NULL;
if (Sim::findObject(pathDataBlockIds[i], pData) == false)
{
Con::warnf(ConsoleLogEntry::General,
"afxEffectWrapperData(%s) unable to find path datablock: %d",
getName(), pathDataBlockIds[i]);
}
else
pathDataBlocks.push_back(pData);
}
return true;
}
afxXM_Base* afxXM_PathConformData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_PathConformData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_PathConformData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_PathConform(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_PathConform::afxXM_PathConform(afxXM_PathConformData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
}
afxXM_PathConform::~afxXM_PathConform()
{
for (S32 i = 0; i < paths.size(); i++)
if (paths[i])
delete paths[i];
for (S32 j = 0; j < paths.size(); j++)
if (rolls[j])
delete rolls[j];
}
void afxXM_PathConform::start(F32 timestamp)
{
init_paths(fx_wrapper->getFullLifetime());
}
void afxXM_PathConform::init_paths(F32 lifetime)
{
for( U32 i=0; i < db->pathDataBlocks.size(); i++ )
{
afxPathData* pd = db->pathDataBlocks[i];
if (!pd)
continue;
if (pd->getSubstitutionCount() > 0)
{
afxPathData* orig_db = pd;
pd = new afxPathData(*orig_db, true);
orig_db->performSubstitutions(pd, fx_wrapper->getChoreographer(), fx_wrapper->getGroupIndex());
}
if (pd->num_points > 0)
{
if (pd->lifetime == 0)
{
if (lifetime <= 0)
{
// Is this possible or is the lifetime always inherited properly???
}
else
{
pd->lifetime = lifetime;
}
}
F32 pd_delay = pd->delay*time_factor;
F32 pd_lifetime = pd->lifetime*time_factor;
F32 pd_time_offset = pd->time_offset*time_factor;
afxPath3D* path = new afxPath3D();
if (pd->times)
path->buildPath( pd->num_points, pd->points, pd->times, pd_delay, time_factor );
else
path->buildPath( pd->num_points, pd->points, pd_delay, pd_delay+pd_lifetime );
path->setLoopType( pd->loop_type );
paths.push_back(path);
// path->print();
path_mults.push_back( db->path_mult * pd->mult );
path_time_offsets.push_back( db->path_time_offset + pd_time_offset );
if (pd->roll_string != ST_NULLSTRING && pd->rolls != NULL)
{
afxAnimCurve* roll_curve = new afxAnimCurve();
for (U32 j=0; j<pd->num_points; j++ )
{
roll_curve->addKey( path->getPointTime(j), pd->rolls[j] );
}
roll_curve->sort();
// roll_curve->print();
rolls.push_back(roll_curve);
}
else
{
rolls.push_back( NULL );
}
}
else
{
Con::warnf("afxXM_PathConform::init_paths() -- paths datablock (%d) has no points.", i);
}
if (pd->isTempClone())
delete pd;
}
}
void afxXM_PathConform::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
// compute path offset
VectorF path_offset(0,0,0);
for( U32 i=0; i < paths.size(); i++ )
path_offset += path_mults[i]*paths[i]->evaluateAtTime(elapsed + path_time_offsets[i])*wt_factor;
params.ori.mulV(path_offset);
params.pos += path_offset;
if (db->orient_to_path && paths.size())
{
VectorF path_v = paths[0]->evaluateTangentAtTime(elapsed+path_time_offsets[0]);
path_v.normalize();
MatrixF mat(true);
if( rolls[0] )
{
F32 roll_angle = rolls[0]->evaluate(elapsed+path_time_offsets[0]);
roll_angle = mDegToRad( roll_angle );
//Con::printf( "roll: %f", roll_angle );
Point3F roll_axis = path_v;
AngAxisF rollRot(roll_axis, roll_angle);
MatrixF roll_mat(true);
rollRot.setMatrix(&roll_mat);
mat.mul(roll_mat);
}
mat.mul(MathUtils::createOrientFromDir(path_v));
params.ori.mul(mat);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,180 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "ts/tsShapeInstance.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_PivotNodeOffsetData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
StringTableEntry node_name;
bool node_is_static;
public:
/*C*/ afxXM_PivotNodeOffsetData();
/*C*/ afxXM_PivotNodeOffsetData(const afxXM_PivotNodeOffsetData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_PivotNodeOffsetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_PivotNodeOffset : public afxXM_Base
{
typedef afxXM_Base Parent;
StringTableEntry node_name;
bool node_is_static;
S32 node_ID;
Point3F pivot_offset;
bool offset_calculated;
public:
/*C*/ afxXM_PivotNodeOffset(afxXM_PivotNodeOffsetData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_PivotNodeOffsetData);
ConsoleDocClass( afxXM_PivotNodeOffsetData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_PivotNodeOffsetData::afxXM_PivotNodeOffsetData()
{
node_name = ST_NULLSTRING;
node_is_static = true;
}
afxXM_PivotNodeOffsetData::afxXM_PivotNodeOffsetData(const afxXM_PivotNodeOffsetData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
node_name = other.node_name;
node_is_static = other.node_is_static;
}
void afxXM_PivotNodeOffsetData::initPersistFields()
{
addField("nodeName", TypeString, Offset(node_name, afxXM_PivotNodeOffsetData),
"...");
addField("nodeIsStatic", TypeBool, Offset(node_is_static, afxXM_PivotNodeOffsetData),
"...");
Parent::initPersistFields();
}
void afxXM_PivotNodeOffsetData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(node_name);
stream->writeFlag(node_is_static);
}
void afxXM_PivotNodeOffsetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
node_name = stream->readSTString();
node_is_static = stream->readFlag();
}
afxXM_Base* afxXM_PivotNodeOffsetData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_PivotNodeOffsetData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_PivotNodeOffsetData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_PivotNodeOffset(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_PivotNodeOffset::afxXM_PivotNodeOffset(afxXM_PivotNodeOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
node_name = db->node_name;
node_is_static = db->node_is_static;
node_ID = -1;
pivot_offset.set(0,0,0);
offset_calculated = false;
}
void afxXM_PivotNodeOffset::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (node_ID < 0)
{
TSShape* ts_shape = fx_wrapper->getTSShape();
node_ID = (ts_shape) ? ts_shape->findNode(node_name) : -1;
}
if (node_ID >= 0)
{
if (!node_is_static || !offset_calculated)
{
TSShapeInstance* ts_shape_inst = fx_wrapper->getTSShapeInstance();
if (ts_shape_inst)
{
const MatrixF& pivot_xfm = ts_shape_inst->mNodeTransforms[node_ID];
pivot_offset = -pivot_xfm.getPosition();
offset_calculated = true;
}
}
}
// re-orient pivot offset then add to position
Point3F pivot_offset_temp;
params.ori.mulV(pivot_offset, &pivot_offset_temp);
params.pos += pivot_offset_temp;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,181 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_RandomRotData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
Point3F axis;
F32 theta_min;
F32 theta_max;
F32 phi_min;
F32 phi_max;
public:
/*C*/ afxXM_RandomRotData();
/*C*/ afxXM_RandomRotData(const afxXM_RandomRotData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_RandomRotData);
DECLARE_CATEGORY("AFX");
};
class afxXM_RandomRot : public afxXM_Base
{
typedef afxXM_Base Parent;
MatrixF rand_ori;
public:
/*C*/ afxXM_RandomRot(afxXM_RandomRotData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_RandomRotData);
ConsoleDocClass( afxXM_RandomRotData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_RandomRotData::afxXM_RandomRotData()
{
axis.set(0,0,1);
theta_min = 0.0f;
theta_max = 360.0f;
phi_min = 0.0f;
phi_max = 360.0f;
}
afxXM_RandomRotData::afxXM_RandomRotData(const afxXM_RandomRotData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
axis = other.axis;
theta_min = other.theta_min;
theta_max = other.theta_max;
phi_min = other.phi_min;
phi_max = other.phi_max;
}
void afxXM_RandomRotData::initPersistFields()
{
addField("axis", TypePoint3F, Offset(axis, afxXM_RandomRotData),
"...");
addField("thetaMin", TypeF32, Offset(theta_min, afxXM_RandomRotData),
"...");
addField("thetaMax", TypeF32, Offset(theta_max, afxXM_RandomRotData),
"...");
addField("phiMin", TypeF32, Offset(phi_min, afxXM_RandomRotData),
"...");
addField("phiMax", TypeF32, Offset(phi_max, afxXM_RandomRotData),
"...");
Parent::initPersistFields();
}
void afxXM_RandomRotData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, axis);
stream->write(theta_min);
stream->write(theta_max);
stream->write(phi_min);
stream->write(phi_max);
}
void afxXM_RandomRotData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &axis);
stream->read(&theta_min);
stream->read(&theta_max);
stream->read(&phi_min);
stream->read(&phi_max);
}
bool afxXM_RandomRotData::onAdd()
{
if (Parent::onAdd() == false)
return false;
axis.normalizeSafe();
return true;
}
afxXM_Base* afxXM_RandomRotData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_RandomRotData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_RandomRotData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_RandomRot(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_RandomRot::afxXM_RandomRot(afxXM_RandomRotData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
Point3F rand_dir = MathUtils::randomDir(db->axis, db->theta_min, db->theta_max, db->phi_min, db->phi_max);
rand_ori = MathUtils::createOrientFromDir(rand_dir);
}
void afxXM_RandomRot::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
params.ori = rand_ori;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,155 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_ScaleData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
Point3F scale;
public:
/*C*/ afxXM_ScaleData();
/*C*/ afxXM_ScaleData(const afxXM_ScaleData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_ScaleData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Scale_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F xm_scale;
public:
/*C*/ afxXM_Scale_weighted(afxXM_ScaleData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_ScaleData);
ConsoleDocClass( afxXM_ScaleData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_ScaleData::afxXM_ScaleData()
{
scale.set(0,0,0);
}
afxXM_ScaleData::afxXM_ScaleData(const afxXM_ScaleData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
scale = other.scale;
}
void afxXM_ScaleData::initPersistFields()
{
addField("scale", TypePoint3F, Offset(scale, afxXM_ScaleData),
"...");
Parent::initPersistFields();
}
void afxXM_ScaleData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, scale);
}
void afxXM_ScaleData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &scale);
}
afxXM_Base* afxXM_ScaleData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_ScaleData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_ScaleData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->hasFixedWeight())
return new afxXM_Scale_weighted(datablock, fx);
else
return new afxXM_Scale_weighted(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Scale_weighted::afxXM_Scale_weighted(afxXM_ScaleData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
xm_scale = db->scale;
}
void afxXM_Scale_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
params.scale += xm_scale*wt_factor;
if (params.scale.x < 0.00001f)
params.scale.x = 0.00001f;
if (params.scale.y < 0.00001f)
params.scale.y = 0.00001f;
if (params.scale.z < 0.00001f)
params.scale.z = 0.00001f;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,170 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_ShockwaveData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
F32 rate;
bool aim_z_only;
public:
/*C*/ afxXM_ShockwaveData();
/*C*/ afxXM_ShockwaveData(const afxXM_ShockwaveData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_ShockwaveData);
DECLARE_CATEGORY("AFX");
};
class afxConstraint;
class afxXM_Shockwave : public afxXM_Base
{
typedef afxXM_Base Parent;
afxXM_ShockwaveData* db;
bool first;
Point3F fixed_pos;
public:
/*C*/ afxXM_Shockwave(afxXM_ShockwaveData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_ShockwaveData);
ConsoleDocClass( afxXM_ShockwaveData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_ShockwaveData::afxXM_ShockwaveData()
{
rate = 1.0f;
aim_z_only = false;
}
afxXM_ShockwaveData::afxXM_ShockwaveData(const afxXM_ShockwaveData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
rate = other.rate;
aim_z_only = other.aim_z_only;
}
void afxXM_ShockwaveData::initPersistFields()
{
addField("rate", TypeF32, Offset(rate, afxXM_ShockwaveData),
"...");
addField("aimZOnly", TypeBool, Offset(aim_z_only, afxXM_ShockwaveData),
"...");
Parent::initPersistFields();
}
void afxXM_ShockwaveData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(rate);
stream->write(aim_z_only);
}
void afxXM_ShockwaveData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&rate);
stream->read(&aim_z_only);
}
afxXM_Base* afxXM_ShockwaveData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_ShockwaveData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_ShockwaveData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
return new afxXM_Shockwave(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Shockwave::afxXM_Shockwave(afxXM_ShockwaveData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
this->db = db;
first = true;
fixed_pos.zero();
}
void afxXM_Shockwave::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (first)
{
fixed_pos = params.pos;
first = false;
}
Point3F aim_at_pos = params.pos2;
if (db->aim_z_only)
aim_at_pos.z = fixed_pos.z;
VectorF line_of_sight = aim_at_pos - fixed_pos;
line_of_sight.normalize();
params.pos = fixed_pos + line_of_sight*(elapsed*db->rate);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,241 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_SpinData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
Point3F spin_axis;
F32 spin_angle;
F32 spin_angle_var;
F32 spin_rate;
F32 spin_rate_var;
public:
/*C*/ afxXM_SpinData() : spin_axis(0,0,1), spin_angle(0), spin_angle_var(0), spin_rate(0), spin_rate_var(0) { }
/*C*/ afxXM_SpinData(const afxXM_SpinData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_SpinData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Spin_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
Point3F spin_axis;
F32 spin_rate;
F32 theta;
public:
/*C*/ afxXM_Spin_weighted(afxXM_SpinData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_Spin_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
Point3F spin_axis;
F32 spin_rate;
F32 theta;
public:
/*C*/ afxXM_Spin_fixed(afxXM_SpinData*, afxEffectWrapper*);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_SpinData);
ConsoleDocClass( afxXM_SpinData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_SpinData::afxXM_SpinData(const afxXM_SpinData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
spin_axis = other.spin_axis;
spin_angle = other.spin_angle;
spin_angle_var = other.spin_angle_var;
spin_rate = other.spin_rate;
spin_rate_var = other.spin_rate_var;
}
void afxXM_SpinData::initPersistFields()
{
addField("spinAxis", TypePoint3F, Offset(spin_axis, afxXM_SpinData),
"...");
addField("spinAngle", TypeF32, Offset(spin_angle, afxXM_SpinData),
"...");
addField("spinAngleVariance", TypeF32, Offset(spin_angle_var, afxXM_SpinData),
"...");
addField("spinRate", TypeF32, Offset(spin_rate, afxXM_SpinData),
"...");
addField("spinRateVariance", TypeF32, Offset(spin_rate_var, afxXM_SpinData),
"...");
Parent::initPersistFields();
}
void afxXM_SpinData::packData(BitStream* stream)
{
Parent::packData(stream);
mathWrite(*stream, spin_axis);
stream->write(spin_angle);
stream->write(spin_angle_var);
stream->write(spin_rate);
stream->write(spin_rate_var);
}
void afxXM_SpinData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mathRead(*stream, &spin_axis);
stream->read(&spin_angle);
stream->read(&spin_angle_var);
stream->read(&spin_rate);
stream->read(&spin_rate_var);
}
bool afxXM_SpinData::onAdd()
{
if (Parent::onAdd() == false)
return false;
spin_axis.normalizeSafe();
return true;
}
afxXM_Base* afxXM_SpinData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_SpinData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_SpinData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->hasFixedWeight())
return new afxXM_Spin_fixed(datablock, fx);
else
return new afxXM_Spin_weighted(datablock, fx);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Spin_weighted::afxXM_Spin_weighted(afxXM_SpinData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
spin_axis = db->spin_axis;
spin_rate = db->spin_rate;
if (db->spin_rate_var != 0.0f)
spin_rate += gRandGen.randF()*2.0f*db->spin_rate_var - db->spin_rate_var;
spin_rate *= db->getWeightFactor()/time_factor;
F32 spin_angle = db->spin_angle;
if (db->spin_angle_var != 0.0f)
spin_angle += gRandGen.randF()*2.0f*db->spin_angle_var - db->spin_angle_var;
theta = mDegToRad(spin_angle);
}
void afxXM_Spin_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 rate = spin_rate*wt_factor;
theta += mDegToRad(dt*rate);
AngAxisF spin_aa(spin_axis, theta);
MatrixF spin_xfm; spin_aa.setMatrix(&spin_xfm);
params.ori.mul(spin_xfm);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Spin_fixed::afxXM_Spin_fixed(afxXM_SpinData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
spin_axis = db->spin_axis;
spin_rate = db->spin_rate;
if (db->spin_rate_var != 0.0f)
spin_rate += gRandGen.randF()*2.0f*db->spin_rate_var - db->spin_rate_var;
spin_rate *= db->getWeightFactor()/time_factor;
F32 spin_angle = db->spin_angle;
if (db->spin_angle_var != 0.0f)
spin_angle += gRandGen.randF()*2.0f*db->spin_angle_var - db->spin_angle_var;
theta = mDegToRad(spin_angle);
}
void afxXM_Spin_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
theta += mDegToRad(dt*spin_rate);
AngAxisF spin_aa(spin_axis, theta);
MatrixF spin_xfm; spin_aa.setMatrix(&spin_xfm);
params.ori.mul(spin_xfm);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,373 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "math/mathUtils.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXfmMod.h"
#include "afx/util/afxPath3D.h"
#include "afx/util/afxPath.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// VELOCITY OFFSET
class afxXM_VelocityOffsetData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
F32 offset_factor;
bool offset_pos2;
bool normalize;
public:
/*C*/ afxXM_VelocityOffsetData();
/*C*/ afxXM_VelocityOffsetData(const afxXM_VelocityOffsetData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_VelocityOffsetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_VelocityOffset_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxConstraint* cons;
F32 offset_factor;
bool normalize;
public:
/*C*/ afxXM_VelocityOffset_weighted(afxXM_VelocityOffsetData*, afxEffectWrapper*);
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_VelocityOffset_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
afxConstraint* cons;
F32 offset_factor;
bool normalize;
public:
/*C*/ afxXM_VelocityOffset_fixed(afxXM_VelocityOffsetData*, afxEffectWrapper*);
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_VelocityOffset2_weighted : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
afxConstraint* cons;
F32 offset_factor;
bool normalize;
public:
/*C*/ afxXM_VelocityOffset2_weighted(afxXM_VelocityOffsetData*, afxEffectWrapper*);
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// this fixed variation is used when
// the weight factors are constant.
class afxXM_VelocityOffset2_fixed : public afxXM_Base
{
typedef afxXM_Base Parent;
afxConstraint* cons;
F32 offset_factor;
bool normalize;
public:
/*C*/ afxXM_VelocityOffset2_fixed(afxXM_VelocityOffsetData*, afxEffectWrapper*);
virtual void start(F32 timestamp);
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// VELOCITY OFFSET
IMPLEMENT_CO_DATABLOCK_V1(afxXM_VelocityOffsetData);
ConsoleDocClass( afxXM_VelocityOffsetData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_VelocityOffsetData::afxXM_VelocityOffsetData()
{
offset_factor = 1.0f;
offset_pos2 = false;
normalize = false;
}
afxXM_VelocityOffsetData::afxXM_VelocityOffsetData(const afxXM_VelocityOffsetData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
offset_factor = other.offset_factor;
offset_pos2 = other.offset_pos2;
normalize = other.normalize;
}
void afxXM_VelocityOffsetData::initPersistFields()
{
addField("offsetFactor", TypeF32, Offset(offset_factor, afxXM_VelocityOffsetData),
"...");
addField("offsetPos2", TypeBool, Offset(offset_pos2, afxXM_VelocityOffsetData),
"...");
addField("normalize", TypeBool, Offset(normalize, afxXM_VelocityOffsetData),
"...");
Parent::initPersistFields();
}
void afxXM_VelocityOffsetData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(offset_factor);
stream->write(offset_pos2);
}
void afxXM_VelocityOffsetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&offset_factor);
stream->read(&offset_pos2);
}
afxXM_Base* afxXM_VelocityOffsetData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_VelocityOffsetData* datablock = this;
if (getSubstitutionCount() > 0)
{
datablock = new afxXM_VelocityOffsetData(*this, true);
this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex());
}
if (datablock->offset_pos2)
{
if (datablock->hasFixedWeight())
return new afxXM_VelocityOffset2_fixed(datablock, fx);
else
return new afxXM_VelocityOffset2_weighted(datablock, fx);
}
else
{
if (datablock->hasFixedWeight())
return new afxXM_VelocityOffset_fixed(datablock, fx);
else
return new afxXM_VelocityOffset_weighted(datablock, fx);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_VelocityOffset_weighted::afxXM_VelocityOffset_weighted(afxXM_VelocityOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
cons = 0;
offset_factor = db->offset_factor*db->getWeightFactor();
normalize = db->normalize;
}
void afxXM_VelocityOffset_weighted::start(F32 timestamp)
{
Parent::start(timestamp);
cons = fx_wrapper->getPosConstraint();
if (!cons)
Con::errorf(ConsoleLogEntry::General,
"afxXM_VelocityOffset: failed to find a SceneObject derived constraint source.");
}
void afxXM_VelocityOffset_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (!cons)
return;
SceneObject* scene_obj = cons->getSceneObject();
if (scene_obj)
{
Point3F vel_vec = scene_obj->getVelocity();
if (!vel_vec.isZero())
{
if (normalize)
vel_vec.normalize();
F32 wt_factor = calc_weight_factor(elapsed);
params.pos += vel_vec*offset_factor*wt_factor;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_VelocityOffset_fixed::afxXM_VelocityOffset_fixed(afxXM_VelocityOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
cons = 0;
offset_factor = db->offset_factor*db->getWeightFactor();
normalize = db->normalize;
}
void afxXM_VelocityOffset_fixed::start(F32 timestamp)
{
Parent::start(timestamp);
cons = fx_wrapper->getPosConstraint();
if (!cons)
Con::errorf(ConsoleLogEntry::General,
"afxXM_VelocityOffset: failed to find a SceneObject derived constraint source.");
}
void afxXM_VelocityOffset_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (!cons)
return;
SceneObject* scene_obj = cons->getSceneObject();
if (scene_obj)
{
Point3F vel_vec = scene_obj->getVelocity();
if (!vel_vec.isZero())
{
if (normalize)
vel_vec.normalize(offset_factor);
params.pos += vel_vec*offset_factor;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_VelocityOffset2_weighted::afxXM_VelocityOffset2_weighted(afxXM_VelocityOffsetData* db, afxEffectWrapper* fxw)
: afxXM_WeightedBase(db, fxw)
{
cons = 0;
offset_factor = db->offset_factor*db->getWeightFactor();
normalize = db->normalize;
}
void afxXM_VelocityOffset2_weighted::start(F32 timestamp)
{
Parent::start(timestamp);
cons = fx_wrapper->getAimConstraint();
if (!cons)
Con::errorf(ConsoleLogEntry::General,
"afxXM_VelocityOffset: failed to find a SceneObject derived constraint source.");
}
void afxXM_VelocityOffset2_weighted::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (!cons)
return;
SceneObject* scene_obj = cons->getSceneObject();
if (scene_obj)
{
Point3F vel_vec = scene_obj->getVelocity();
if (!vel_vec.isZero())
{
if (normalize)
vel_vec.normalize();
F32 wt_factor = calc_weight_factor(elapsed);
params.pos2 += vel_vec*offset_factor*wt_factor;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_VelocityOffset2_fixed::afxXM_VelocityOffset2_fixed(afxXM_VelocityOffsetData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
cons = 0;
offset_factor = db->offset_factor*db->getWeightFactor();
normalize = db->normalize;
}
void afxXM_VelocityOffset2_fixed::start(F32 timestamp)
{
Parent::start(timestamp);
cons = fx_wrapper->getAimConstraint();
if (!cons)
Con::errorf(ConsoleLogEntry::General,
"afxXM_VelocityOffset: failed to find a SceneObject derived constraint source.");
}
void afxXM_VelocityOffset2_fixed::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (!cons)
return;
SceneObject* scene_obj = cons->getSceneObject();
if (scene_obj)
{
Point3F vel_vec = scene_obj->getVelocity();
if (!vel_vec.isZero())
{
if (normalize)
vel_vec.normalize(offset_factor);
params.pos2 += vel_vec*offset_factor;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,610 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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 "math/mathIO.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXM_WaveBase.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveBaseData);
ConsoleDocClass( afxXM_WaveBaseData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveBaseData::afxXM_WaveBaseData()
{
waveform_type = WAVEFORM_SINE;
parameter = PARAM_NONE;
op = OP_ADD;
speed = 1.0f;
speed_vari = 0.0;
accel = 0.0f;
phase_shift = 0.0f;
duty_cycle = 1.0f;
duty_shift = 0.0f;
off_duty_t = 0.0f;
waves_per_pulse.set(1,1);
waves_per_rest.set(0,0);
rest_dur = 0.0f;
rest_dur_vari = 0.0f;
axis.zero();
local_axis = true;
}
afxXM_WaveBaseData::afxXM_WaveBaseData(const afxXM_WaveBaseData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
waveform_type = other.waveform_type;
parameter = other.parameter;
op = other.op;
speed = other.speed;
speed_vari = other.speed;
accel = other.accel;
phase_shift = other.phase_shift;
duty_cycle = other.duty_cycle;
duty_shift = other.duty_shift;
off_duty_t = other.off_duty_t;
waves_per_pulse = other.waves_per_pulse;
waves_per_rest = other.waves_per_rest;
rest_dur = other.rest_dur;
rest_dur_vari = other.rest_dur_vari;
axis = other.axis;
local_axis = true;
}
ImplementEnumType( afxXM_WaveFormType, "Possible waveform types.\n" "@ingroup afxXM_WaveBase\n\n" )
{ afxXM_WaveBaseData::WAVEFORM_NONE, "none", "..." },
{ afxXM_WaveBaseData::WAVEFORM_SINE, "sine", "..." },
{ afxXM_WaveBaseData::WAVEFORM_SQUARE, "square", "..." },
{ afxXM_WaveBaseData::WAVEFORM_TRIANGLE, "triangle", "..." },
{ afxXM_WaveBaseData::WAVEFORM_SAWTOOTH, "sawtooth", "..." },
{ afxXM_WaveBaseData::WAVEFORM_NOISE, "noise", "..." },
{ afxXM_WaveBaseData::WAVEFORM_ONE, "one", "..." },
EndImplementEnumType;
ImplementEnumType( afxXM_WaveParamType, "Possible wave parameter types.\n" "@ingroup afxXM_WaveBase\n\n" )
{ afxXM_WaveBaseData::PARAM_NONE, "none", "..." },
{ afxXM_WaveBaseData::PARAM_POS, "pos", "..." },
{ afxXM_WaveBaseData::PARAM_POS_X, "pos.x", "..." },
{ afxXM_WaveBaseData::PARAM_POS_Y, "pos.y", "..." },
{ afxXM_WaveBaseData::PARAM_POS_Z, "pos.z", "..." },
{ afxXM_WaveBaseData::PARAM_ORI, "ori", "..." },
{ afxXM_WaveBaseData::PARAM_POS2, "pos2", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_X, "pos2.x", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_Y, "pos2.y", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_Z, "pos2.z", "..." },
{ afxXM_WaveBaseData::PARAM_SCALE, "scale", "..." },
{ afxXM_WaveBaseData::PARAM_SCALE_X, "scale.x", "..." },
{ afxXM_WaveBaseData::PARAM_SCALE_Y, "scale.y", "..." },
{ afxXM_WaveBaseData::PARAM_SCALE_Z, "scale.z", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR, "color", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_R, "color.red", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_G, "color.green", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_B, "color.blue", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_A, "color.alpha", "..." },
{ afxXM_WaveBaseData::PARAM_VIS, "vis", "..." },
{ afxXM_WaveBaseData::PARAM_POS, "position", "..." },
{ afxXM_WaveBaseData::PARAM_POS_X, "position.x", "..." },
{ afxXM_WaveBaseData::PARAM_POS_Y, "position.y", "..." },
{ afxXM_WaveBaseData::PARAM_POS_Z, "position.z", "..." },
{ afxXM_WaveBaseData::PARAM_ORI, "orientation", "..." },
{ afxXM_WaveBaseData::PARAM_POS2, "position2", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_X, "position2.x", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_Y, "position2.y", "..." },
{ afxXM_WaveBaseData::PARAM_POS2_Z, "position2.z", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_R, "color.r", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_G, "color.g", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_B, "color.b", "..." },
{ afxXM_WaveBaseData::PARAM_COLOR_A, "color.a", "..." },
{ afxXM_WaveBaseData::PARAM_VIS, "visibility", "..." },
EndImplementEnumType;
ImplementEnumType( afxXM_WaveOpType, "Possible wave operation types.\n" "@ingroup afxXM_WaveBase\n\n" )
{ afxXM_WaveBaseData::OP_ADD, "add", "..." },
{ afxXM_WaveBaseData::OP_MULTIPLY, "multiply", "..." },
{ afxXM_WaveBaseData::OP_REPLACE, "replace", "..." },
{ afxXM_WaveBaseData::OP_MULTIPLY, "mult", "..." },
EndImplementEnumType;
void afxXM_WaveBaseData::initPersistFields()
{
addField("waveform", TYPEID< afxXM_WaveBaseData::WaveFormType >(), Offset(waveform_type, afxXM_WaveBaseData),
"...");
addField("parameter", TYPEID< afxXM_WaveBaseData::WaveParamType >(), Offset(parameter, afxXM_WaveBaseData),
"...");
addField("op", TYPEID< afxXM_WaveBaseData::WaveOpType >(), Offset(op, afxXM_WaveBaseData),
"...");
addField("speed", TypeF32, Offset(speed, afxXM_WaveBaseData),
"waves per second");
addField("speedVariance", TypeF32, Offset(speed_vari, afxXM_WaveBaseData),
"...");
addField("acceleration", TypeF32, Offset(accel, afxXM_WaveBaseData),
"...");
addField("phaseShift", TypeF32, Offset(phase_shift, afxXM_WaveBaseData),
"...");
addField("dutyCycle", TypeF32, Offset(duty_cycle, afxXM_WaveBaseData),
"...");
addField("dutyShift", TypeF32, Offset(duty_shift, afxXM_WaveBaseData),
"...");
addField("offDutyT", TypeF32, Offset(off_duty_t, afxXM_WaveBaseData),
"...");
addField("wavesPerPulse", TypeByteRange2, Offset(waves_per_pulse, afxXM_WaveBaseData),
"...");
addField("wavesPerRest", TypeByteRange2, Offset(waves_per_rest, afxXM_WaveBaseData),
"...");
addField("restDuration", TypeF32, Offset(rest_dur, afxXM_WaveBaseData),
"...");
addField("restDurationVariance", TypeF32, Offset(rest_dur_vari, afxXM_WaveBaseData),
"...");
addField("axis", TypePoint3F, Offset(axis, afxXM_WaveBaseData),
"...");
addField("axisIsLocal", TypeBool, Offset(local_axis, afxXM_WaveBaseData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveBaseData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeInt(waveform_type, WAVEFORM_BITS);
stream->writeInt(parameter, PARAM_BITS);
stream->writeInt(op, OP_BITS);
stream->write(speed);
stream->write(speed_vari);
stream->write(accel);
stream->write(phase_shift);
stream->write(duty_cycle);
stream->write(duty_shift);
stream->write(off_duty_t);
stream->write(waves_per_pulse.low);
stream->write(waves_per_pulse.high);
stream->write(waves_per_rest.low);
stream->write(waves_per_rest.high);
stream->write(rest_dur);
stream->write(rest_dur_vari);
mathWrite(*stream, axis);
stream->writeFlag(local_axis);
}
void afxXM_WaveBaseData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
waveform_type = stream->readInt(WAVEFORM_BITS);
parameter = stream->readInt(PARAM_BITS);
op = stream->readInt(OP_BITS);
stream->read(&speed);
stream->read(&speed_vari);
stream->read(&accel);
stream->read(&phase_shift);
stream->read(&duty_cycle);
stream->read(&duty_shift);
stream->read(&off_duty_t);
stream->read(&waves_per_pulse.low);
stream->read(&waves_per_pulse.high);
stream->read(&waves_per_rest.low);
stream->read(&waves_per_rest.high);
stream->read(&rest_dur);
stream->read(&rest_dur_vari);
mathRead(*stream, &axis);
local_axis = stream->readFlag();
}
void afxXM_WaveBaseData::initParamInfo(U32 parameter, U32& parambit, S32& component)
{
switch (parameter)
{
case PARAM_POS:
parambit = POSITION;
component = -1;
break;
case PARAM_POS_X:
parambit = POSITION;
component = 0;
break;
case PARAM_POS_Y:
parambit = POSITION;
component = 1;
break;
case PARAM_POS_Z:
parambit = POSITION;
component = 2;
break;
case PARAM_ORI:
parambit = ORIENTATION;
component = -1;
break;
case PARAM_POS2:
parambit = POSITION2;
component = -1;
break;
case PARAM_POS2_X:
parambit = POSITION2;
component = 0;
break;
case PARAM_POS2_Y:
parambit = POSITION2;
component = 1;
break;
case PARAM_POS2_Z:
parambit = POSITION2;
component = 2;
break;
case PARAM_SCALE:
parambit = SCALE;
component = -1;
break;
case PARAM_SCALE_X:
parambit = SCALE;
component = 0;
break;
case PARAM_SCALE_Y:
parambit = SCALE;
component = 1;
break;
case PARAM_SCALE_Z:
parambit = SCALE;
component = 2;
break;
case PARAM_COLOR:
parambit = COLOR;
component = -1;
break;
case PARAM_COLOR_R:
parambit = COLOR;
component = 0;
break;
case PARAM_COLOR_G:
parambit = COLOR;
component = 1;
break;
case PARAM_COLOR_B:
parambit = COLOR;
component = 2;
break;
case PARAM_COLOR_A:
parambit = COLOR;
component = 3;
break;
case PARAM_VIS:
parambit = VISIBILITY;
component = -1;
break;
default:
parambit = 0;
component = -1;
break;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveRiderBaseData);
ConsoleDocClass( afxXM_WaveRiderBaseData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveRiderBaseData::afxXM_WaveRiderBaseData()
{
waveform_type = afxXM_WaveBaseData::WAVEFORM_NONE;
parameter = afxXM_WaveBaseData::PARAM_NONE;
op = afxXM_WaveBaseData::OP_ADD;
off_duty_t = 0.0f;
axis.zero();
local_axis = true;
}
afxXM_WaveRiderBaseData::afxXM_WaveRiderBaseData(const afxXM_WaveRiderBaseData& other, bool temp_clone) : afxXM_WeightedBaseData(other, temp_clone)
{
waveform_type = other.waveform_type;
parameter = other.parameter;
op = other.op;
off_duty_t = other.off_duty_t;
axis = other.axis;
local_axis = true;
}
void afxXM_WaveRiderBaseData::initPersistFields()
{
addField("waveform", TYPEID< afxXM_WaveBaseData::WaveFormType >(), Offset(waveform_type, afxXM_WaveRiderBaseData),
"...");
addField("parameter", TYPEID< afxXM_WaveBaseData::WaveParamType >(), Offset(parameter, afxXM_WaveRiderBaseData),
"...");
addField("op", TYPEID< afxXM_WaveBaseData::WaveOpType >(), Offset(op, afxXM_WaveRiderBaseData),
"...");
addField("offDutyT", TypeF32, Offset(off_duty_t, afxXM_WaveRiderBaseData),
"...");
addField("axis", TypePoint3F, Offset(axis, afxXM_WaveRiderBaseData),
"...");
addField("axisIsLocal", TypeBool, Offset(local_axis, afxXM_WaveRiderBaseData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveRiderBaseData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeInt(waveform_type, afxXM_WaveBaseData::WAVEFORM_BITS);
stream->writeInt(parameter, afxXM_WaveBaseData::PARAM_BITS);
stream->writeInt(op, afxXM_WaveBaseData::OP_BITS);
stream->write(off_duty_t);
mathWrite(*stream, axis);
stream->writeFlag(local_axis);
}
void afxXM_WaveRiderBaseData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
waveform_type = stream->readInt(afxXM_WaveBaseData::WAVEFORM_BITS);
parameter = stream->readInt(afxXM_WaveBaseData::PARAM_BITS);
op = stream->readInt(afxXM_WaveBaseData::OP_BITS);
stream->read(&off_duty_t);
mathRead(*stream, &axis);
local_axis = stream->readFlag();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// WAVEFORMS
F32 afxXM_WaveformSine::evaluate(F32 t)
{
t = (0.75f + t)*Float_2Pi;
return 0.5f*(1.0f + mSin(t));
}
F32 afxXM_WaveformSquare::evaluate(F32 t)
{
return (t < 0.25f || t >= 0.75) ? 0.0f : 1.0f;
}
F32 afxXM_WaveformTriangle::evaluate(F32 t)
{
return (t < 0.5f) ? 2.0f*t : 2.0f*(1.0f - t);
}
//~~~~~~~~~~~~~~~~~~~~//
afxXM_Waveform* afxXM_WaveBaseData::getWaveform(U32 waveform_type)
{
static afxXM_WaveformSine sine;
static afxXM_WaveformSquare square;
static afxXM_WaveformTriangle triangle;
static afxXM_WaveformSawtooth sawtooth;
static afxXM_WaveformNoise noise;
static afxXM_WaveformOne one;
switch (waveform_type)
{
case WAVEFORM_SINE:
return &sine;
case WAVEFORM_SQUARE:
return &square;
case WAVEFORM_TRIANGLE:
return &triangle;
case WAVEFORM_SAWTOOTH:
return &sawtooth;
case WAVEFORM_NOISE:
return &noise;
case WAVEFORM_ONE:
return &one;
default:
// error condition
return &sine;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
bool afxXM_WaveBase::last_was_pulsed = false;
bool afxXM_WaveBase::last_was_off_duty = true;
F32 afxXM_WaveBase::last_t = 0.0f;
F32 afxXM_WaveBase::last_wave_t = 0.0f;
afxXM_WaveBase::afxXM_WaveBase(afxXM_WaveBaseData* db, afxEffectWrapper* fxw, afxXM_WaveInterp* interp)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
interpolator = interp;
waveform = afxXM_WaveBaseData::getWaveform(db->waveform_type);
speed_is_randomized = !mIsZero(db->speed_vari);
speed = calc_initial_speed();
fixed_weight = db->hasFixedWeight();
is_resting = false;
cur_pulse_time = db->delay;
next_pulse_time = cur_pulse_time + ((F32)calc_new_wavesPerPulse())/speed;
interpolator->pulse();
last_was_pulsed = false;
last_was_off_duty = true;
last_t = 0.0f;
last_wave_t = 0.0f;
}
afxXM_WaveBase::~afxXM_WaveBase()
{
delete interpolator;
}
void afxXM_WaveBase::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
elapsed -= db->delay;
if (elapsed > next_pulse_time)
{
is_resting = !is_resting;
cur_pulse_time = next_pulse_time;
if (is_resting)
{
F32 rest_dt = ((F32)(calc_new_wavesPerRest())/speed) + calc_new_restDur();
if (rest_dt < 0.01)
is_resting = false;
else
next_pulse_time = cur_pulse_time + rest_dt;
}
if (!is_resting)
{
speed = calc_new_speed();
next_pulse_time = cur_pulse_time + ((F32)calc_new_wavesPerPulse())/speed;
interpolator->pulse();
last_was_pulsed = true;
}
}
if (is_resting)
{
last_was_off_duty = true;
interpolator->interpolate(db->off_duty_t, params);
return;
}
F32 n_waves = db->phase_shift + (elapsed - cur_pulse_time)*speed;
F32 wave_t = (n_waves - mFloor(n_waves))/db->duty_cycle;
// we are beyond the duty portion of the wave, use off_duty_t
if (wave_t > 1.0f)
{
last_was_off_duty = true;
interpolator->interpolate(db->off_duty_t, params);
return;
}
if (db->duty_shift > 0.0f)
{
wave_t += db->duty_shift;
if (wave_t > 1.0)
wave_t -= 1.0f;
}
last_was_off_duty = false;
last_wave_t = wave_t;
last_t = waveform->evaluate(wave_t);
if (fixed_weight)
{
interpolator->interpolate(last_t, params);
}
else
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 final_t = afxXM_WaveInterp::lerp(wt_factor, db->off_duty_t, last_t);
interpolator->interpolate(final_t, params);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
afxXM_WaveRiderBase::afxXM_WaveRiderBase(afxXM_WaveRiderBaseData* db, afxEffectWrapper* fxw, afxXM_WaveInterp* interp)
: afxXM_WeightedBase(db, fxw)
{
this->db = db;
interpolator = interp;
waveform = afxXM_WaveBaseData::getWaveform(db->waveform_type);
fixed_weight = db->hasFixedWeight();
interpolator->pulse();
}
afxXM_WaveRiderBase::~afxXM_WaveRiderBase()
{
delete interpolator;
}
void afxXM_WaveRiderBase::updateParams(F32 dt, F32 elapsed, afxXM_Params& params)
{
if (afxXM_WaveBase::last_was_pulsed)
interpolator->pulse();
if (afxXM_WaveBase::last_was_off_duty)
{
interpolator->interpolate(db->off_duty_t, params);
return;
}
F32 t;
if (db->waveform_type != afxXM_WaveBaseData::WAVEFORM_NONE)
t = waveform->evaluate(afxXM_WaveBase::last_wave_t);
else
t = afxXM_WaveBase::last_t;
if (fixed_weight)
interpolator->interpolate(t, params);
else
{
F32 wt_factor = calc_weight_factor(elapsed);
F32 final_t = afxXM_WaveInterp::lerp(wt_factor, db->off_duty_t, t);
interpolator->interpolate(final_t, params);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,314 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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_XFM_WAVE_BASE_H_
#define _AFX_XFM_WAVE_BASE_H_
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVEFORM
class afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t) = 0;
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveformSine : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t);
};
class afxXM_WaveformSquare : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t);
};
class afxXM_WaveformTriangle : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t);
};
class afxXM_WaveformSawtooth : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t) { return t; }
};
class afxXM_WaveformNoise : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t) { return gRandGen.randF(); };
};
class afxXM_WaveformOne : public afxXM_Waveform
{
public:
virtual F32 evaluate(F32 t) { return 1.0f; };
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE INTERPOLATOR
class afxXM_WaveInterp
{
public:
virtual void interpolate(F32 t, afxXM_Params& params)=0;
virtual void pulse()=0;
static F32 lerp(F32 t, F32 a, F32 b) { return a + t * (b - a); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE BASE DATABLOCK
class afxXM_WaveBaseData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
friend class afxXM_WaveRiderBaseData;
public:
enum WaveFormType
{
WAVEFORM_NONE = 0,
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_TRIANGLE,
WAVEFORM_SAWTOOTH,
WAVEFORM_NOISE,
WAVEFORM_ONE,
WAVEFORM_BITS = 3
};
enum WaveOpType
{
OP_ADD = 0,
OP_MULTIPLY,
OP_REPLACE,
OP_BITS = 2
};
enum WaveParamType
{
PARAM_NONE = 0,
PARAM_POS,
PARAM_POS_X,
PARAM_POS_Y,
PARAM_POS_Z,
PARAM_ORI,
PARAM_POS2,
PARAM_POS2_X,
PARAM_POS2_Y,
PARAM_POS2_Z,
PARAM_SCALE,
PARAM_SCALE_X,
PARAM_SCALE_Y,
PARAM_SCALE_Z,
PARAM_COLOR,
PARAM_COLOR_R,
PARAM_COLOR_G,
PARAM_COLOR_B,
PARAM_COLOR_A,
PARAM_VIS,
PARAM_BITS = 5,
};
U32 waveform_type;
U32 parameter;
U32 op;
F32 speed;
F32 speed_vari;
F32 accel;
F32 phase_shift;
F32 duty_cycle;
F32 duty_shift;
F32 off_duty_t;
ByteRange waves_per_pulse;
ByteRange waves_per_rest;
F32 rest_dur;
F32 rest_dur_vari;
Point3F axis;
bool local_axis;
public:
/*C*/ afxXM_WaveBaseData();
/*C*/ afxXM_WaveBaseData(const afxXM_WaveBaseData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
static void initParamInfo(U32 parameter, U32& parambit, S32& component);
static afxXM_Waveform* getWaveform(U32 waveform_type);
DECLARE_CONOBJECT(afxXM_WaveBaseData);
DECLARE_CATEGORY("AFX");
};
typedef afxXM_WaveBaseData::WaveFormType afxXM_WaveFormType;
DefineEnumType( afxXM_WaveFormType );
typedef afxXM_WaveBaseData::WaveOpType afxXM_WaveOpType;
DefineEnumType( afxXM_WaveOpType );
typedef afxXM_WaveBaseData::WaveParamType afxXM_WaveParamType;
DefineEnumType( afxXM_WaveParamType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE RIDER BASE DATABLOCK
class afxXM_WaveRiderBaseData : public afxXM_WeightedBaseData
{
typedef afxXM_WeightedBaseData Parent;
public:
U32 waveform_type;
F32 off_duty_t;
U32 parameter;
U32 op;
Point3F axis;
bool local_axis;
public:
/*C*/ afxXM_WaveRiderBaseData();
/*C*/ afxXM_WaveRiderBaseData(const afxXM_WaveRiderBaseData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
DECLARE_CONOBJECT(afxXM_WaveRiderBaseData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE BASE
class afxXM_WaveBase : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
friend class afxXM_WaveRiderBase;
protected:
static bool last_was_pulsed;
static bool last_was_off_duty;
static F32 last_t;
static F32 last_wave_t;
afxXM_WaveInterp* interpolator;
protected:
afxXM_Waveform* waveform;
afxXM_WaveBaseData* db;
F32 speed;
bool fixed_weight;
bool speed_is_randomized;
bool is_resting;
F32 cur_pulse_time;
F32 next_pulse_time;
F32 calc_initial_speed();
F32 calc_new_speed();
F32 calc_new_restDur();
S32 calc_new_wavesPerPulse();
S32 calc_new_wavesPerRest();
public:
/*C*/ afxXM_WaveBase(afxXM_WaveBaseData*, afxEffectWrapper*, afxXM_WaveInterp*);
/*D*/ ~afxXM_WaveBase();
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
inline F32 afxXM_WaveBase::calc_initial_speed()
{
return (!speed_is_randomized) ?
db->speed :
(db->speed + gRandGen.randF()*2.0f*db->speed_vari - db->speed_vari);
}
inline F32 afxXM_WaveBase::calc_new_speed()
{
return mClampF((!speed_is_randomized) ?
(speed + speed*db->accel) :
(db->speed + gRandGen.randF()*2.0f*db->speed_vari - db->speed_vari), 0.001f, 200.0f);
}
inline F32 afxXM_WaveBase::calc_new_restDur()
{
return db->rest_dur + gRandGen.randF()*2.0f*db->rest_dur_vari - db->rest_dur_vari;
}
inline S32 afxXM_WaveBase::calc_new_wavesPerPulse()
{
return (db->waves_per_pulse.getSpan() == 0) ?
db->waves_per_pulse.low :
gRandGen.randI(db->waves_per_pulse.low, db->waves_per_pulse.high);
}
inline S32 afxXM_WaveBase::calc_new_wavesPerRest()
{
return (db->waves_per_rest.getSpan() == 0) ?
db->waves_per_rest.low :
gRandGen.randI(db->waves_per_rest.low, db->waves_per_rest.high);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE RIDER BASE
class afxXM_WaveRiderBase : public afxXM_WeightedBase
{
typedef afxXM_WeightedBase Parent;
protected:
afxXM_WaveInterp* interpolator;
afxXM_WaveRiderBaseData* db;
afxXM_Waveform* waveform;
bool fixed_weight;
public:
/*C*/ afxXM_WaveRiderBase(afxXM_WaveRiderBaseData*, afxEffectWrapper*, afxXM_WaveInterp*);
/*D*/ ~afxXM_WaveRiderBase();
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_XFM_WAVE_BASE_H_

View file

@ -0,0 +1,388 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXM_WaveBase.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE COLOR INTERPOLATORS
class afxXM_WaveInterp_Color : public afxXM_WaveInterp
{
protected:
LinearColorF a_set, b_set;
LinearColorF a_var, b_var;
LinearColorF a, b;
bool sync_var;
public:
afxXM_WaveInterp_Color();
void set(LinearColorF& a, LinearColorF& b, LinearColorF& a_var, LinearColorF& b_var, bool sync_var);
virtual void interpolate(F32 t, afxXM_Params& params)=0;
virtual void pulse();
};
afxXM_WaveInterp_Color::afxXM_WaveInterp_Color()
{
a_set.set(0.0f, 0.0f, 0.0f, 0.0f);
b_set.set(1.0f, 1.0f, 1.0f, 1.0f);
a_var.set(0.0f, 0.0f, 0.0f, 0.0f);
b_var.set(0.0f, 0.0f, 0.0f, 0.0f);
sync_var = false;
a.set(0.0f, 0.0f, 0.0f, 0.0f);
b.set(1.0f, 1.0f, 1.0f, 1.0f);
}
void afxXM_WaveInterp_Color::set(LinearColorF& a, LinearColorF& b, LinearColorF& a_var, LinearColorF& b_var, bool sync_var)
{
a_set = a;
b_set = b;
this->a_var = a_var;
this->b_var = b_var;
this->sync_var = sync_var;
this->a = a;
this->b = b;
}
inline void afxXM_WaveInterp_Color::pulse()
{
LinearColorF temp_color;
F32 rand_t = gRandGen.randF()*2.0f;
temp_color.interpolate(-a_var, a_var, rand_t);
a = a_set + temp_color;
if (!sync_var)
rand_t = gRandGen.randF()*2.0f;
temp_color.interpolate(-b_var, b_var, rand_t);
b = b_set + temp_color;
}
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Color_Add : public afxXM_WaveInterp_Color
{
public:
virtual void interpolate(F32 t, afxXM_Params& params)
{
LinearColorF temp_color;
temp_color.interpolate(a, b, t);
params.color += temp_color;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Color_Mul : public afxXM_WaveInterp_Color
{
public:
virtual void interpolate(F32 t, afxXM_Params& params)
{
LinearColorF temp_color;
temp_color.interpolate(a, b, t);
params.color *= temp_color;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Color_Rep : public afxXM_WaveInterp_Color
{
public:
virtual void interpolate(F32 t, afxXM_Params& params)
{
params.color.interpolate(a, b, t);
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE SCALAR BASE DATABLOCK
class afxXM_WaveColorData_Common : public virtual afxXM_Defs
{
protected:
static afxXM_WaveInterp_Color* createInterp(U32 op, afxXM_BaseData*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
afxXM_WaveInterp_Color*
afxXM_WaveColorData_Common::createInterp(U32 op, afxXM_BaseData* db)
{
afxXM_WaveInterp_Color* interpolator = 0;
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Color_Add();
return 0;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Color_Mul();
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Color_Rep();
break;
}
if (!interpolator)
Con::errorf("%s::%s -- failed to allocate wave color interpolator.", db->getClassName(), db->getName());
return interpolator;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE COLOR DATABLOCK
class afxXM_WaveColorData : public afxXM_WaveBaseData, afxXM_WaveColorData_Common
{
typedef afxXM_WaveBaseData Parent;
public:
LinearColorF a, b;
LinearColorF a_var, b_var;
bool sync_var;
public:
/*C*/ afxXM_WaveColorData();
/*C*/ afxXM_WaveColorData(const afxXM_WaveColorData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_WaveColorData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveColorData);
ConsoleDocClass( afxXM_WaveColorData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveColorData::afxXM_WaveColorData()
{
a.set(0.0f, 0.0f, 0.0f, 0.0f);
b.set(1.0f, 1.0f, 1.0f, 1.0f);
a_var.set(0.0f, 0.0f, 0.0f, 0.0f);
b_var.set(0.0f, 0.0f, 0.0f, 0.0f);
sync_var = false;
}
afxXM_WaveColorData::afxXM_WaveColorData(const afxXM_WaveColorData& other, bool temp_clone) : afxXM_WaveBaseData(other, temp_clone)
{
a = other.a;
b = other.b;
a_var = other.a_var;
b_var = other.b_var;
sync_var = other.sync_var;
}
void afxXM_WaveColorData::initPersistFields()
{
addField("a", TypeColorF, Offset(a, afxXM_WaveColorData),
"...");
addField("b", TypeColorF, Offset(b, afxXM_WaveColorData),
"...");
addField("aVariance", TypeColorF, Offset(a_var, afxXM_WaveColorData),
"...");
addField("bVariance", TypeColorF, Offset(b_var, afxXM_WaveColorData),
"...");
addField("syncVariances", TypeBool, Offset(sync_var, afxXM_WaveColorData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveColorData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(a);
stream->write(b);
stream->write(a_var);
stream->write(b_var);
stream->writeFlag(sync_var);
}
void afxXM_WaveColorData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&a);
stream->read(&b);
stream->read(&a_var);
stream->read(&b_var);
sync_var = stream->readFlag();
}
afxXM_Base* afxXM_WaveColorData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_WaveColorData* dblock = this;
if (getSubstitutionCount() > 0)
{
dblock = new afxXM_WaveColorData(*this, true);
this->performSubstitutions(dblock, fx->getChoreographer(), fx->getGroupIndex());
}
afxXM_WaveInterp_Color* interp;
interp = createInterp(dblock->op, dblock);
if (!interp)
return 0;
interp->set(dblock->a, dblock->b, dblock->a_var, dblock->b_var, dblock->sync_var);
return new afxXM_WaveBase(dblock, fx, interp);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE RIDER COLOR DATABLOCK
class afxXM_WaveRiderColorData : public afxXM_WaveRiderBaseData, afxXM_WaveColorData_Common
{
typedef afxXM_WaveRiderBaseData Parent;
public:
LinearColorF a, b;
LinearColorF a_var, b_var;
bool sync_var;
public:
/*C*/ afxXM_WaveRiderColorData();
/*C*/ afxXM_WaveRiderColorData(const afxXM_WaveRiderColorData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_WaveRiderColorData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveRiderColorData);
ConsoleDocClass( afxXM_WaveRiderColorData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveRiderColorData::afxXM_WaveRiderColorData()
{
a.set(0.0f, 0.0f, 0.0f, 0.0f);
b.set(1.0f, 1.0f, 1.0f, 1.0f);
a_var.set(0.0f, 0.0f, 0.0f, 0.0f);
b_var.set(0.0f, 0.0f, 0.0f, 0.0f);
sync_var = false;
}
afxXM_WaveRiderColorData::afxXM_WaveRiderColorData(const afxXM_WaveRiderColorData& other, bool temp_clone) : afxXM_WaveRiderBaseData(other, temp_clone)
{
a = other.a;
b = other.b;
a_var = other.a_var;
b_var = other.b_var;
sync_var = other.sync_var;
}
void afxXM_WaveRiderColorData::initPersistFields()
{
addField("a", TypeColorF, Offset(a, afxXM_WaveRiderColorData),
"...");
addField("b", TypeColorF, Offset(b, afxXM_WaveRiderColorData),
"...");
addField("aVariance", TypeColorF, Offset(a_var, afxXM_WaveRiderColorData),
"...");
addField("bVariance", TypeColorF, Offset(b_var, afxXM_WaveRiderColorData),
"...");
addField("syncVariances", TypeBool, Offset(sync_var, afxXM_WaveRiderColorData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveRiderColorData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(a);
stream->write(b);
stream->write(a_var);
stream->write(b_var);
stream->writeFlag(sync_var);
}
void afxXM_WaveRiderColorData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&a);
stream->read(&b);
stream->read(&a_var);
stream->read(&b_var);
sync_var = stream->readFlag();
}
afxXM_Base* afxXM_WaveRiderColorData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_WaveRiderColorData* dblock = this;
if (getSubstitutionCount() > 0)
{
dblock = new afxXM_WaveRiderColorData(*this, true);
this->performSubstitutions(dblock, fx->getChoreographer(), fx->getGroupIndex());
}
afxXM_WaveInterp_Color* interp;
interp = createInterp(dblock->op, dblock);
if (!interp)
return 0;
interp->set(dblock->a, dblock->b, dblock->a_var, dblock->b_var, dblock->sync_var);
return new afxXM_WaveRiderBase(dblock, fx, interp);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,825 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/afxChoreographer.h"
#include "afx/xm/afxXM_WaveBase.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE SCALAR INTERPOLATORS
class afxXM_WaveInterp_Scalar : public afxXM_WaveInterp
{
protected:
F32 a_set, b_set;
F32 a_var, b_var;
F32 a, b;
bool sync_var;
public:
afxXM_WaveInterp_Scalar();
void set(F32 a, F32 b, F32 a_var, F32 b_var, bool sync_var);
virtual void interpolate(F32 t, afxXM_Params& params)=0;
virtual void pulse();
};
afxXM_WaveInterp_Scalar::afxXM_WaveInterp_Scalar()
{
a_set = 0.0f;
b_set = 1.0f;
a_var = 0.0f;
b_var = 0.0;
sync_var = false;
a = 0.0f;
b = 1.0f;
}
void afxXM_WaveInterp_Scalar::set(F32 a, F32 b, F32 a_var, F32 b_var, bool sync_var)
{
a_set = a;
b_set = b;
this->a_var = a_var;
this->b_var = b_var;
this->sync_var = sync_var;
this->a = a;
this->b = b;
}
inline void afxXM_WaveInterp_Scalar::pulse()
{
F32 rand_t = gRandGen.randF()*2.0f;
a = a_set + rand_t*a_var - a_var;
if (!sync_var)
rand_t = gRandGen.randF()*2.0f;
b = b_set + rand_t*b_var - b_var;
}
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Add : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_Add(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
*((F32*)(((char*)(&params)) + offset)) += lerp(t, a, b);
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Mul : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_Mul(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
*((F32*)(((char*)(&params)) + offset)) *= lerp(t, a, b);
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Rep : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_Rep(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
*((F32*)(((char*)(&params)) + offset)) = lerp(t, a, b);
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_PointAdd : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_PointAdd(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 scalar_at_t = lerp(t, a, b);
Point3F point_at_t(scalar_at_t, scalar_at_t, scalar_at_t);
*((Point3F*)(((char*)(&params)) + offset)) += point_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_PointMul : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_PointMul(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
*((Point3F*)(((char*)(&params)) + offset)) *= lerp(t, a, b);
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_PointRep : public afxXM_WaveInterp_Scalar
{
protected:
U32 offset;
public:
afxXM_WaveInterp_Scalar_PointRep(U32 o) : afxXM_WaveInterp_Scalar() { offset = o; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 scalar_at_t = lerp(t, a, b);
Point3F point_at_t(scalar_at_t, scalar_at_t, scalar_at_t);
*((Point3F*)(((char*)(&params)) + offset)) = point_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Axis_PointAdd : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_Axis_PointAdd(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F point_at_t = axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) += point_at_t;
}
};
class afxXM_WaveInterp_Scalar_LocalAxis_PointAdd : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_LocalAxis_PointAdd(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F local_axis(axis);
params.ori.mulV(local_axis);
Point3F point_at_t = local_axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) += point_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Axis_PointMul : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_Axis_PointMul(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F point_at_t = axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) *= point_at_t;
}
};
class afxXM_WaveInterp_Scalar_LocalAxis_PointMul : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_LocalAxis_PointMul(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F local_axis(axis);
params.ori.mulV(local_axis);
Point3F point_at_t = local_axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) *= point_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_Axis_PointRep : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_Axis_PointRep(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F point_at_t = axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) = point_at_t;
}
};
class afxXM_WaveInterp_Scalar_LocalAxis_PointRep : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
U32 offset;
public:
afxXM_WaveInterp_Scalar_LocalAxis_PointRep(U32 o, Point3F ax) : afxXM_WaveInterp_Scalar() { offset = o; axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
Point3F local_axis(axis);
params.ori.mulV(local_axis);
Point3F point_at_t = local_axis*lerp(t, a, b);
*((Point3F*)(((char*)(&params)) + offset)) = point_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_ColorAdd : public afxXM_WaveInterp_Scalar
{
public:
afxXM_WaveInterp_Scalar_ColorAdd() : afxXM_WaveInterp_Scalar() { }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 scalar_at_t = lerp(t, a, b);
LinearColorF color_at_t(scalar_at_t, scalar_at_t, scalar_at_t, scalar_at_t);
params.color += color_at_t;
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_ColorMul : public afxXM_WaveInterp_Scalar
{
public:
afxXM_WaveInterp_Scalar_ColorMul() : afxXM_WaveInterp_Scalar() { }
virtual void interpolate(F32 t, afxXM_Params& params)
{
params.color *= lerp(t, a, b);
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_ColorRep : public afxXM_WaveInterp_Scalar
{
public:
afxXM_WaveInterp_Scalar_ColorRep() : afxXM_WaveInterp_Scalar() { }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 scalar_at_t = lerp(t, a, b);
params.color.set(scalar_at_t, scalar_at_t, scalar_at_t, scalar_at_t);
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_OriMul : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
public:
afxXM_WaveInterp_Scalar_OriMul(Point3F& ax) : afxXM_WaveInterp_Scalar() { axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 theta = mDegToRad(lerp(t, a, b));
AngAxisF rot_aa(axis, theta);
MatrixF rot_xfm; rot_aa.setMatrix(&rot_xfm);
params.ori.mul(rot_xfm);
}
};
//~~~~~~~~~~~~~~~~~~~~//
class afxXM_WaveInterp_Scalar_OriRep : public afxXM_WaveInterp_Scalar
{
protected:
Point3F axis;
public:
afxXM_WaveInterp_Scalar_OriRep(Point3F& ax) : afxXM_WaveInterp_Scalar() { axis = ax; }
virtual void interpolate(F32 t, afxXM_Params& params)
{
F32 theta = mDegToRad(lerp(t, a, b));
AngAxisF rot_aa(axis, theta);
rot_aa.setMatrix(&params.ori);
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE SCALAR BASE DATABLOCK
class afxXM_WaveScalarData_Common : public virtual afxXM_Defs
{
static afxXM_WaveInterp_Scalar* alloc_interp(U32 param, S32 comp, U32 op, U32 off,
Point3F& axis, bool loc_axis, afxXM_BaseData*);
static bool needs_offset(U32 param, S32 component);
static bool needs_axis(U32 param, S32 component);
protected:
static afxXM_WaveInterp_Scalar* createInterp(U32 param, U32 op, Point3F axis, bool loc_axis,
afxXM_BaseData*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
bool afxXM_WaveScalarData_Common::needs_offset(U32 param, S32 component)
{
switch (param)
{
case ORIENTATION:
return false;
case POSITION:
case POSITION2:
case SCALE:
case VISIBILITY:
return true;
case COLOR:
return (component != -1);
}
return false;
}
bool afxXM_WaveScalarData_Common::needs_axis(U32 param, S32 component)
{
switch (param)
{
case ORIENTATION:
return true;
case POSITION:
case POSITION2:
case SCALE:
case COLOR:
case VISIBILITY:
return false;
}
return true;
}
afxXM_WaveInterp_Scalar*
afxXM_WaveScalarData_Common::alloc_interp(U32 param, S32 component, U32 op, U32 offset, Point3F& axis, bool loc_axis, afxXM_BaseData* db)
{
afxXM_WaveInterp_Scalar* interpolator = 0;
switch (param)
{
case ORIENTATION:
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
Con::errorf("%s::%s -- invalid orientation op.", db->getClassName(), db->getName());
return 0;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_OriMul(axis);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_OriRep(axis);
break;
}
break;
case POSITION:
case POSITION2:
case SCALE:
if (component == -1)
{
if (axis.isZero())
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_PointAdd(offset);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_PointMul(offset);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_PointRep(offset);
break;
}
}
else if (loc_axis)
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_LocalAxis_PointAdd(offset, axis);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_LocalAxis_PointMul(offset, axis);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_LocalAxis_PointRep(offset, axis);
break;
}
}
else
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_Axis_PointAdd(offset, axis);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_Axis_PointMul(offset, axis);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_Axis_PointRep(offset, axis);
break;
}
}
}
else
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_Add(offset);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_Mul(offset);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_Rep(offset);
break;
}
}
break;
case COLOR:
if (component == -1)
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_ColorAdd();
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_ColorMul();
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_ColorRep();
break;
}
}
else
{
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_Add(offset);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_Mul(offset);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_Rep(offset);
break;
}
}
break;
case VISIBILITY:
switch (op)
{
case afxXM_WaveBaseData::OP_ADD:
interpolator = new afxXM_WaveInterp_Scalar_Add(offset);
break;
case afxXM_WaveBaseData::OP_MULTIPLY:
interpolator = new afxXM_WaveInterp_Scalar_Mul(offset);
break;
case afxXM_WaveBaseData::OP_REPLACE:
interpolator = new afxXM_WaveInterp_Scalar_Rep(offset);
break;
}
}
if (!interpolator)
Con::errorf("%s::%s -- failed to allocate wave interpolator.", db->getClassName(), db->getName());
return interpolator;
}
afxXM_WaveInterp_Scalar*
afxXM_WaveScalarData_Common::createInterp(U32 parameter, U32 op, Point3F axis, bool loc_axis, afxXM_BaseData* db)
{
S32 component; U32 param_bit;
afxXM_WaveBaseData::initParamInfo(parameter, param_bit, component);
if (param_bit == 0)
{
Con::errorf("%s::%s -- unknown parameter specified.", db->getClassName(), db->getName());
return 0;
}
if (axis.isZero() && needs_axis(param_bit, component))
{
Con::errorf("%s::%s -- axis required.", db->getClassName(), db->getName());
return 0;
}
if (!axis.isZero())
axis.normalize();
U32 offset = afxXM_Params::BAD_OFFSET;
if (needs_offset(param_bit, component))
{
offset = afxXM_Params::getParameterOffset(param_bit, component);
if (offset == afxXM_Params::BAD_OFFSET)
{
Con::errorf("%s::%s -- bad component offset.", db->getClassName(), db->getName());
return 0;
}
}
return alloc_interp(param_bit, component, op, offset, axis, loc_axis, db);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE SCALAR DATABLOCK
class afxXM_WaveScalarData : public afxXM_WaveBaseData, afxXM_WaveScalarData_Common
{
typedef afxXM_WaveBaseData Parent;
public:
F32 a, b;
F32 a_var, b_var;
bool sync_var;
public:
/*C*/ afxXM_WaveScalarData();
/*C*/ afxXM_WaveScalarData(const afxXM_WaveScalarData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_WaveScalarData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveScalarData);
ConsoleDocClass( afxXM_WaveScalarData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveScalarData::afxXM_WaveScalarData()
{
a = 0.0f;
b = 1.0f;
a_var = 0.0f;
b_var = 0.0f;
sync_var = false;
}
afxXM_WaveScalarData::afxXM_WaveScalarData(const afxXM_WaveScalarData& other, bool temp_clone) : afxXM_WaveBaseData(other, temp_clone)
{
a = other.a;
b = other.b;
a_var = other.a_var;
b_var = other.b_var;
sync_var = other.sync_var;
}
void afxXM_WaveScalarData::initPersistFields()
{
addField("a", TypeF32, Offset(a, afxXM_WaveScalarData),
"...");
addField("b", TypeF32, Offset(b, afxXM_WaveScalarData),
"...");
addField("aVariance", TypeF32, Offset(a_var, afxXM_WaveScalarData),
"...");
addField("bVariance", TypeF32, Offset(b_var, afxXM_WaveScalarData),
"...");
addField("syncVariances", TypeBool, Offset(sync_var, afxXM_WaveScalarData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveScalarData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(a);
stream->write(b);
if (stream->writeFlag(a_var != 0.0f || b_var != 0.0f))
{
stream->write(a_var);
stream->write(b_var);
stream->writeFlag(sync_var);
}
}
void afxXM_WaveScalarData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&a);
stream->read(&b);
if (stream->readFlag())
{
stream->read(&a_var);
stream->read(&b_var);
sync_var = stream->readFlag();
}
else
{
a_var = b_var = 0.0f;
sync_var = false;
}
}
afxXM_Base* afxXM_WaveScalarData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_WaveScalarData* dblock = this;
if (getSubstitutionCount() > 0)
{
dblock = new afxXM_WaveScalarData(*this, true);
this->performSubstitutions(dblock, fx->getChoreographer(), fx->getGroupIndex());
}
afxXM_WaveInterp_Scalar* interp;
interp = createInterp(dblock->parameter, dblock->op, dblock->axis, dblock->local_axis, dblock);
if (!interp)
return 0;
interp->set(dblock->a, dblock->b, dblock->a_var, dblock->b_var, dblock->sync_var);
return new afxXM_WaveBase(dblock, fx, interp);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// WAVE RIDER SCALAR DATABLOCK
class afxXM_WaveRiderScalarData : public afxXM_WaveRiderBaseData, afxXM_WaveScalarData_Common
{
typedef afxXM_WaveRiderBaseData Parent;
public:
F32 a, b;
F32 a_var, b_var;
bool sync_var;
public:
/*C*/ afxXM_WaveRiderScalarData();
/*C*/ afxXM_WaveRiderScalarData(const afxXM_WaveRiderScalarData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
afxXM_Base* create(afxEffectWrapper* fx, bool on_server);
DECLARE_CONOBJECT(afxXM_WaveRiderScalarData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WaveRiderScalarData);
ConsoleDocClass( afxXM_WaveRiderScalarData,
"@brief An xmod datablock.\n\n"
"@ingroup afxXMods\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxXM_WaveRiderScalarData::afxXM_WaveRiderScalarData()
{
a = 0.0f;
b = 1.0f;
a_var = 0.0f;
b_var = 0.0f;
sync_var = false;
}
afxXM_WaveRiderScalarData::afxXM_WaveRiderScalarData(const afxXM_WaveRiderScalarData& other, bool temp_clone) : afxXM_WaveRiderBaseData(other, temp_clone)
{
a = other.a;
b = other.b;
a_var = other.a_var;
b_var = other.b_var;
sync_var = other.sync_var;
}
void afxXM_WaveRiderScalarData::initPersistFields()
{
addField("a", TypeF32, Offset(a, afxXM_WaveRiderScalarData),
"...");
addField("b", TypeF32, Offset(b, afxXM_WaveRiderScalarData),
"...");
addField("aVariance", TypeF32, Offset(a_var, afxXM_WaveRiderScalarData),
"...");
addField("bVariance", TypeF32, Offset(b_var, afxXM_WaveRiderScalarData),
"...");
addField("syncVariances", TypeBool, Offset(sync_var, afxXM_WaveRiderScalarData),
"...");
Parent::initPersistFields();
}
void afxXM_WaveRiderScalarData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(a);
stream->write(b);
if (stream->writeFlag(a_var != 0.0f || b_var != 0.0f))
{
stream->write(a_var);
stream->write(b_var);
stream->writeFlag(sync_var);
}
}
void afxXM_WaveRiderScalarData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&a);
stream->read(&b);
if (stream->readFlag())
{
stream->read(&a_var);
stream->read(&b_var);
sync_var = stream->readFlag();
}
else
{
a_var = b_var = 0.0f;
sync_var = false;
}
}
afxXM_Base* afxXM_WaveRiderScalarData::create(afxEffectWrapper* fx, bool on_server)
{
afxXM_WaveRiderScalarData* dblock = this;
if (getSubstitutionCount() > 0)
{
dblock = new afxXM_WaveRiderScalarData(*this, true);
this->performSubstitutions(dblock, fx->getChoreographer(), fx->getGroupIndex());
}
afxXM_WaveInterp_Scalar* interp;
interp = createInterp(dblock->parameter, dblock->op, dblock->axis, dblock->local_axis, dblock);
if (!interp)
return 0;
interp->set(dblock->a, dblock->b, dblock->a_var, dblock->b_var, dblock->sync_var);
return new afxXM_WaveRiderBase(dblock, fx, interp);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,333 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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/afxEffectWrapper.h"
#include "afx/util/afxEase.h"
#include "afx/xm/afxXfmMod.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
afxXM_Params::afxXM_Params()
{
pos.zero();
ori.identity();
scale.set(1.0f,1.0f,1.0f);
pos2.zero();
color.set(0.0f,0.0f,0.0f,0.0f);
vis = 0.0;
}
U32 afxXM_Params::getParameterOffset(U32 param, S32 component)
{
switch (param)
{
case POSITION:
switch (component)
{
case 0:
return Offset(pos.x, afxXM_Params);
case 1:
return Offset(pos.y, afxXM_Params);
case 2:
return Offset(pos.z, afxXM_Params);
default:
return Offset(pos, afxXM_Params);
}
break;
case ORIENTATION:
return Offset(ori, afxXM_Params);
case POSITION2:
switch (component)
{
case 0:
return Offset(pos2.x, afxXM_Params);
case 1:
return Offset(pos2.y, afxXM_Params);
case 2:
return Offset(pos2.z, afxXM_Params);
default:
return Offset(pos2, afxXM_Params);
}
break;
case SCALE:
switch (component)
{
case 0:
return Offset(scale.x, afxXM_Params);
case 1:
return Offset(scale.y, afxXM_Params);
case 2:
return Offset(scale.z, afxXM_Params);
default:
return Offset(scale, afxXM_Params);
}
break;
case COLOR:
switch (component)
{
case 0:
return Offset(color.red, afxXM_Params);
case 1:
return Offset(color.green, afxXM_Params);
case 2:
return Offset(color.blue, afxXM_Params);
case 3:
return Offset(color.alpha, afxXM_Params);
default:
return Offset(color, afxXM_Params);
}
break;
case VISIBILITY:
return Offset(vis, afxXM_Params);
}
return BAD_OFFSET;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// BASE CLASSES
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_BaseData);
afxXM_BaseData::afxXM_BaseData()
{
ignore_time_factor = false;
}
afxXM_BaseData::afxXM_BaseData(const afxXM_BaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
ignore_time_factor = other.ignore_time_factor;
}
void afxXM_BaseData::initPersistFields()
{
addField("ignoreTimeFactor", TypeBool, Offset(ignore_time_factor, afxXM_BaseData),
"...");
Parent::initPersistFields();
Con::setIntVariable("$afxXfmMod::POS", POSITION);
Con::setIntVariable("$afxXfmMod::ORI", ORIENTATION);
Con::setIntVariable("$afxXfmMod::POS2", POSITION2);
Con::setIntVariable("$afxXfmMod::SCALE", SCALE);
Con::setIntVariable("$afxXfmMod::ALL_BUT_SCALE", ALL_BUT_SCALE);
Con::setIntVariable("$afxXfmMod::ALL", ALL);
}
void afxXM_BaseData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(ignore_time_factor);
}
void afxXM_BaseData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&ignore_time_factor);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_Base::afxXM_Base(afxXM_BaseData* db, afxEffectWrapper* fxw)
{
fx_wrapper = fxw;
time_factor = (db->ignore_time_factor) ? 1.0f : fxw->getTimeFactor();
datablock = db;
}
afxXM_Base::~afxXM_Base()
{
if (datablock && datablock->isTempClone())
delete datablock;
datablock = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxXM_WeightedBaseData);
afxXM_WeightedBaseData::afxXM_WeightedBaseData()
{
delay = 0;
lifetime = afxEffectDefs::INFINITE_LIFETIME;
fade_in_time = 0;
fade_out_time = 0;
fadein_ease.set(0.0f, 1.0f);
fadeout_ease.set(0.0f, 1.0f);
life_bias = 1.0f;
}
afxXM_WeightedBaseData::afxXM_WeightedBaseData(const afxXM_WeightedBaseData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone)
{
delay = other.delay;
lifetime = other.lifetime;
fade_in_time = other.fade_in_time;
fade_out_time = other.fade_out_time;
fadein_ease = other.fadein_ease;
fadeout_ease = other.fadeout_ease;
life_bias = other.life_bias;
}
bool afxXM_WeightedBaseData::hasFixedWeight() const
{
return (delay == 0.0f && lifetime == afxEffectDefs::INFINITE_LIFETIME && fade_in_time == 0.0f && fade_out_time == 0.0f);
}
F32 afxXM_WeightedBaseData::getWeightFactor() const
{
return 1.0f;
}
void afxXM_WeightedBaseData::initPersistFields()
{
addField("delay", TypeF32, Offset(delay, afxXM_WeightedBaseData),
"...");
addField("lifetime", TypeF32, Offset(lifetime, afxXM_WeightedBaseData),
"...");
addField("fadeInTime", TypeF32, Offset(fade_in_time, afxXM_WeightedBaseData),
"...");
addField("fadeOutTime", TypeF32, Offset(fade_out_time, afxXM_WeightedBaseData),
"...");
addField("fadeInEase", TypePoint2F, Offset(fadein_ease, afxXM_WeightedBaseData),
"...");
addField("fadeOutEase", TypePoint2F, Offset(fadeout_ease, afxXM_WeightedBaseData),
"...");
addField("lifetimeBias", TypeF32, Offset(life_bias, afxXM_WeightedBaseData),
"...");
Parent::initPersistFields();
}
void afxXM_WeightedBaseData::packData(BitStream* stream)
{
Parent::packData(stream);
if (stream->writeFlag(!hasFixedWeight()))
{
stream->write(delay);
stream->write(lifetime);
stream->write(fade_in_time);
stream->write(fade_out_time);
if (stream->writeFlag(fadein_ease.x != 0.0f || fadein_ease.y != 1.0f))
{
stream->writeFloat(fadein_ease.x, 16);
stream->writeFloat(fadein_ease.y, 16);
}
if (stream->writeFlag(fadeout_ease.x != 0.0f || fadeout_ease.y != 1.0f))
{
stream->writeFloat(fadeout_ease.x, 16);
stream->writeFloat(fadeout_ease.y, 16);
}
stream->write(life_bias);
}
}
void afxXM_WeightedBaseData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
if (stream->readFlag()) // WEIGHTED?
{
stream->read(&delay);
stream->read(&lifetime);
stream->read(&fade_in_time);
stream->read(&fade_out_time);
if (stream->readFlag()) // FADE-IN EASED?
{
fadein_ease.x = stream->readFloat(16);
fadein_ease.y = stream->readFloat(16);
}
else
fadein_ease.set(0.0f, 1.0f);
if (stream->readFlag()) // FADE-OUT EASED?
{
fadeout_ease.x = stream->readFloat(16);
fadeout_ease.y = stream->readFloat(16);
}
else
fadeout_ease.set(0.0f, 1.0f);
stream->read(&life_bias);
}
else
{
delay = 0.0f;
lifetime = afxEffectDefs::INFINITE_LIFETIME;
fade_in_time = 0.0f;
fade_out_time = 0.0f;
fadein_ease.set(0.0f, 1.0f);
fadeout_ease.set(0.0f, 1.0f);
life_bias = 1.0f;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxXM_WeightedBase::afxXM_WeightedBase(afxXM_WeightedBaseData* db, afxEffectWrapper* fxw)
: afxXM_Base(db, fxw)
{
wt_fadein = db->fade_in_time*db->life_bias;
wt_fadeout = db->fade_out_time*db->life_bias;
wt_fadein_ease = db->fadein_ease;
wt_fadeout_ease = db->fadeout_ease;
wt_start_time = db->delay;
wt_full_time = wt_start_time + wt_fadein;
wt_fade_time = wt_start_time + db->lifetime*db->life_bias;
wt_done_time = wt_fade_time + wt_fadeout;
}
F32 afxXM_WeightedBase::calc_weight_factor(F32 elapsed)
{
if (elapsed < wt_start_time) // pre
return 0.0f;
else if (elapsed < wt_full_time) // fade-in
{
F32 t = (elapsed - wt_start_time)/wt_fadein;
return afxEase::t(t, wt_fadein_ease.x, wt_fadein_ease.y);
}
else if (elapsed < wt_fade_time) // full
return 1.0f;
else if (elapsed < wt_done_time) // fade-out
{
F32 t = (wt_done_time - elapsed)/wt_fadeout;
return afxEase::t(t, wt_fadeout_ease.x, wt_fadeout_ease.y);
}
else // post
return 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,176 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// 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_XFM_MOD_BASE_H_
#define _AFX_XFM_MOD_BASE_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "math/mPoint3.h"
#include "math/mMatrix.h"
#include "math/mMathFn.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// BASE CLASSES
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class BitStream;
class afxEffectWrapper;
class afxXM_Defs
{
public:
enum
{
POSITION = BIT(0),
ORIENTATION = BIT(1),
POSITION2 = BIT(2),
SCALE = BIT(3),
COLOR = BIT(4),
VISIBILITY = BIT(5),
ALL_BUT_SCALE = (POSITION | ORIENTATION | POSITION2),
ALL = (ALL_BUT_SCALE | SCALE),
};
};
struct afxXM_Params : public afxXM_Defs
{
Point3F pos;
MatrixF ori;
Point3F scale;
Point3F pos2;
LinearColorF color;
F32 vis;
enum { BAD_OFFSET = S32_MAX };
static U32 getParameterOffset(U32 param, S32 component=-1);
afxXM_Params();
};
class afxXM_Base;
class afxXM_BaseData : public GameBaseData, public afxXM_Defs
{
typedef GameBaseData Parent;
public:
bool ignore_time_factor;
public:
/*C*/ afxXM_BaseData();
/*C*/ afxXM_BaseData(const afxXM_BaseData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
virtual afxXM_Base* create(afxEffectWrapper* fx, bool on_server) { return 0; }
DECLARE_CONOBJECT(afxXM_BaseData);
DECLARE_CATEGORY("AFX");
};
class afxXM_Base : public afxXM_Defs
{
protected:
afxEffectWrapper* fx_wrapper;
afxXM_BaseData* datablock;
F32 time_factor;
public:
/*C*/ afxXM_Base(afxXM_BaseData*, afxEffectWrapper*);
virtual ~afxXM_Base();
virtual void start(F32 timestamp) { }
virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& p);
// old update form for backwards compatibility (deprecated)
virtual void update(F32 dt, F32 elapsed, Point3F& pos, MatrixF& ori, Point3F& pos2, Point3F& scale) { };
};
// New subclasses should define own updateParams() and should *not* call this thru Parent.
// This calls old form of update() for backwards compatibility.
inline void afxXM_Base::updateParams(F32 dt, F32 elapsed, afxXM_Params& p)
{
update(dt, elapsed, p.pos, p.ori, p.pos2, p.scale);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_WeightedBaseData : public afxXM_BaseData
{
typedef afxXM_BaseData Parent;
public:
F32 lifetime;
F32 delay;
F32 fade_in_time;
F32 fade_out_time;
Point2F fadein_ease;
Point2F fadeout_ease;
F32 life_bias;
public:
/*C*/ afxXM_WeightedBaseData();
/*C*/ afxXM_WeightedBaseData(const afxXM_WeightedBaseData&, bool = false);
bool hasFixedWeight() const;
F32 getWeightFactor() const;
void packData(BitStream* stream);
void unpackData(BitStream* stream);
static void initPersistFields();
DECLARE_CONOBJECT(afxXM_WeightedBaseData);
DECLARE_CATEGORY("AFX");
};
class afxXM_WeightedBase : public afxXM_Base
{
typedef afxXM_Base Parent;
protected:
F32 wt_fadein;
F32 wt_fadeout;
Point2F wt_fadein_ease;
Point2F wt_fadeout_ease;
F32 wt_start_time;
F32 wt_full_time;
F32 wt_fade_time;
F32 wt_done_time;
F32 calc_weight_factor(F32 elapsed);
public:
/*C*/ afxXM_WeightedBase(afxXM_WeightedBaseData*, afxEffectWrapper*);
virtual ~afxXM_WeightedBase() { }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_XFM_MOD_BASE_H_