afxEA_Zodiac.cpp
Engine/source/afx/ea/afxEA_Zodiac.cpp
Classes:
class
class
Public Defines
define
myOffset(field) (field, )
Detailed Description
Public Defines
myOffset(field) (field, )
1 2 3//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 4// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames 5// Copyright (C) 2015 Faust Logic, Inc. 6// 7// Permission is hereby granted, free of charge, to any person obtaining a copy 8// of this software and associated documentation files (the "Software"), to 9// deal in the Software without restriction, including without limitation the 10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11// sell copies of the Software, and to permit persons to whom the Software is 12// furnished to do so, subject to the following conditions: 13// 14// The above copyright notice and this permission notice shall be included in 15// all copies or substantial portions of the Software. 16// 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23// IN THE SOFTWARE. 24// 25//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 26 27#include <typeinfo> 28#include "afx/arcaneFX.h" 29 30#include "math/mathUtils.h" 31 32#include "afx/afxEffectDefs.h" 33#include "afx/afxEffectWrapper.h" 34#include "afx/afxChoreographer.h" 35#include "afx/afxResidueMgr.h" 36#include "afx/util/afxEase.h" 37#include "afx/ce/afxZodiacMgr.h" 38 39//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 40// afxEA_Zodiac 41 42class afxEA_Zodiac : public afxEffectWrapper 43{ 44 typedef afxEffectWrapper Parent; 45 46 afxZodiacData* zode_data; 47 Point3F zode_pos; 48 F32 zode_radius; 49 Point2F zode_vrange; 50 LinearColorF zode_color; 51 F32 zode_angle; 52 F32 zode_angle_offset; 53 54 F32 live_color_factor; 55 LinearColorF live_color; 56 bool became_residue; 57 bool do_altitude_bias; 58 F32 altitude_falloff_range; 59 60 F32 calc_facing_angle(); 61 F32 calc_terrain_alt_bias(); 62 F32 calc_interior_alt_bias(); 63 void do_runtime_substitutions(); 64 65public: 66 /*C*/ afxEA_Zodiac(); 67 /*C*/ ~afxEA_Zodiac(); 68 69 virtual void ea_set_datablock(SimDataBlock*); 70 virtual bool ea_start(); 71 virtual bool ea_update(F32 dt); 72 virtual void ea_finish(bool was_stopped); 73 74 virtual bool ea_is_enabled() { return true; } 75 76 virtual void getBaseColor(LinearColorF& color) { color = zode_data->color; } 77 78 static void initPersistFields(); 79 80 //DECLARE_CONOBJECT(afxEA_Zodiac); 81 DECLARE_CATEGORY("AFX"); 82}; 83 84//IMPLEMENT_CONOBJECT(afxEA_Zodiac); 85 86//~~~~~~~~~~~~~~~~~~~~// 87 88F32 afxEA_Zodiac::calc_facing_angle() 89{ 90 // get direction player is facing 91 VectorF shape_vec; 92 MatrixF shape_xfm; 93 94 afxConstraint* orient_constraint = getOrientConstraint(); 95 if (orient_constraint) 96 orient_constraint->getTransform(shape_xfm); 97 else 98 shape_xfm.identity(); 99 100 shape_xfm.getColumn(1, &shape_vec); 101 shape_vec.z = 0.0f; 102 shape_vec.normalize(); 103 104 F32 pitch, yaw; 105 MathUtils::getAnglesFromVector(shape_vec, yaw, pitch); 106 107 return mRadToDeg(yaw); 108} 109 110inline F32 afxEA_Zodiac::calc_terrain_alt_bias() 111{ 112 if (mTerrain_altitude >= zode_data->altitude_max) 113 return 0.0f; 114 return 1.0f - (mTerrain_altitude - zode_data->altitude_falloff)/altitude_falloff_range; 115} 116 117inline F32 afxEA_Zodiac::calc_interior_alt_bias() 118{ 119 if (mInterior_altitude >= zode_data->altitude_max) 120 return 0.0f; 121 return 1.0f - (mInterior_altitude - zode_data->altitude_falloff)/altitude_falloff_range; 122} 123 124afxEA_Zodiac::afxEA_Zodiac() 125{ 126 zode_data = 0; 127 zode_pos.zero(); 128 zode_radius = 1; 129 zode_vrange.set(1,1); 130 zode_color.set(1,1,1,1); 131 zode_angle = 0; 132 zode_angle_offset = 0; 133 live_color.set(1,1,1,1); 134 live_color_factor = 0.0f; 135 do_altitude_bias = false; 136 altitude_falloff_range = 0.0f; 137 became_residue = false; 138} 139 140afxEA_Zodiac::~afxEA_Zodiac() 141{ 142 if (!became_residue && zode_data && zode_data->isTempClone()) 143 delete zode_data; 144 zode_data = 0; 145} 146 147void afxEA_Zodiac::ea_set_datablock(SimDataBlock* db) 148{ 149 zode_data = dynamic_cast<afxZodiacData*>(db); 150 if (zode_data) 151 { 152 do_altitude_bias = (zode_data->altitude_max > 0.0f && (zode_data->altitude_shrinks || zode_data->altitude_fades)); 153 altitude_falloff_range = zode_data->altitude_max - zode_data->altitude_falloff; 154 } 155} 156 157bool afxEA_Zodiac::ea_start() 158{ 159 if (!zode_data) 160 { 161 Con::errorf("afxEA_Zodiac::ea_start() -- missing or incompatible datablock."); 162 return false; 163 } 164 165 do_runtime_substitutions(); 166 167 zode_angle_offset = calc_facing_angle(); 168 169 return true; 170} 171 172bool afxEA_Zodiac::ea_update(F32 dt) 173{ 174 if (!mIn_scope) 175 return true; 176 177 //~~~~~~~~~~~~~~~~~~~~// 178 // Zodiac Color 179 180 zode_color = mUpdated_color; 181 182 if (live_color_factor > 0.0) 183 { 184 zode_color.interpolate(zode_color, live_color, live_color_factor); 185 //Con::printf("LIVE-COLOR %g %g %g %g FACTOR is %g", 186 // live_color.red, live_color.green, live_color.blue, live_color.alpha, 187 // live_color_factor); 188 } 189 else 190 { 191 //Con::printf("LIVE-COLOR-FACTOR is ZERO"); 192 } 193 194 if (mDo_fades) 195 { 196 if (mFade_value < 0.01f) 197 return true; // too transparent 198 199 if (zode_data->blend_flags == afxZodiacDefs::BLEND_SUBTRACTIVE) 200 zode_color *= mFade_value * mLive_fade_factor; 201 else 202 zode_color.alpha *= mFade_value * mLive_fade_factor; 203 } 204 205 if (zode_color.alpha < 0.01f) 206 return true; 207 208 //~~~~~~~~~~~~~~~~~~~~// 209 // Zodiac 210 211 // scale and grow zode 212 zode_radius = zode_data->radius_xy*mUpdated_scale.x + mLife_elapsed *zode_data->growth_rate; 213 214 // zode is growing 215 if (mLife_elapsed < zode_data->grow_in_time) 216 { 217 F32 t = mLife_elapsed /zode_data->grow_in_time; 218 zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.2f, 0.8f); 219 } 220 // zode is shrinking 221 else if (mFull_lifetime - mLife_elapsed < zode_data->shrink_out_time) 222 { 223 F32 t = (mFull_lifetime - mLife_elapsed)/zode_data->shrink_out_time; 224 zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.0f, 0.9f); 225 } 226 227 zode_radius *= mLive_scale_factor; 228 229 if (zode_radius < 0.001f) 230 return true; // too small 231 232 zode_vrange = zode_data->vert_range; 233 if (zode_data->scale_vert_range) 234 { 235 F32 scale_factor = zode_radius/zode_data->radius_xy; 236 zode_vrange *= scale_factor; 237 } 238 239 //~~~~~~~~~~~~~~~~~~~~// 240 // Zodiac Position 241 242 zode_pos = mUpdated_pos; 243 244 //~~~~~~~~~~~~~~~~~~~~// 245 // Zodiac Rotation 246 247 if (zode_data->respect_ori_cons) 248 { 249 afxConstraint* orient_constraint = getOrientConstraint(); 250 if (orient_constraint) 251 { 252 VectorF shape_vec; 253 mUpdated_xfm.getColumn(1, &shape_vec); 254 shape_vec.z = 0.0f; 255 shape_vec.normalize(); 256 F32 pitch, yaw; 257 MathUtils::getAnglesFromVector(shape_vec, yaw, pitch); 258 zode_angle_offset = mRadToDeg(yaw); 259 } 260 } 261 262 zode_angle = zode_data->calcRotationAngle(mLife_elapsed, mDatablock->rate_factor/ mProp_time_factor); 263 zode_angle = mFmod(zode_angle + zode_angle_offset, 360.0f); 264 265 //~~~~~~~~~~~~~~~~~~~~// 266 // post zodiac 267 if ((zode_data->zflags & afxZodiacDefs::SHOW_ON_TERRAIN) != 0) 268 { 269 if (do_altitude_bias && mTerrain_altitude > zode_data->altitude_falloff) 270 { 271 F32 alt_bias = calc_terrain_alt_bias(); 272 if (alt_bias > 0.0f) 273 { 274 F32 alt_rad = zode_radius; 275 if (zode_data->altitude_shrinks) 276 alt_rad *= alt_bias; 277 LinearColorF alt_clr(zode_color.red, zode_color.green, zode_color.blue, zode_color.alpha); 278 if (zode_data->altitude_fades) 279 alt_clr.alpha *= alt_bias; 280 afxZodiacMgr::addTerrainZodiac(zode_pos, alt_rad, alt_clr, zode_angle, zode_data); 281 } 282 } 283 else 284 { 285 afxZodiacMgr::addTerrainZodiac(zode_pos, zode_radius, zode_color, zode_angle, zode_data); 286 } 287 } 288 289 if ((zode_data->zflags & afxZodiacDefs::SHOW_ON_INTERIORS) != 0) 290 { 291 if (do_altitude_bias && mInterior_altitude > zode_data->altitude_falloff) 292 { 293 F32 alt_bias = calc_interior_alt_bias(); 294 if (alt_bias > 0.0f) 295 { 296 F32 alt_rad = zode_radius; 297 if (zode_data->altitude_shrinks) 298 alt_rad *= alt_bias; 299 LinearColorF alt_clr(zode_color.red, zode_color.green, zode_color.blue, zode_color.alpha); 300 if (zode_data->altitude_fades) 301 alt_clr.alpha *= alt_bias; 302 afxZodiacMgr::addInteriorZodiac(zode_pos, alt_rad, zode_vrange, alt_clr, zode_angle, zode_data); 303 } 304 } 305 else 306 afxZodiacMgr::addInteriorZodiac(zode_pos, zode_radius, zode_vrange, zode_color, zode_angle, zode_data); 307 } 308 309 return true; 310} 311 312void afxEA_Zodiac::ea_finish(bool was_stopped) 313{ 314 if (mIn_scope && mEW_timing.residue_lifetime > 0) 315 { 316 if (mDo_fades) 317 { 318 if (mFade_value < 0.01f) 319 return; 320 zode_color.alpha *= mFade_value; 321 } 322 if ((zode_data->zflags & afxZodiacDefs::SHOW_ON_TERRAIN) != 0) 323 { 324 if (do_altitude_bias && mTerrain_altitude > zode_data->altitude_falloff) 325 { 326 F32 alt_bias = calc_terrain_alt_bias(); 327 if (alt_bias > 0.0f) 328 { 329 F32 alt_rad = zode_radius; 330 if (zode_data->altitude_shrinks) 331 alt_rad *= alt_bias; 332 LinearColorF alt_clr(zode_color.red, zode_color.green, zode_color.blue, zode_color.alpha); 333 if (zode_data->altitude_fades) 334 zode_color.alpha *= alt_bias; 335 became_residue = true; 336 afxResidueMgr::add_terrain_zodiac(mEW_timing.residue_lifetime, mEW_timing.residue_fadetime, zode_data, zode_pos, alt_rad, 337 alt_clr, zode_angle); 338 } 339 } 340 else 341 { 342 became_residue = true; 343 afxResidueMgr::add_terrain_zodiac(mEW_timing.residue_lifetime, mEW_timing.residue_fadetime, zode_data, zode_pos, zode_radius, 344 zode_color, zode_angle); 345 } 346 } 347 if ((zode_data->zflags & afxZodiacDefs::SHOW_ON_INTERIORS) != 0) 348 { 349 if (do_altitude_bias && mInterior_altitude > zode_data->altitude_falloff) 350 { 351 F32 alt_bias = calc_interior_alt_bias(); 352 if (alt_bias > 0.0f) 353 { 354 F32 alt_rad = zode_radius; 355 if (zode_data->altitude_shrinks) 356 alt_rad *= alt_bias; 357 LinearColorF alt_clr(zode_color.red, zode_color.green, zode_color.blue, zode_color.alpha); 358 if (zode_data->altitude_fades) 359 zode_color.alpha *= alt_bias; 360 361 afxZodiacData* temp_zode = zode_data; 362 if (became_residue) 363 temp_zode = new afxZodiacData(*zode_data, true); 364 became_residue = true; 365 afxResidueMgr::add_interior_zodiac(mEW_timing.residue_lifetime, mEW_timing.residue_fadetime, temp_zode, zode_pos, alt_rad, 366 zode_vrange, alt_clr, zode_angle); 367 } 368 369 } 370 else 371 { 372 afxZodiacData* temp_zode = zode_data; 373 if (became_residue) 374 temp_zode = new afxZodiacData(*zode_data, true); 375 became_residue = true; 376 afxResidueMgr::add_interior_zodiac(mEW_timing.residue_lifetime, mEW_timing.residue_fadetime, temp_zode, zode_pos, zode_radius, 377 zode_vrange, zode_color, zode_angle); 378 } 379 } 380 } 381} 382 383void afxEA_Zodiac::do_runtime_substitutions() 384{ 385 // only clone the datablock if there are substitutions 386 if (zode_data->getSubstitutionCount() > 0) 387 { 388 // clone the datablock and perform substitutions 389 afxZodiacData* orig_db = zode_data; 390 zode_data = new afxZodiacData(*orig_db, true); 391 orig_db->performSubstitutions(zode_data, mChoreographer, mGroup_index); 392 } 393} 394 395#undef myOffset 396#define myOffset(field) Offset(field, afxEA_Zodiac) 397 398void afxEA_Zodiac::initPersistFields() 399{ 400 addField("liveColor", TypeColorF, myOffset(live_color), 401 "..."); 402 addField("liveColorFactor", TypeF32, myOffset(live_color_factor), 403 "..."); 404 405 Parent::initPersistFields(); 406} 407 408//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 409 410class afxEA_ZodiacDesc : public afxEffectAdapterDesc, public afxEffectDefs 411{ 412 static afxEA_ZodiacDesc desc; 413 414public: 415 virtual bool testEffectType(const SimDataBlock*) const; 416 virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const; 417 virtual bool runsOnServer(const afxEffectWrapperData*) const { return false; } 418 virtual bool runsOnClient(const afxEffectWrapperData*) const { return true; } 419 420 virtual afxEffectWrapper* create() const { return new afxEA_Zodiac; } 421}; 422 423afxEA_ZodiacDesc afxEA_ZodiacDesc::desc; 424 425bool afxEA_ZodiacDesc::testEffectType(const SimDataBlock* db) const 426{ 427 return (typeid(afxZodiacData) == typeid(*db)); 428} 429 430bool afxEA_ZodiacDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const 431{ 432 return (timing.lifetime < 0); 433} 434 435//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 436