123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777 |
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
- // Copyright (C) 2015 Faust Logic, Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- #include "afx/arcaneFX.h"
- #include "T3D/objectTypes.h"
- #include "T3D/gameBase/gameProcess.h"
- #include "core/resourceManager.h"
- #include "sim/netConnection.h"
- #include "scene/sceneRenderState.h"
- #include "scene/sceneManager.h"
- #include "ts/tsShapeInstance.h"
- #include "ts/tsMaterialList.h"
- #include "afx/ce/afxModel.h"
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // afxModelData
- IMPLEMENT_CO_DATABLOCK_V1(afxModelData);
-
- ConsoleDocClass( afxModelData,
- "@brief A datablock that specifies a Model effect.\n\n"
- "A Model effect is a lightweight client-only geometry object useful for effect-driven props."
- "\n\n"
- "@ingroup afxEffects\n"
- "@ingroup AFX\n"
- "@ingroup Datablocks\n"
- );
- afxModelData::afxModelData()
- {
- INIT_ASSET(Shape);
- sequence = ST_NULLSTRING;
- seq_rate = 1.0f;
- seq_offset = 0.0f;
- alpha_mult = 1.0f;
- use_vertex_alpha = false;
- force_on_material_flags = 0;
- force_off_material_flags = 0;
- texture_filtering = true;
- fog_mult = 1.0f;
- remap_txr_tags = ST_NULLSTRING;
- remap_buffer = 0;
- overrideLightingOptions = false;
- receiveSunLight = true;
- receiveLMLighting = true;
- useAdaptiveSelfIllumination = false;
- useCustomAmbientLighting = false;
- customAmbientForSelfIllumination = false;
- customAmbientLighting = LinearColorF(0.0f, 0.0f, 0.0f);
- shadowEnable = false;
- shadowSize = 128;
- shadowMaxVisibleDistance = 80.0f;
- shadowProjectionDistance = 10.0f;
- shadowSphereAdjust = 1.0;
- }
- afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone)
- {
- CLONE_ASSET(Shape);
- sequence = other.sequence;
- seq_rate = other.seq_rate;
- seq_offset = other.seq_offset;
- alpha_mult = other.alpha_mult;
- use_vertex_alpha = other.use_vertex_alpha;
- force_on_material_flags = other.force_on_material_flags;
- force_off_material_flags = other.force_off_material_flags;
- texture_filtering = other.texture_filtering;
- fog_mult = other.fog_mult;
- remap_txr_tags = other.remap_txr_tags;
- remap_buffer = other.remap_buffer;
- overrideLightingOptions = other.overrideLightingOptions;
- receiveSunLight = other.receiveSunLight;
- receiveLMLighting = other.receiveLMLighting;
- useAdaptiveSelfIllumination = other.useAdaptiveSelfIllumination;
- useCustomAmbientLighting = other.useCustomAmbientLighting;
- customAmbientForSelfIllumination = other.customAmbientForSelfIllumination;
- customAmbientLighting = other.customAmbientLighting;
- shadowEnable = other.shadowEnable;
- shadowSize = other.shadowSize;
- shadowMaxVisibleDistance = other.shadowMaxVisibleDistance;
- shadowProjectionDistance = other.shadowProjectionDistance;
- shadowSphereAdjust = other.shadowSphereAdjust;
- }
- afxModelData::~afxModelData()
- {
- if (remap_buffer)
- dFree(remap_buffer);
- }
- bool afxModelData::preload(bool server, String &errorStr)
- {
- if (Parent::preload(server, errorStr) == false)
- return false;
-
- // don't need to do this stuff on the server
- if (server)
- return true;
-
- if (mShapeAsset.notNull())
- {
- if (!mShape)
- {
- errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", mShapeAssetId);
- return false;
- }
- // just parse up the string and collect the remappings in txr_tag_remappings.
- if (remap_txr_tags != ST_NULLSTRING)
- {
- txr_tag_remappings.clear();
- if (remap_buffer)
- dFree(remap_buffer);
- remap_buffer = dStrdup(remap_txr_tags);
- char* remap_token = dStrtok(remap_buffer, " \t");
- while (remap_token != NULL)
- {
- char* colon = dStrchr(remap_token, ':');
- if (colon)
- {
- *colon = '\0';
- txr_tag_remappings.increment();
- txr_tag_remappings.last().old_tag = remap_token;
- txr_tag_remappings.last().new_tag = colon+1;
- }
- remap_token = dStrtok(NULL, " \t");
- }
- }
- // this little hack messes things up when remapping texture tags
- if (txr_tag_remappings.size() == 0)
- {
- // this little hack forces the textures to preload
- TSShapeInstance* pDummy = new TSShapeInstance(mShape);
- delete pDummy;
- }
- }
- return true;
- }
- #define myOffset(field) Offset(field, afxModelData)
- void afxModelData::initPersistFields()
- {
- INITPERSISTFIELD_SHAPEASSET(Shape, afxModelData, "The name of a .dts format file to use for the model.");
- addField("sequence", TypeString, myOffset(sequence),
- "The name of an animation sequence to play in the model.");
- addField("sequenceRate", TypeF32, myOffset(seq_rate),
- "The rate of playback for the sequence.");
- addField("sequenceOffset", TypeF32, myOffset(seq_offset),
- "An offset in seconds indicating a starting point for the animation sequence "
- "specified by the sequence field. A rate of 1.0 (rather than sequenceRate) is used "
- "to convert from seconds to the thread offset.");
- addField("alphaMult", TypeF32, myOffset(alpha_mult),
- "An alpha multiplier used to set maximum opacity of the model.");
- addField("fogMult", TypeF32, myOffset(fog_mult),
- "");
- addField("remapTextureTags", TypeString, myOffset(remap_txr_tags),
- "Rename one or more texture tags in the model. Texture tags are what link a "
- "model's textures to materials.\n"
- "Field should be a string containing space-separated remapping tokens. A remapping "
- "token is two names separated by a colon, ':'. The first name should be a texture-tag "
- "that exists in the model, while the second is a new name to replace it. The string "
- "can have any number of remapping tokens as long as the total string length does not "
- "exceed 255.");
- addField("shadowEnable", TypeBool, myOffset(shadowEnable),
- "Sets whether the model casts a shadow.");
- addField("useVertexAlpha", TypeBool, myOffset(use_vertex_alpha),
- "deprecated");
- addField("forceOnMaterialFlags", TypeS32, myOffset(force_on_material_flags),
- "deprecated");
- addField("forceOffMaterialFlags", TypeS32, myOffset(force_off_material_flags),
- "deprecated");
- addField("textureFiltering", TypeBool, myOffset(texture_filtering),
- "deprecated");
- addField("overrideLightingOptions", TypeBool, myOffset(overrideLightingOptions),
- "deprecated");
- addField("receiveSunLight", TypeBool, myOffset(receiveSunLight),
- "");
- addField("receiveLMLighting", TypeBool, myOffset(receiveLMLighting),
- "deprecated");
- addField("useAdaptiveSelfIllumination", TypeBool, myOffset(useAdaptiveSelfIllumination),
- "deprecated");
- addField("useCustomAmbientLighting", TypeBool, myOffset(useCustomAmbientLighting),
- "deprecated");
- addField("customAmbientSelfIllumination", TypeBool, myOffset(customAmbientForSelfIllumination),
- "deprecated");
- addField("customAmbientLighting", TypeColorF, myOffset(customAmbientLighting),
- "deprecated");
- addField("shadowSize", TypeS32, myOffset(shadowSize),
- "deprecated");
- addField("shadowMaxVisibleDistance", TypeF32, myOffset(shadowMaxVisibleDistance),
- "deprecated");
- addField("shadowProjectionDistance", TypeF32, myOffset(shadowProjectionDistance),
- "deprecated");
- addField("shadowSphereAdjust", TypeF32, myOffset(shadowSphereAdjust),
- "deprecated");
- Parent::initPersistFields();
- // Material Flags
- Con::setIntVariable("$MaterialFlags::S_Wrap", TSMaterialList::S_Wrap);
- Con::setIntVariable("$MaterialFlags::T_Wrap", TSMaterialList::T_Wrap);
- Con::setIntVariable("$MaterialFlags::Translucent", TSMaterialList::Translucent);
- Con::setIntVariable("$MaterialFlags::Additive", TSMaterialList::Additive);
- Con::setIntVariable("$MaterialFlags::Subtractive", TSMaterialList::Subtractive);
- Con::setIntVariable("$MaterialFlags::SelfIlluminating", TSMaterialList::SelfIlluminating);
- Con::setIntVariable("$MaterialFlags::NeverEnvMap", TSMaterialList::NeverEnvMap);
- Con::setIntVariable("$MaterialFlags::NoMipMap", TSMaterialList::NoMipMap);
- Con::setIntVariable("$MaterialFlags::MipMap_ZeroBorder", TSMaterialList::MipMap_ZeroBorder);
- Con::setIntVariable("$MaterialFlags::AuxiliaryMap", TSMaterialList::AuxiliaryMap);
- #if defined(AFX_CAP_AFXMODEL_TYPE)
- Con::setIntVariable("$TypeMasks::afxModelObjectType", afxModelObjectType);
- #endif
- }
- void afxModelData::packData(BitStream* stream)
- {
- Parent::packData(stream);
- PACKDATA_ASSET(Shape);
- stream->writeString(sequence);
- stream->write(seq_rate);
- stream->write(seq_offset);
- stream->write(alpha_mult);
- stream->write(use_vertex_alpha);
- stream->write(force_on_material_flags);
- stream->write(force_off_material_flags);
- stream->writeFlag(texture_filtering);
- stream->write(fog_mult);
- stream->writeString(remap_txr_tags);
- stream->writeFlag(overrideLightingOptions);
- stream->writeFlag(receiveSunLight);
- stream->writeFlag(useAdaptiveSelfIllumination);
- stream->writeFlag(useCustomAmbientLighting);
- stream->writeFlag(customAmbientForSelfIllumination);
- stream->write(customAmbientLighting);
- stream->writeFlag(receiveLMLighting);
- stream->writeFlag(shadowEnable);
- stream->write(shadowSize);
- stream->write(shadowMaxVisibleDistance);
- stream->write(shadowProjectionDistance);
- stream->write(shadowSphereAdjust);
- }
- void afxModelData::unpackData(BitStream* stream)
- {
- Parent::unpackData(stream);
- UNPACKDATA_ASSET(Shape);
- sequence = stream->readSTString();
- stream->read(&seq_rate);
- stream->read(&seq_offset);
- stream->read(&alpha_mult);
- stream->read(&use_vertex_alpha);
- stream->read(&force_on_material_flags);
- stream->read(&force_off_material_flags);
- texture_filtering = stream->readFlag();
- stream->read(&fog_mult);
- remap_txr_tags = stream->readSTString();
- overrideLightingOptions = stream->readFlag();
- receiveSunLight = stream->readFlag();
- useAdaptiveSelfIllumination = stream->readFlag();
- useCustomAmbientLighting = stream->readFlag();
- customAmbientForSelfIllumination = stream->readFlag();
- stream->read(&customAmbientLighting);
- receiveLMLighting = stream->readFlag();
- shadowEnable = stream->readFlag();
- stream->read(&shadowSize);
- stream->read(&shadowMaxVisibleDistance);
- stream->read(&shadowProjectionDistance);
- stream->read(&shadowSphereAdjust);
- }
- void afxModelData::onPerformSubstitutions()
- {
- if (mShapeAssetId != StringTable->EmptyString())
- {
- mShapeAsset = mShapeAssetId;
- if (mShapeAsset.notNull())
- {
- mShape = mShapeAsset->getShapeResource();
- }
- if (!mShape)
- {
- Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", mShapeAssetId);
- return;
- }
- // REMAP-TEXTURE-TAGS ISSUES?
- }
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // afxModel
- IMPLEMENT_CO_NETOBJECT_V1(afxModel);
- ConsoleDocClass( afxModel,
- "@brief A Model effect as defined by an afxModelData datablock.\n\n"
- "A Model effect is a lightweight client-only geometry object useful for effect-driven "
- "props.\n"
- "@ingroup afxEffects\n"
- "@ingroup AFX\n"
- );
- afxModel::afxModel()
- {
- mTypeMask |= DynamicShapeObjectType;
- #if defined(AFX_CAP_AFXMODEL_TYPE)
- mTypeMask |= afxModelObjectType;
- #endif
- shape_inst = 0;
- main_seq_thread = 0;
- main_seq_id = -1;
- seq_rate_factor = 1.0f;
- last_anim_tag = 0;
- seq_animates_vis = false;
- fade_amt = 1.0f;
- is_visible = true;
- sort_priority = 0;
- mDataBlock = NULL;
- mNetFlags.set( IsGhost );
- }
- afxModel::~afxModel()
- {
- delete shape_inst;
- }
- void afxModel::setSequenceRateFactor(F32 factor)
- {
- seq_rate_factor = factor;
- if (shape_inst != NULL && main_seq_thread != NULL)
- shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
- bool afxModel::onNewDataBlock(GameBaseData* dptr, bool reload)
- {
- mDataBlock = dynamic_cast<afxModelData*>(dptr);
- if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
- return false;
- return true;
- }
- bool afxModel::onAdd()
- {
- // first check if we have a server connection, if we don't then this is on the server
- // and we should exit, then check if the parent fails to add the object
- NetConnection* conn = NetConnection::getConnectionToServer();
- if (!conn || !Parent::onAdd())
- return false;
- // setup our bounding box
- if (mDataBlock->mShape)
- mObjBox = mDataBlock->mShape->mBounds;
- else
- mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
- // setup the shape instance and sequence
- if (mDataBlock->mShape)
- {
- if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0)
- {
- // temporarily substitute material tags with alternates
- TSMaterialList* mat_list = mDataBlock->mShape->materialList;
- if (mat_list)
- {
- for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
- {
- afxModelData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
- Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
- for (S32 j = 0; j < mat_names.size(); j++)
- {
- if (mat_names[j].compare(remap->old_tag, dStrlen(remap->old_tag), String::NoCase) == 0)
- {
- //Con::printf("REMAP TEXTURE TAG [%s] TO [%s]", remap->old_tag, remap->new_tag);
- mat_names[j] = String(remap->new_tag);
- mat_names[j].insert(0,'#');
- break;
- }
- }
- }
- }
- }
- shape_inst = new TSShapeInstance(mDataBlock->mShape);
- if (true) // isClientObject())
- {
- shape_inst->cloneMaterialList();
- // restore the material tags to original form
- if (mDataBlock->txr_tag_remappings.size() > 0)
- {
- TSMaterialList* mat_list = mDataBlock->mShape->materialList;
- if (mat_list)
- {
- for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
- {
- afxModelData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
- Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
- for (S32 j = 0; j < mat_names.size(); j++)
- {
- if (mat_names[j].compare(remap->new_tag, dStrlen(remap->new_tag)) == 0)
- {
- //Con::printf("UNREMAP TEXTURE TAG [%s] TO [%s]", remap->new_tag, remap->old_tag);
- mat_names[j] = String(remap->old_tag);
- break;
- }
- }
- }
- }
- }
- }
- if (mDataBlock->sequence == ST_NULLSTRING)
- {
- main_seq_thread = 0;
- main_seq_id = -1;
- }
- else
- {
- // here we start the default animation sequence
- TSShape* shape = shape_inst->getShape();
- main_seq_id = shape->findSequence(mDataBlock->sequence);
- if (main_seq_id != -1)
- {
- main_seq_thread = shape_inst->addThread();
-
- F32 seq_pos = 0.0f;
- if (mDataBlock->seq_offset > 0.0f && mDataBlock->seq_offset < shape_inst->getDuration(main_seq_thread))
- seq_pos = mDataBlock->seq_offset / shape_inst->getDuration(main_seq_thread);
- shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
- shape_inst->setSequence(main_seq_thread, main_seq_id, seq_pos);
- seq_animates_vis = shape->sequences[main_seq_id].visMatters.testAll();
- }
- }
- // deal with material changes
- if (shape_inst && (mDataBlock->force_on_material_flags | mDataBlock->force_off_material_flags))
- {
- shape_inst->cloneMaterialList();
- TSMaterialList* mats = shape_inst->getMaterialList();
- if (mDataBlock->force_on_material_flags != 0)
- {
- for (U32 i = 0; i < mats->size(); i++)
- mats->setFlags(i, mats->getFlags(i) | mDataBlock->force_on_material_flags);
- }
- if (mDataBlock->force_off_material_flags != 0)
- {
- for (U32 i = 0; i < mats->size(); i++)
- mats->setFlags(i, mats->getFlags(i) & ~mDataBlock->force_off_material_flags);
- }
- }
- }
- resetWorldBox();
- if (mDataBlock->mShape)
- {
- // Scan out the collision hulls...
- static const String sCollisionStr( "collision-" );
- for (U32 i = 0; i < mDataBlock->mShape->details.size(); i++)
- {
- const String &name = mDataBlock->mShape->names[mDataBlock->mShape->details[i].nameIndex];
- if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0)
- {
- mCollisionDetails.push_back(i);
- // The way LOS works is that it will check to see if there is a LOS detail that matches
- // the the collision detail + 1 + MaxCollisionShapes (this variable name should change in
- // the future). If it can't find a matching LOS it will simply use the collision instead.
- // We check for any "unmatched" LOS's further down
- mLOSDetails.increment();
- char buff[128];
- dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/);
- U32 los = mDataBlock->mShape->findDetail(buff);
- if (los == -1)
- mLOSDetails.last() = i;
- else
- mLOSDetails.last() = los;
- }
- }
- // Snag any "unmatched" LOS details
- static const String sLOSStr( "LOS-" );
- for (U32 i = 0; i < mDataBlock->mShape->details.size(); i++)
- {
- const String &name = mDataBlock->mShape->names[mDataBlock->mShape->details[i].nameIndex];
- if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0)
- {
- // See if we already have this LOS
- bool found = false;
- for (U32 j = 0; j < mLOSDetails.size(); j++)
- {
- if (mLOSDetails[j] == i)
- {
- found = true;
- break;
- }
- }
- if (!found)
- mLOSDetails.push_back(i);
- }
- }
- // Compute the hull accelerators (actually, just force the shape to compute them)
- for (U32 i = 0; i < mCollisionDetails.size(); i++)
- shape_inst->getShape()->getAccelerator(mCollisionDetails[i]);
- }
- // tell engine the model exists
- gClientSceneGraph->addObjectToScene(this);
- removeFromProcessList();
- ClientProcessList::get()->addObject(this);
- conn->addObject(this);
- return true;
- }
- void afxModel::onRemove()
- {
- mSceneManager->removeObjectFromScene(this);
- getContainer()->removeObject(this);
- Parent::onRemove();
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
- void afxModel::advanceTime(F32 dt)
- {
- if (main_seq_thread)
- shape_inst->advanceTime(dt, main_seq_thread);
- for (S32 i = 0; i < blend_clips.size(); i++)
- shape_inst->advanceTime(dt, blend_clips[i].thread);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
- void afxModel::prepRenderImage(SceneRenderState* state)
- {
- if (!is_visible || !shape_inst)
- return;
-
- // calculate distance to camera
- Point3F cameraOffset;
- getRenderTransform().getColumn(3, &cameraOffset);
- cameraOffset -= state->getCameraPosition();
- F32 dist = cameraOffset.len();
- if (dist < 0.01f)
- dist = 0.01f;
- F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));
- shape_inst->setDetailFromDistance(state, dist*invScale);
- if ( shape_inst->getCurrentDetail() < 0 )
- return;
- renderObject(state);
- }
- bool afxModel::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
- {
- if (shape_inst)
- {
- RayInfo shortest;
- shortest.t = 1e8;
- info->object = NULL;
- if (mLOSDetails.size() > 0)
- {
- for (U32 i = 0; i < mLOSDetails.size(); i++)
- {
- shape_inst->animate(mLOSDetails[i]);
- if (shape_inst->castRay(start, end, info, mLOSDetails[i]))
- {
- info->object = this;
- if (info->t < shortest.t)
- shortest = *info;
- }
- }
- }
- else
- {
- if (mCollisionDetails.size() > 0)
- {
- for (U32 i = 0; i < mCollisionDetails.size(); i++)
- {
- shape_inst->animate(mCollisionDetails[i]);
- if (shape_inst->castRay(start, end, info, mCollisionDetails[i]))
- {
- info->object = this;
- if (info->t < shortest.t)
- shortest = *info;
- }
- }
- }
- }
- if (info->object == this)
- {
- // Copy out the shortest time...
- *info = shortest;
- return true;
- }
- }
- return false;
- }
- U32 afxModel::unique_anim_tag_counter = 1;
- #define BAD_ANIM_ID 999999999
- U32 afxModel::setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans)
- {
- if (!shape_inst)
- return 0;
- TSShape* shape = shape_inst->getShape();
- S32 seq_id = shape->findSequence(clip);
- if (seq_id == -1)
- {
- Con::errorf("afxModel::setAnimClip() -- failed to find a sequence matching the name, \"%s\".", clip);
- return 0;
- }
- // JTF Note: test if this blend implementation is working
- if (shape->sequences[seq_id].isBlend())
- {
- BlendThread blend_clip;
- blend_clip.tag = ((unique_anim_tag_counter++) | 0x80000000);
- blend_clip.thread = shape_inst->addThread();
- shape_inst->setSequence(blend_clip.thread, seq_id, pos);
- shape_inst->setTimeScale(blend_clip.thread, rate);
- blend_clips.push_back(blend_clip);
- return blend_clip.tag;
- }
- if (!main_seq_thread)
- {
- main_seq_thread = shape_inst->addThread();
- shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*rate);
- shape_inst->setSequence(main_seq_thread, seq_id, pos);
- seq_animates_vis = shape->sequences[seq_id].visMatters.testAll();
- }
- else
- {
- shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*rate);
- F32 transTime = (trans < 0) ? 0.25 : trans;
- if (transTime > 0.0f)
- shape_inst->transitionToSequence(main_seq_thread, seq_id, pos, transTime, true);
- else
- shape_inst->setSequence(main_seq_thread, seq_id, pos);
- seq_animates_vis = shape->sequences[seq_id].visMatters.testAll();
- }
- last_anim_tag = unique_anim_tag_counter++;
- return last_anim_tag;
- }
- void afxModel::resetAnimation(U32 tag)
- {
- // check if this is a blended clip
- if ((tag & 0x80000000) != 0)
- {
- for (S32 i = 0; i < blend_clips.size(); i++)
- {
- if (blend_clips[i].tag == tag)
- {
- if (blend_clips[i].thread)
- {
- //Con::printf("DESTROY THREAD %d of %d tag=%d" , i, blend_clips.size(), tag & 0x7fffffff);
- shape_inst->destroyThread(blend_clips[i].thread);
- }
- blend_clips.erase_fast(i);
- break;
- }
- }
- return;
- }
- if (tag != 0 && tag == last_anim_tag)
- {
- // restore original non-animated state
- if (main_seq_id == -1)
- {
- shape_inst->destroyThread(main_seq_thread);
- main_seq_thread = 0;
- }
- // restore original sequence
- else
- {
- shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
- shape_inst->transitionToSequence(main_seq_thread, main_seq_id , 0.0f, 0.25f, true);
- }
- last_anim_tag = 0;
- }
- }
- F32 afxModel::getAnimClipDuration(const char* clip)
- {
- if (!shape_inst)
- return 0.0f;
- TSShape* shape = shape_inst->getShape();
- S32 seq_id = shape->findSequence(clip);
- return (seq_id != -1) ? shape->sequences[seq_id].duration : 0.0f;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|