123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // 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/ce/afxZodiacMgr.h"
- #include "afx/ce/afxModel.h"
- #include "afx/afxResidueMgr.h"
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- int QSORT_CALLBACK afxResidueMgr::ResidueList::compare_residue(const void* p1, const void* p2)
- {
- const afxResidueMgr::Residue** pd1 = (const afxResidueMgr::Residue**)p1;
- const afxResidueMgr::Residue** pd2 = (const afxResidueMgr::Residue**)p2;
-
- return int(((char*)(*pd1)->data.simobject) - ((char*)(*pd2)->data.simobject));
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- inline void afxResidueMgr::ResidueList::swap_array_ptrs()
- {
- Vector<Residue*>* tmp = m_array;
- m_array = m_scratch_array;
- m_scratch_array = tmp;
- }
- void afxResidueMgr::ResidueList::free_residue(Residue* residue)
- {
- if (the_mgr == NULL)
- return;
- if (the_mgr->requires_delete_tracking(residue))
- the_mgr->disable_delete_tracking(residue);
- the_mgr->free_residue(residue);
- }
- afxResidueMgr::ResidueList::ResidueList()
- {
- VECTOR_SET_ASSOCIATION(m_array_a);
- VECTOR_SET_ASSOCIATION(m_array_b);
- m_array = &m_array_a;
- m_scratch_array = &m_array_b ;
- m_dirty = false;
- m_pending = -1;
- }
- afxResidueMgr::ResidueList::~ResidueList()
- {
- clear();
- }
- void afxResidueMgr::ResidueList::clear()
- {
- if (the_mgr)
- {
- for (S32 i = 0; i < m_array->size(); i++)
- {
- Residue* r = (*m_array)[i];
- the_mgr->free_residue(r);
- }
- }
- m_array_a.clear();
- m_array_b.clear();
- }
- void afxResidueMgr::ResidueList::sort()
- {
- dQsort(m_array->address(), m_array->size(), sizeof(Residue*), compare_residue);
- m_dirty = false;
- }
- void afxResidueMgr::ResidueList::fadeAndCull(U32 now)
- {
- for (S32 i = 0; i < m_array->size(); i++)
- {
- Residue* r = (*m_array)[i];
- // done
- if (now >= r->stop_time)
- {
- free_residue(r);
- }
- // fading
- else if (now >= r->fade_time)
- {
- r->fade = 1.0f - ((F32)(now - r->fade_time))/((F32)(r->stop_time - r->fade_time));
- m_scratch_array->push_back(r);
- }
- // opaque
- else
- {
- r->fade = 1.0f;
- m_scratch_array->push_back(r);
- }
- }
- m_array->clear();
- swap_array_ptrs();
- }
- // removes all residue with datablock matching obj
- void afxResidueMgr::ResidueList::stripMatchingObjects(SimObject* db, bool del_notify)
- {
- if (del_notify)
- {
- for (S32 i = 0; i < m_array->size(); i++)
- {
- Residue* r = (*m_array)[i];
- if (db == r->data.simobject && the_mgr != NULL)
- the_mgr->free_residue(r);
- else
- m_scratch_array->push_back(r);
- }
- }
- else
- {
- for (S32 i = 0; i < m_array->size(); i++)
- {
- Residue* r = (*m_array)[i];
- if (db == r->data.simobject)
- free_residue(r);
- else
- m_scratch_array->push_back(r);
- }
- }
- m_array->clear();
- swap_array_ptrs();
- }
- void afxResidueMgr::ResidueList::add(Residue* residue)
- {
- m_array->push_back(residue);
- m_dirty = true;
- }
- void afxResidueMgr::manage_residue(const Residue* r)
- {
- if (r == NULL || r->fade < 0.01f)
- return;
- if (r->type == ZODIAC)
- {
- LinearColorF zode_color = ColorI(r->params.zodiac.r, r->params.zodiac.g, r->params.zodiac.b, r->params.zodiac.a);
- afxZodiacData* zd = (afxZodiacData*) r->data.zodiac;
- if (zd->blend_flags == afxZodiacDefs::BLEND_SUBTRACTIVE)
- zode_color *= r->fade;
- else
- zode_color.alpha *= r->fade;
- Point3F zode_pos(r->params.zodiac.pos_x, r->params.zodiac.pos_y, r->params.zodiac.pos_z);
- Point2F zode_vrange(r->params.zodiac.vrange_dn, r->params.zodiac.vrange_dn);
- if (r->params.zodiac.on_terrain)
- {
- afxZodiacMgr::addTerrainZodiac(zode_pos, r->params.zodiac.rad, zode_color, r->params.zodiac.ang, zd);
- }
- else
- {
- afxZodiacMgr::addInteriorZodiac(zode_pos, r->params.zodiac.rad, zode_vrange, zode_color, r->params.zodiac.ang, zd);
- }
- }
- else if (r->type == MODEL)
- {
- r->data.model->setFadeAmount(r->fade);
- }
- }
- void afxResidueMgr::ResidueList::manage()
- {
- if (the_mgr == NULL)
- return;
- S32 n_residue = m_array->size();
- for (S32 x = 0; x < n_residue; x++)
- the_mgr->manage_residue((*m_array)[x]);
- }
- U32 afxResidueMgr::ResidueList::findPendingBestBump(U32 look_max)
- {
- U32 soonest = 1000*60*60*24;
- m_pending = -1;
- U32 n = m_array->size();
- for (U32 i = 0; i < n && i < look_max; i++)
- {
- Residue* r = (*m_array)[i];
- if (r->stop_time < soonest)
- {
- soonest = r->stop_time;
- m_pending = i;
- }
- }
- return soonest;
- }
- void afxResidueMgr::ResidueList::bumpPending()
- {
- if (m_pending >= 0 && m_pending < m_array->size())
- {
- Residue* r = (*m_array)[m_pending];
- m_array->erase(m_pending);
- free_residue(r);
- }
- m_pending = -1;
- }
- bool afxResidueMgr::requires_delete_tracking(Residue* r)
- {
- return (r->type == MODEL);
- }
- void afxResidueMgr::enable_delete_tracking(Residue* r)
- {
- deleteNotify(r->data.simobject);
- }
- void afxResidueMgr::disable_delete_tracking(Residue* r)
- {
- clearNotify(r->data.simobject);
- r->data.simobject->deleteObject();
- r->data.simobject = 0;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- afxResidueMgr* afxResidueMgr::the_mgr = NULL;
- U32 afxResidueMgr::m_max_residue_objs = 256;
- bool afxResidueMgr::enabled = true;
- IMPLEMENT_CONOBJECT(afxResidueMgr);
- ConsoleDocClass( afxResidueMgr,
- "@brief A class that manages certain AFX effects that can persist for long durations.\n\n"
- "A class that manages certain AFX effects that can persist much longer than the duration of choreographers.\n"
- "@ingroup AFX\n"
- );
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // free-list management
- afxResidueMgr::Residue* afxResidueMgr::alloc_free_pool_block()
- {
- // allocate new block for the free-list
- m_free_pool_blocks.push_back(new Residue[FREE_POOL_BLOCK_SIZE]);
-
- // link them onto the free-list
- Residue* new_block = m_free_pool_blocks.last();
- for (U32 i = 0; i < FREE_POOL_BLOCK_SIZE - 1; i++)
- new_block[i].next = &new_block[i + 1];
-
- // tail of free-list points to NULL
- new_block[FREE_POOL_BLOCK_SIZE - 1].next = NULL;
- return new_block;
- }
- afxResidueMgr::Residue* afxResidueMgr::alloc_residue()
- {
- // need new free-list-block if m_next_free is null
- if (!m_next_free)
- m_next_free = alloc_free_pool_block();
-
- // pop new residue from head of free-list
- Residue* residue = m_next_free;
- m_next_free = residue->next;
- residue->next = NULL;
- return residue;
- }
- void afxResidueMgr::free_residue(Residue* residue)
- {
- if (residue && residue->type == ZODIAC)
- {
- if (residue->data.zodiac && residue->data.zodiac->isTempClone())
- {
- delete residue->data.zodiac;
- residue->data.zodiac = 0;
- }
- }
- // push residue onto head of free-list
- residue->next = m_next_free;
- m_next_free = residue;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- void afxResidueMgr::deleteResidueObject(SimObject* obj, bool del_notify)
- {
- m_managed.stripMatchingObjects(obj, del_notify);
- }
- void afxResidueMgr::bump_residue()
- {
- if (m_managed.findPendingBestBump())
- m_managed.bumpPending();
- }
- void afxResidueMgr::add_residue(Residue* residue)
- {
- AssertFatal(residue != NULL, "residue pointer is NULL.");
- if (m_managed.size() >= m_max_residue_objs)
- bump_residue();
- m_managed.add(residue);
- manage_residue(residue);
- if (requires_delete_tracking(residue))
- enable_delete_tracking(residue);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- afxResidueMgr::afxResidueMgr()
- {
- mObjBox.minExtents.set(-1e7, -1e7, -1e7);
- mObjBox.maxExtents.set( 1e7, 1e7, 1e7);
- mWorldBox.minExtents.set(-1e7, -1e7, -1e7);
- mWorldBox.maxExtents.set( 1e7, 1e7, 1e7);
-
- m_next_free = NULL;
- VECTOR_SET_ASSOCIATION(m_free_pool_blocks);
- }
- afxResidueMgr::~afxResidueMgr()
- {
- cleanup();
- }
- void afxResidueMgr::cleanup()
- {
- m_managed.clear();
- m_next_free = NULL;
- for (S32 i = 0; i < m_free_pool_blocks.size(); i++)
- delete [] m_free_pool_blocks[i];
- m_free_pool_blocks.clear();
- }
- void afxResidueMgr::onDeleteNotify(SimObject* obj)
- {
- deleteResidueObject(obj, true);
- Parent::onDeleteNotify(obj);
- }
- void afxResidueMgr::residueAdvanceTime()
- {
- U32 now = Platform::getVirtualMilliseconds();
- m_managed.fadeAndCull(now);
- m_managed.sortIfDirty();
- m_managed.manage();
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
- // add ZODIAC residue
- void afxResidueMgr::add_interior_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
- F32 rad, const Point2F& vrange, const LinearColorF& col, F32 ang)
- {
- add_zodiac(dur, fade_dur, zode, pos, rad, vrange, col, ang, false);
- }
- void afxResidueMgr::add_terrain_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
- F32 rad, const LinearColorF& col, F32 ang)
- {
- static Point2F vrange(0.0, 0.0);
- add_zodiac(dur, fade_dur, zode, pos, rad, vrange, col, ang, true);
- }
- void afxResidueMgr::add_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
- F32 rad, const Point2F& vrange, const LinearColorF& col, F32 ang, bool on_terrain)
- {
- if (m_max_residue_objs == 0 || dur <= 0 || the_mgr == NULL)
- return;
- ColorI col_i = LinearColorF(col).toColorI();
- U32 now = Platform::getVirtualMilliseconds();
- Residue* residue = the_mgr->alloc_residue();
- //
- residue->type = ZODIAC;
- residue->data.zodiac = zode;
- residue->fade_time = now + (U32)(dur*1000);
- residue->stop_time = residue->fade_time + (U32)(fade_dur*1000);
- residue->fade = 1.0f;
- //
- residue->params.zodiac.pos_x = pos.x;
- residue->params.zodiac.pos_y = pos.y;
- residue->params.zodiac.pos_z = pos.z;
- residue->params.zodiac.rad = rad;
- residue->params.zodiac.vrange_dn = vrange.x;
- residue->params.zodiac.vrange_up = vrange.y;
- residue->params.zodiac.r = col_i.red;
- residue->params.zodiac.g = col_i.green;
- residue->params.zodiac.b = col_i.blue;
- residue->params.zodiac.a = col_i.alpha;
- residue->params.zodiac.ang = ang;
- residue->params.zodiac.on_terrain = on_terrain;
- //
- residue->next = 0;
-
- the_mgr->add_residue(residue);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
- // add MODEL residue
- void afxResidueMgr::add(F32 dur, F32 fade_dur, afxModel* model)
- {
- if (m_max_residue_objs == 0 || dur <= 0 || the_mgr == NULL)
- return;
- U32 now = Platform::getVirtualMilliseconds();
-
- Residue* residue = the_mgr->alloc_residue();
- //
- residue->type = MODEL;
- residue->data.model = model;
- residue->fade_time = now + (U32)(dur*1000);
- residue->stop_time = residue->fade_time + (U32)(fade_dur*1000);
- residue->fade = 1.0f;
- //
- residue->next = 0;
- the_mgr->add_residue(residue);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|