mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 00:24:40 +00:00
update assimp to 5.2.3 Bugfix-Release
This commit is contained in:
parent
3f796d2a06
commit
f297476092
1150 changed files with 165834 additions and 112019 deletions
609
Engine/lib/assimp/code/AssetLib/LWO/LWOAnimation.cpp
Normal file
609
Engine/lib/assimp/code/AssetLib/LWO/LWOAnimation.cpp
Normal file
|
|
@ -0,0 +1,609 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file LWOAnimation.cpp
|
||||
* @brief LWOAnimationResolver utility class
|
||||
*
|
||||
* It's a very generic implementation of LightWave's system of
|
||||
* component-wise-animated stuff. The one and only fully free
|
||||
* implementation of LightWave envelopes of which I know.
|
||||
*/
|
||||
|
||||
#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER) && (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
|
||||
|
||||
#include <functional>
|
||||
|
||||
// internal headers
|
||||
#include "LWOFileData.h"
|
||||
#include <assimp/anim.h>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::LWO;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct an animation resolver from a given list of envelopes
|
||||
AnimResolver::AnimResolver(std::list<Envelope> &_envelopes, double tick) :
|
||||
envelopes(_envelopes),
|
||||
sample_rate(0.),
|
||||
envl_x(),
|
||||
envl_y(),
|
||||
envl_z(),
|
||||
end_x(),
|
||||
end_y(),
|
||||
end_z(),
|
||||
flags(),
|
||||
sample_delta() {
|
||||
trans_x = trans_y = trans_z = nullptr;
|
||||
rotat_x = rotat_y = rotat_z = nullptr;
|
||||
scale_x = scale_y = scale_z = nullptr;
|
||||
|
||||
first = last = 150392.;
|
||||
|
||||
// find transformation envelopes
|
||||
for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
|
||||
|
||||
(*it).old_first = 0;
|
||||
(*it).old_last = (*it).keys.size() - 1;
|
||||
|
||||
if ((*it).keys.empty()) {
|
||||
continue;
|
||||
}
|
||||
if ((int)(*it).type < 1 || (int)(*it).type>EnvelopeType_Unknown) {
|
||||
continue;
|
||||
}
|
||||
switch ((*it).type) {
|
||||
// translation
|
||||
case LWO::EnvelopeType_Position_X:
|
||||
trans_x = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Position_Y:
|
||||
trans_y = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Position_Z:
|
||||
trans_z = &*it;
|
||||
break;
|
||||
|
||||
// rotation
|
||||
case LWO::EnvelopeType_Rotation_Heading:
|
||||
rotat_x = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Rotation_Pitch:
|
||||
rotat_y = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Rotation_Bank:
|
||||
rotat_z = &*it;
|
||||
break;
|
||||
|
||||
// scaling
|
||||
case LWO::EnvelopeType_Scaling_X:
|
||||
scale_x = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Scaling_Y:
|
||||
scale_y = &*it;
|
||||
break;
|
||||
case LWO::EnvelopeType_Scaling_Z:
|
||||
scale_z = &*it;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
};
|
||||
|
||||
// convert from seconds to ticks
|
||||
for (std::vector<LWO::Key>::iterator d = (*it).keys.begin(); d != (*it).keys.end(); ++d)
|
||||
(*d).time *= tick;
|
||||
|
||||
// set default animation range (minimum and maximum time value for which we have a keyframe)
|
||||
first = std::min(first, (*it).keys.front().time);
|
||||
last = std::max(last, (*it).keys.back().time);
|
||||
}
|
||||
|
||||
// deferred setup of animation range to increase performance.
|
||||
// typically the application will want to specify its own.
|
||||
need_to_setup = true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reset all envelopes to their original contents
|
||||
void AnimResolver::ClearAnimRangeSetup() {
|
||||
for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
|
||||
|
||||
(*it).keys.erase((*it).keys.begin(), (*it).keys.begin() + (*it).old_first);
|
||||
(*it).keys.erase((*it).keys.begin() + (*it).old_last + 1, (*it).keys.end());
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Insert additional keys to match LWO's pre& post behaviors.
|
||||
void AnimResolver::UpdateAnimRangeSetup() {
|
||||
// XXX doesn't work yet (hangs if more than one envelope channels needs to be interpolated)
|
||||
|
||||
for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
|
||||
if ((*it).keys.empty()) continue;
|
||||
|
||||
const double my_first = (*it).keys.front().time;
|
||||
const double my_last = (*it).keys.back().time;
|
||||
|
||||
const double delta = my_last - my_first;
|
||||
const size_t old_size = (*it).keys.size();
|
||||
|
||||
const float value_delta = (*it).keys.back().value - (*it).keys.front().value;
|
||||
|
||||
// NOTE: We won't handle reset, linear and constant here.
|
||||
// See DoInterpolation() for their implementation.
|
||||
|
||||
// process pre behavior
|
||||
switch ((*it).pre) {
|
||||
case LWO::PrePostBehaviour_OffsetRepeat:
|
||||
case LWO::PrePostBehaviour_Repeat:
|
||||
case LWO::PrePostBehaviour_Oscillate: {
|
||||
const double start_time = delta - std::fmod(my_first - first, delta);
|
||||
std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(), (*it).keys.end(),
|
||||
[start_time](double t) { return start_time > t; }),
|
||||
m;
|
||||
|
||||
size_t ofs = 0;
|
||||
if (n != (*it).keys.end()) {
|
||||
// copy from here - don't use iterators, insert() would invalidate them
|
||||
ofs = (*it).keys.end() - n;
|
||||
(*it).keys.insert((*it).keys.begin(), ofs, LWO::Key());
|
||||
|
||||
std::copy((*it).keys.end() - ofs, (*it).keys.end(), (*it).keys.begin());
|
||||
}
|
||||
|
||||
// do full copies. again, no iterators
|
||||
const unsigned int num = (unsigned int)((my_first - first) / delta);
|
||||
(*it).keys.resize((*it).keys.size() + num * old_size);
|
||||
|
||||
n = (*it).keys.begin() + ofs;
|
||||
bool reverse = false;
|
||||
for (unsigned int i = 0; i < num; ++i) {
|
||||
m = n + old_size * (i + 1);
|
||||
std::copy(n, n + old_size, m);
|
||||
const bool res = ((*it).pre == LWO::PrePostBehaviour_Oscillate);
|
||||
reverse = !reverse;
|
||||
if (res && reverse) {
|
||||
std::reverse(m, m + old_size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// update time values
|
||||
n = (*it).keys.end() - (old_size + 1);
|
||||
double cur_minus = delta;
|
||||
unsigned int tt = 1;
|
||||
for (const double tmp = delta * (num + 1); cur_minus <= tmp; cur_minus += delta, ++tt) {
|
||||
m = (delta == tmp ? (*it).keys.begin() : n - (old_size + 1));
|
||||
for (; m != n; --n) {
|
||||
(*n).time -= cur_minus;
|
||||
|
||||
// offset repeat? add delta offset to key value
|
||||
if ((*it).pre == LWO::PrePostBehaviour_OffsetRepeat) {
|
||||
(*n).value += tt * value_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// silence compiler warning
|
||||
break;
|
||||
}
|
||||
|
||||
// process post behavior
|
||||
switch ((*it).post) {
|
||||
|
||||
case LWO::PrePostBehaviour_OffsetRepeat:
|
||||
case LWO::PrePostBehaviour_Repeat:
|
||||
case LWO::PrePostBehaviour_Oscillate:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// silence compiler warning
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Extract bind pose matrix
|
||||
void AnimResolver::ExtractBindPose(aiMatrix4x4 &out) {
|
||||
// If we have no envelopes, return identity
|
||||
if (envelopes.empty()) {
|
||||
out = aiMatrix4x4();
|
||||
return;
|
||||
}
|
||||
aiVector3D angles, scaling(1.f, 1.f, 1.f), translation;
|
||||
|
||||
if (trans_x) translation.x = trans_x->keys[0].value;
|
||||
if (trans_y) translation.y = trans_y->keys[0].value;
|
||||
if (trans_z) translation.z = trans_z->keys[0].value;
|
||||
|
||||
if (rotat_x) angles.x = rotat_x->keys[0].value;
|
||||
if (rotat_y) angles.y = rotat_y->keys[0].value;
|
||||
if (rotat_z) angles.z = rotat_z->keys[0].value;
|
||||
|
||||
if (scale_x) scaling.x = scale_x->keys[0].value;
|
||||
if (scale_y) scaling.y = scale_y->keys[0].value;
|
||||
if (scale_z) scaling.z = scale_z->keys[0].value;
|
||||
|
||||
// build the final matrix
|
||||
aiMatrix4x4 s, rx, ry, rz, t;
|
||||
aiMatrix4x4::RotationZ(angles.z, rz);
|
||||
aiMatrix4x4::RotationX(angles.y, rx);
|
||||
aiMatrix4x4::RotationY(angles.x, ry);
|
||||
aiMatrix4x4::Translation(translation, t);
|
||||
aiMatrix4x4::Scaling(scaling, s);
|
||||
out = t * ry * rx * rz * s;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Do a single interpolation on a channel
|
||||
void AnimResolver::DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
|
||||
LWO::Envelope *envl, double time, float &fill) {
|
||||
if (envl->keys.size() == 1) {
|
||||
fill = envl->keys[0].value;
|
||||
return;
|
||||
}
|
||||
|
||||
// check whether we're at the beginning of the animation track
|
||||
if (cur == envl->keys.begin()) {
|
||||
|
||||
// ok ... this depends on pre behaviour now
|
||||
// we don't need to handle repeat&offset repeat&oszillate here, see UpdateAnimRangeSetup()
|
||||
switch (envl->pre) {
|
||||
case LWO::PrePostBehaviour_Linear:
|
||||
DoInterpolation2(cur, cur + 1, time, fill);
|
||||
return;
|
||||
|
||||
case LWO::PrePostBehaviour_Reset:
|
||||
fill = 0.f;
|
||||
return;
|
||||
|
||||
default: //case LWO::PrePostBehaviour_Constant:
|
||||
fill = (*cur).value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// check whether we're at the end of the animation track
|
||||
else if (cur == envl->keys.end() - 1 && time > envl->keys.rbegin()->time) {
|
||||
// ok ... this depends on post behaviour now
|
||||
switch (envl->post) {
|
||||
case LWO::PrePostBehaviour_Linear:
|
||||
DoInterpolation2(cur, cur - 1, time, fill);
|
||||
return;
|
||||
|
||||
case LWO::PrePostBehaviour_Reset:
|
||||
fill = 0.f;
|
||||
return;
|
||||
|
||||
default: //case LWO::PrePostBehaviour_Constant:
|
||||
fill = (*cur).value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise do a simple interpolation
|
||||
DoInterpolation2(cur - 1, cur, time, fill);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Almost the same, except we won't handle pre/post conditions here
|
||||
void AnimResolver::DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
|
||||
std::vector<LWO::Key>::const_iterator end, double time, float &fill) {
|
||||
switch ((*end).inter) {
|
||||
|
||||
case LWO::IT_STEP:
|
||||
// no interpolation at all - take the value of the last key
|
||||
fill = (*beg).value;
|
||||
return;
|
||||
default:
|
||||
|
||||
// silence compiler warning
|
||||
break;
|
||||
}
|
||||
// linear interpolation - default
|
||||
double duration = (*end).time - (*beg).time;
|
||||
if (duration > 0.0) {
|
||||
fill = (*beg).value + ((*end).value - (*beg).value) * (float)(((time - (*beg).time) / duration));
|
||||
} else {
|
||||
fill = (*beg).value;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Subsample animation track by given key values
|
||||
void AnimResolver::SubsampleAnimTrack(std::vector<aiVectorKey> & /*out*/,
|
||||
double /*time*/, double /*sample_delta*/) {
|
||||
//ai_assert(out.empty() && sample_delta);
|
||||
|
||||
//const double time_start = out.back().mTime;
|
||||
// for ()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Track interpolation
|
||||
void AnimResolver::InterpolateTrack(std::vector<aiVectorKey> &out, aiVectorKey &fill, double time) {
|
||||
// subsample animation track?
|
||||
if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
|
||||
SubsampleAnimTrack(out, time, sample_delta);
|
||||
}
|
||||
|
||||
fill.mTime = time;
|
||||
|
||||
// get x
|
||||
if ((*cur_x).time == time) {
|
||||
fill.mValue.x = (*cur_x).value;
|
||||
|
||||
if (cur_x != envl_x->keys.end() - 1) /* increment x */
|
||||
++cur_x;
|
||||
else
|
||||
end_x = true;
|
||||
} else
|
||||
DoInterpolation(cur_x, envl_x, time, (float &)fill.mValue.x);
|
||||
|
||||
// get y
|
||||
if ((*cur_y).time == time) {
|
||||
fill.mValue.y = (*cur_y).value;
|
||||
|
||||
if (cur_y != envl_y->keys.end() - 1) /* increment y */
|
||||
++cur_y;
|
||||
else
|
||||
end_y = true;
|
||||
} else
|
||||
DoInterpolation(cur_y, envl_y, time, (float &)fill.mValue.y);
|
||||
|
||||
// get z
|
||||
if ((*cur_z).time == time) {
|
||||
fill.mValue.z = (*cur_z).value;
|
||||
|
||||
if (cur_z != envl_z->keys.end() - 1) /* increment z */
|
||||
++cur_z;
|
||||
else
|
||||
end_x = true;
|
||||
} else
|
||||
DoInterpolation(cur_z, envl_z, time, (float &)fill.mValue.z);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build linearly subsampled keys from three single envelopes, one for each component (x,y,z)
|
||||
void AnimResolver::GetKeys(std::vector<aiVectorKey> &out,
|
||||
LWO::Envelope *_envl_x,
|
||||
LWO::Envelope *_envl_y,
|
||||
LWO::Envelope *_envl_z,
|
||||
unsigned int _flags) {
|
||||
envl_x = _envl_x;
|
||||
envl_y = _envl_y;
|
||||
envl_z = _envl_z;
|
||||
flags = _flags;
|
||||
|
||||
// generate default channels if none are given
|
||||
LWO::Envelope def_x, def_y, def_z;
|
||||
LWO::Key key_dummy;
|
||||
key_dummy.time = 0.f;
|
||||
if ((envl_x && envl_x->type == LWO::EnvelopeType_Scaling_X) ||
|
||||
(envl_y && envl_y->type == LWO::EnvelopeType_Scaling_Y) ||
|
||||
(envl_z && envl_z->type == LWO::EnvelopeType_Scaling_Z)) {
|
||||
key_dummy.value = 1.f;
|
||||
} else
|
||||
key_dummy.value = 0.f;
|
||||
|
||||
if (!envl_x) {
|
||||
envl_x = &def_x;
|
||||
envl_x->keys.push_back(key_dummy);
|
||||
}
|
||||
if (!envl_y) {
|
||||
envl_y = &def_y;
|
||||
envl_y->keys.push_back(key_dummy);
|
||||
}
|
||||
if (!envl_z) {
|
||||
envl_z = &def_z;
|
||||
envl_z->keys.push_back(key_dummy);
|
||||
}
|
||||
|
||||
// guess how many keys we'll get
|
||||
size_t reserve;
|
||||
double sr = 1.;
|
||||
if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
|
||||
if (!sample_rate)
|
||||
sr = 100.f;
|
||||
else
|
||||
sr = sample_rate;
|
||||
sample_delta = 1.f / sr;
|
||||
|
||||
reserve = (size_t)(
|
||||
std::max(envl_x->keys.rbegin()->time,
|
||||
std::max(envl_y->keys.rbegin()->time, envl_z->keys.rbegin()->time)) *
|
||||
sr);
|
||||
} else
|
||||
reserve = std::max(envl_x->keys.size(), std::max(envl_x->keys.size(), envl_z->keys.size()));
|
||||
out.reserve(reserve + (reserve >> 1));
|
||||
|
||||
// Iterate through all three arrays at once - it's tricky, but
|
||||
// rather interesting to implement.
|
||||
cur_x = envl_x->keys.begin();
|
||||
cur_y = envl_y->keys.begin();
|
||||
cur_z = envl_z->keys.begin();
|
||||
|
||||
end_x = end_y = end_z = false;
|
||||
while (1) {
|
||||
|
||||
aiVectorKey fill;
|
||||
|
||||
if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time) {
|
||||
|
||||
// we have a keyframe for all of them defined .. this means
|
||||
// we don't need to interpolate here.
|
||||
fill.mTime = (*cur_x).time;
|
||||
|
||||
fill.mValue.x = (*cur_x).value;
|
||||
fill.mValue.y = (*cur_y).value;
|
||||
fill.mValue.z = (*cur_z).value;
|
||||
|
||||
// subsample animation track
|
||||
if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
|
||||
//SubsampleAnimTrack(out,cur_x, cur_y, cur_z, d, sample_delta);
|
||||
}
|
||||
}
|
||||
|
||||
// Find key with lowest time value
|
||||
else if ((*cur_x).time <= (*cur_y).time && !end_x) {
|
||||
|
||||
if ((*cur_z).time <= (*cur_x).time && !end_z) {
|
||||
InterpolateTrack(out, fill, (*cur_z).time);
|
||||
} else {
|
||||
InterpolateTrack(out, fill, (*cur_x).time);
|
||||
}
|
||||
} else if ((*cur_z).time <= (*cur_y).time && !end_y) {
|
||||
InterpolateTrack(out, fill, (*cur_y).time);
|
||||
} else if (!end_y) {
|
||||
// welcome on the server, y
|
||||
InterpolateTrack(out, fill, (*cur_y).time);
|
||||
} else {
|
||||
// we have reached the end of at least 2 channels,
|
||||
// only one is remaining. Extrapolate the 2.
|
||||
if (end_y) {
|
||||
InterpolateTrack(out, fill, (end_x ? (*cur_z) : (*cur_x)).time);
|
||||
} else if (end_x) {
|
||||
InterpolateTrack(out, fill, (end_z ? (*cur_y) : (*cur_z)).time);
|
||||
} else { // if (end_z)
|
||||
InterpolateTrack(out, fill, (end_y ? (*cur_x) : (*cur_y)).time);
|
||||
}
|
||||
}
|
||||
double lasttime = fill.mTime;
|
||||
out.push_back(fill);
|
||||
|
||||
if (lasttime >= (*cur_x).time) {
|
||||
if (cur_x != envl_x->keys.end() - 1)
|
||||
++cur_x;
|
||||
else
|
||||
end_x = true;
|
||||
}
|
||||
if (lasttime >= (*cur_y).time) {
|
||||
if (cur_y != envl_y->keys.end() - 1)
|
||||
++cur_y;
|
||||
else
|
||||
end_y = true;
|
||||
}
|
||||
if (lasttime >= (*cur_z).time) {
|
||||
if (cur_z != envl_z->keys.end() - 1)
|
||||
++cur_z;
|
||||
else
|
||||
end_z = true;
|
||||
}
|
||||
|
||||
if (end_x && end_y && end_z) /* finished? */
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & AI_LWO_ANIM_FLAG_START_AT_ZERO) {
|
||||
for (std::vector<aiVectorKey>::iterator it = out.begin(); it != out.end(); ++it)
|
||||
(*it).mTime -= first;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Extract animation channel
|
||||
void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) {
|
||||
*out = nullptr;
|
||||
|
||||
//FIXME: crashes if more than one component is animated at different timings, to be resolved.
|
||||
|
||||
// If we have no envelopes, return nullptr
|
||||
if (envelopes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We won't spawn an animation channel if we don't have at least one envelope with more than one keyframe defined.
|
||||
const bool trans = ((trans_x && trans_x->keys.size() > 1) || (trans_y && trans_y->keys.size() > 1) || (trans_z && trans_z->keys.size() > 1));
|
||||
const bool rotat = ((rotat_x && rotat_x->keys.size() > 1) || (rotat_y && rotat_y->keys.size() > 1) || (rotat_z && rotat_z->keys.size() > 1));
|
||||
const bool scale = ((scale_x && scale_x->keys.size() > 1) || (scale_y && scale_y->keys.size() > 1) || (scale_z && scale_z->keys.size() > 1));
|
||||
if (!trans && !rotat && !scale)
|
||||
return;
|
||||
|
||||
// Allocate the output animation
|
||||
aiNodeAnim *anim = *out = new aiNodeAnim();
|
||||
|
||||
// Setup default animation setup if necessary
|
||||
if (need_to_setup) {
|
||||
UpdateAnimRangeSetup();
|
||||
need_to_setup = false;
|
||||
}
|
||||
|
||||
// copy translation keys
|
||||
if (trans) {
|
||||
std::vector<aiVectorKey> keys;
|
||||
GetKeys(keys, trans_x, trans_y, trans_z, flags);
|
||||
|
||||
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = static_cast<unsigned int>(keys.size())];
|
||||
std::copy(keys.begin(), keys.end(), anim->mPositionKeys);
|
||||
}
|
||||
|
||||
// copy rotation keys
|
||||
if (rotat) {
|
||||
std::vector<aiVectorKey> keys;
|
||||
GetKeys(keys, rotat_x, rotat_y, rotat_z, flags);
|
||||
|
||||
anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = static_cast<unsigned int>(keys.size())];
|
||||
|
||||
// convert heading, pitch, bank to quaternion
|
||||
// mValue.x=Heading=Rot(Y), mValue.y=Pitch=Rot(X), mValue.z=Bank=Rot(Z)
|
||||
// Lightwave's rotation order is ZXY
|
||||
aiVector3D X(1.0, 0.0, 0.0);
|
||||
aiVector3D Y(0.0, 1.0, 0.0);
|
||||
aiVector3D Z(0.0, 0.0, 1.0);
|
||||
for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
|
||||
aiQuatKey &qk = anim->mRotationKeys[i];
|
||||
qk.mTime = keys[i].mTime;
|
||||
qk.mValue = aiQuaternion(Y, keys[i].mValue.x) * aiQuaternion(X, keys[i].mValue.y) * aiQuaternion(Z, keys[i].mValue.z);
|
||||
}
|
||||
}
|
||||
|
||||
// copy scaling keys
|
||||
if (scale) {
|
||||
std::vector<aiVectorKey> keys;
|
||||
GetKeys(keys, scale_x, scale_y, scale_z, flags);
|
||||
|
||||
anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = static_cast<unsigned int>(keys.size())];
|
||||
std::copy(keys.begin(), keys.end(), anim->mScalingKeys);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // no lwo or no lws
|
||||
346
Engine/lib/assimp/code/AssetLib/LWO/LWOAnimation.h
Normal file
346
Engine/lib/assimp/code/AssetLib/LWO/LWOAnimation.h
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file LWOAnimation.h
|
||||
* @brief LWOAnimationResolver utility class
|
||||
*
|
||||
* This is for all lightwave-related file format, not only LWO.
|
||||
* LWS isthe main purpose.
|
||||
*/
|
||||
#ifndef AI_LWO_ANIMATION_INCLUDED
|
||||
#define AI_LWO_ANIMATION_INCLUDED
|
||||
|
||||
//
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
struct aiNodeAnim;
|
||||
struct aiVectorKey;
|
||||
|
||||
namespace Assimp {
|
||||
namespace LWO {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief List of recognized LWO envelopes
|
||||
*/
|
||||
enum EnvelopeType
|
||||
{
|
||||
EnvelopeType_Position_X = 0x1,
|
||||
EnvelopeType_Position_Y = 0x2,
|
||||
EnvelopeType_Position_Z = 0x3,
|
||||
|
||||
EnvelopeType_Rotation_Heading = 0x4,
|
||||
EnvelopeType_Rotation_Pitch = 0x5,
|
||||
EnvelopeType_Rotation_Bank = 0x6,
|
||||
|
||||
EnvelopeType_Scaling_X = 0x7,
|
||||
EnvelopeType_Scaling_Y = 0x8,
|
||||
EnvelopeType_Scaling_Z = 0x9,
|
||||
|
||||
// -- currently not yet handled
|
||||
EnvelopeType_Color_R = 0xa,
|
||||
EnvelopeType_Color_G = 0xb,
|
||||
EnvelopeType_Color_B = 0xc,
|
||||
|
||||
EnvelopeType_Falloff_X = 0xd,
|
||||
EnvelopeType_Falloff_Y = 0xe,
|
||||
EnvelopeType_Falloff_Z = 0xf,
|
||||
|
||||
EnvelopeType_Unknown
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief List of recognized LWO interpolation modes
|
||||
*/
|
||||
enum InterpolationType
|
||||
{
|
||||
IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief List of recognized LWO pre or post range behaviours
|
||||
*/
|
||||
enum PrePostBehaviour
|
||||
{
|
||||
PrePostBehaviour_Reset = 0x0,
|
||||
PrePostBehaviour_Constant = 0x1,
|
||||
PrePostBehaviour_Repeat = 0x2,
|
||||
PrePostBehaviour_Oscillate = 0x3,
|
||||
PrePostBehaviour_OffsetRepeat = 0x4,
|
||||
PrePostBehaviour_Linear = 0x5
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO animation keyframe
|
||||
*/
|
||||
struct Key {
|
||||
Key() AI_NO_EXCEPT
|
||||
: time()
|
||||
, value()
|
||||
, inter(IT_LINE)
|
||||
, params() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Current time
|
||||
double time;
|
||||
|
||||
//! Current value
|
||||
float value;
|
||||
|
||||
//! How to interpolate this key with previous key?
|
||||
InterpolationType inter;
|
||||
|
||||
//! Interpolation parameters
|
||||
float params[5];
|
||||
|
||||
|
||||
// for std::find()
|
||||
operator double () {
|
||||
return time;
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO animation envelope
|
||||
*/
|
||||
struct Envelope {
|
||||
Envelope() AI_NO_EXCEPT
|
||||
: index()
|
||||
, type(EnvelopeType_Unknown)
|
||||
, pre(PrePostBehaviour_Constant)
|
||||
, post(PrePostBehaviour_Constant)
|
||||
, old_first(0)
|
||||
, old_last(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Index of this envelope
|
||||
unsigned int index;
|
||||
|
||||
//! Type of envelope
|
||||
EnvelopeType type;
|
||||
|
||||
//! Pre- and post-behavior
|
||||
PrePostBehaviour pre,post;
|
||||
|
||||
//! Keyframes for this envelope
|
||||
std::vector<Key> keys;
|
||||
|
||||
// temporary data for AnimResolver
|
||||
size_t old_first,old_last;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
//! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS
|
||||
//! Flag for AnimResolver, subsamples the input data with the rate specified
|
||||
//! by AnimResolver::SetSampleRate().
|
||||
#define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
//! @def AI_LWO_ANIM_FLAG_START_AT_ZERO
|
||||
//! Flag for AnimResolver, ensures that the animations starts at zero.
|
||||
#define AI_LWO_ANIM_FLAG_START_AT_ZERO 0x2
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Utility class to build Assimp animations from LWO envelopes.
|
||||
*
|
||||
* Used for both LWO and LWS (MOT also).
|
||||
*/
|
||||
class AnimResolver
|
||||
{
|
||||
public:
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Construct an AnimResolver from a given list of envelopes
|
||||
* @param envelopes Input envelopes. May be empty.
|
||||
* @param Output tick rate, per second
|
||||
* @note The input envelopes are possibly modified.
|
||||
*/
|
||||
AnimResolver(std::list<Envelope>& envelopes, double tick);
|
||||
|
||||
public:
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Extract the bind-pose transformation matrix.
|
||||
* @param out Receives bind-pose transformation matrix
|
||||
*/
|
||||
void ExtractBindPose(aiMatrix4x4& out);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Extract a node animation channel
|
||||
* @param out Receives a pointer to a newly allocated node anim.
|
||||
* If there's just one keyframe defined, *out is set to nullptr and
|
||||
* no animation channel is computed.
|
||||
* @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
|
||||
*/
|
||||
void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Set the sampling rate for ExtractAnimChannel().
|
||||
*
|
||||
* Non-linear interpolations are subsampled with this rate (keys
|
||||
* per second). Closer sampling positions, if existent, are kept.
|
||||
* The sampling rate defaults to 0, if this value is not changed and
|
||||
* AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(),
|
||||
* the class finds a suitable sample rate by itself.
|
||||
*/
|
||||
void SetSampleRate(double sr) {
|
||||
sample_rate = sr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Getter for SetSampleRate()
|
||||
*/
|
||||
double GetSampleRate() const {
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Set the animation time range
|
||||
*
|
||||
* @param first Time where the animation starts, in ticks
|
||||
* @param last Time where the animation ends, in ticks
|
||||
*/
|
||||
void SetAnimationRange(double _first, double _last) {
|
||||
first = _first;
|
||||
last = _last;
|
||||
|
||||
ClearAnimRangeSetup();
|
||||
UpdateAnimRangeSetup();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Build linearly subsampled keys from 3 single envelopes
|
||||
* @param out Receives output keys
|
||||
* @param envl_x X-component envelope
|
||||
* @param envl_y Y-component envelope
|
||||
* @param envl_z Z-component envelope
|
||||
* @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
|
||||
* @note Up to two input envelopes may be nullptr
|
||||
*/
|
||||
void GetKeys(std::vector<aiVectorKey>& out,
|
||||
LWO::Envelope* envl_x,
|
||||
LWO::Envelope* envl_y,
|
||||
LWO::Envelope* envl_z,
|
||||
unsigned int flags);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Resolve a single animation key by applying the right
|
||||
* interpolation to it.
|
||||
* @param cur Current key
|
||||
* @param envl Envelope working on
|
||||
* @param time time to be interpolated
|
||||
* @param fill Receives the interpolated output value.
|
||||
*/
|
||||
void DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
|
||||
LWO::Envelope* envl,double time, float& fill);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Almost the same, except we won't handle pre/post
|
||||
* conditions here.
|
||||
* @see DoInterpolation
|
||||
*/
|
||||
void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
|
||||
std::vector<LWO::Key>::const_iterator end,double time, float& fill);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Interpolate 2 tracks if one is given
|
||||
*
|
||||
* @param out Receives extra output keys
|
||||
* @param key_out Primary output key
|
||||
* @param time Time to interpolate for
|
||||
*/
|
||||
void InterpolateTrack(std::vector<aiVectorKey>& out,
|
||||
aiVectorKey& key_out,double time);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Subsample an animation track by a given sampling rate
|
||||
*
|
||||
* @param out Receives output keys. Last key at input defines the
|
||||
* time where subsampling starts.
|
||||
* @param time Time to end subsampling at
|
||||
* @param sample_delta Time delta between two samples
|
||||
*/
|
||||
void SubsampleAnimTrack(std::vector<aiVectorKey>& out,
|
||||
double time,double sample_delta);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Delete all keys which we inserted to match anim setup
|
||||
*/
|
||||
void ClearAnimRangeSetup();
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** @brief Insert extra keys to match LWO's pre and post behaviours
|
||||
* in a given time range [first...last]
|
||||
*/
|
||||
void UpdateAnimRangeSetup();
|
||||
|
||||
private:
|
||||
std::list<Envelope>& envelopes;
|
||||
double sample_rate;
|
||||
|
||||
LWO::Envelope* trans_x, *trans_y, *trans_z;
|
||||
LWO::Envelope* rotat_x, *rotat_y, *rotat_z;
|
||||
LWO::Envelope* scale_x, *scale_y, *scale_z;
|
||||
|
||||
double first, last;
|
||||
bool need_to_setup;
|
||||
|
||||
// temporary storage
|
||||
LWO::Envelope* envl_x, * envl_y, * envl_z;
|
||||
std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z;
|
||||
bool end_x, end_y, end_z;
|
||||
|
||||
unsigned int flags;
|
||||
double sample_delta;
|
||||
};
|
||||
|
||||
} // end namespace LWO
|
||||
} // end namespace Assimp
|
||||
|
||||
#endif // !! AI_LWO_ANIMATION_INCLUDED
|
||||
428
Engine/lib/assimp/code/AssetLib/LWO/LWOBLoader.cpp
Normal file
428
Engine/lib/assimp/code/AssetLib/LWO/LWOBLoader.cpp
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file Implementation of the LWO importer class for the older LWOB
|
||||
file formats, including materials */
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
|
||||
// Internal headers
|
||||
#include "LWOLoader.h"
|
||||
using namespace Assimp;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOBFile()
|
||||
{
|
||||
LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
|
||||
bool running = true;
|
||||
while (running)
|
||||
{
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
||||
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head.length > end)
|
||||
{
|
||||
throw DeadlyImportError("LWOB: Invalid chunk length");
|
||||
break;
|
||||
}
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// vertex list
|
||||
case AI_LWO_PNTS:
|
||||
{
|
||||
if (!mCurLayer->mTempPoints.empty())
|
||||
ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice");
|
||||
else LoadLWOPoints(head.length);
|
||||
break;
|
||||
}
|
||||
// face list
|
||||
case AI_LWO_POLS:
|
||||
{
|
||||
|
||||
if (!mCurLayer->mFaces.empty())
|
||||
ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice");
|
||||
else LoadLWOBPolygons(head.length);
|
||||
break;
|
||||
}
|
||||
// list of tags
|
||||
case AI_LWO_SRFS:
|
||||
{
|
||||
if (!mTags->empty())
|
||||
ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
|
||||
else LoadLWOTags(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
LoadLWOBSurface(head.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOBPolygons(unsigned int length)
|
||||
{
|
||||
// first find out how many faces and vertices we'll finally need
|
||||
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
|
||||
LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||
|
||||
// perform endianness conversions
|
||||
#ifndef AI_BUILD_BIG_ENDIAN
|
||||
while (cursor < end)ByteSwap::Swap2(cursor++);
|
||||
cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||
#endif
|
||||
|
||||
unsigned int iNumFaces = 0,iNumVertices = 0;
|
||||
CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
|
||||
|
||||
// allocate the output array and copy face indices
|
||||
if (iNumFaces)
|
||||
{
|
||||
cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||
|
||||
mCurLayer->mFaces.resize(iNumFaces);
|
||||
FaceList::iterator it = mCurLayer->mFaces.begin();
|
||||
CopyFaceIndicesLWOB(it,cursor,end);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
|
||||
LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
|
||||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
uint16_t numIndices;
|
||||
// must have 2 shorts left for numIndices and surface
|
||||
if (end - cursor < 2) {
|
||||
throw DeadlyImportError("LWOB: Unexpected end of file");
|
||||
}
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
// must have enough left for indices and surface
|
||||
if (end - cursor < (1 + numIndices)) {
|
||||
throw DeadlyImportError("LWOB: Unexpected end of file");
|
||||
}
|
||||
verts += numIndices;
|
||||
faces++;
|
||||
cursor += numIndices;
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
// there are detail polygons
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
|
||||
LE_NCONST uint16_t*& cursor,
|
||||
const uint16_t* const end,
|
||||
unsigned int max)
|
||||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
LWO::Face& face = *it;++it;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
face.mNumIndices = numIndices;
|
||||
if(face.mNumIndices)
|
||||
{
|
||||
if (cursor + face.mNumIndices >= end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i) {
|
||||
unsigned int & mi = face.mIndices[i];
|
||||
uint16_t index;
|
||||
::memcpy(&index, cursor++, 2);
|
||||
mi = index;
|
||||
if (mi > mCurLayer->mTempPoints.size())
|
||||
{
|
||||
ASSIMP_LOG_WARN("LWOB: face index is out of range");
|
||||
mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("LWOB: Face has 0 indices");
|
||||
}
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
surface = -surface;
|
||||
|
||||
// there are detail polygons.
|
||||
uint16_t numPolygons;
|
||||
::memcpy(&numPolygons, cursor++, 2);
|
||||
if (cursor < end)
|
||||
{
|
||||
CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||
}
|
||||
}
|
||||
face.surfaceIndex = surface-1;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size)
|
||||
{
|
||||
list.push_back(LWO::Texture());
|
||||
LWO::Texture* tex = &list.back();
|
||||
|
||||
std::string type;
|
||||
GetS0(type,size);
|
||||
const char* s = type.c_str();
|
||||
|
||||
if(strstr(s, "Image Map"))
|
||||
{
|
||||
// Determine mapping type
|
||||
if(strstr(s, "Planar"))
|
||||
tex->mapMode = LWO::Texture::Planar;
|
||||
else if(strstr(s, "Cylindrical"))
|
||||
tex->mapMode = LWO::Texture::Cylindrical;
|
||||
else if(strstr(s, "Spherical"))
|
||||
tex->mapMode = LWO::Texture::Spherical;
|
||||
else if(strstr(s, "Cubic"))
|
||||
tex->mapMode = LWO::Texture::Cubic;
|
||||
else if(strstr(s, "Front"))
|
||||
tex->mapMode = LWO::Texture::FrontProjection;
|
||||
}
|
||||
else
|
||||
{
|
||||
// procedural or gradient, not supported
|
||||
ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOBSurface(unsigned int size)
|
||||
{
|
||||
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
|
||||
mSurfaces->push_back( LWO::Surface () );
|
||||
LWO::Surface& surf = mSurfaces->back();
|
||||
LWO::Texture *pTex = nullptr;
|
||||
|
||||
GetS0(surf.mName,size);
|
||||
bool running = true;
|
||||
while (running) {
|
||||
if (mFileBuffer + 6 >= end)
|
||||
break;
|
||||
|
||||
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
/* A single test file (sonycam.lwo) seems to have invalid surface chunks.
|
||||
* I'm assuming it's the fault of a single, unknown exporter so there are
|
||||
* probably THOUSANDS of them. Here's a dirty workaround:
|
||||
*
|
||||
* We don't break if the chunk limit is exceeded. Instead, we're computing
|
||||
* how much storage is actually left and work with this value from now on.
|
||||
*/
|
||||
if (mFileBuffer + head.length > end) {
|
||||
ASSIMP_LOG_ERROR("LWOB: Invalid surface chunk length. Trying to continue.");
|
||||
head.length = (uint16_t) (end - mFileBuffer);
|
||||
}
|
||||
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
|
||||
surf.mColor.r = GetU1() / 255.0f;
|
||||
surf.mColor.g = GetU1() / 255.0f;
|
||||
surf.mColor.b = GetU1() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// diffuse strength ...
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
|
||||
surf.mDiffuseValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// specular strength ...
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
|
||||
surf.mSpecularValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// luminosity ...
|
||||
case AI_LWO_LUMI:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
|
||||
surf.mLuminosity = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
case AI_LWO_TRAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
|
||||
surf.mTransparency = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// surface flags
|
||||
case AI_LWO_FLAG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
|
||||
uint16_t flag = GetU2();
|
||||
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
|
||||
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
|
||||
if (flag & 0x100) surf.bDoubleSided = true;
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = std::fabs( GetF4() );
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
|
||||
surf.mGlossiness = (float)GetU2();
|
||||
break;
|
||||
}
|
||||
// color texture
|
||||
case AI_LWO_CTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mColorTextures,
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// diffuse texture
|
||||
case AI_LWO_DTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// specular texture
|
||||
case AI_LWO_STEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// bump texture
|
||||
case AI_LWO_BTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// transparency texture
|
||||
case AI_LWO_TTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// texture path
|
||||
case AI_LWO_TIMG:
|
||||
{
|
||||
if (pTex) {
|
||||
GetS0(pTex->mFileName,head.length);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
|
||||
}
|
||||
break;
|
||||
}
|
||||
// texture strength
|
||||
case AI_LWO_TVAL:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
|
||||
if (pTex) {
|
||||
pTex->mStrength = (float)GetU1()/ 255.f;
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
|
||||
}
|
||||
break;
|
||||
}
|
||||
// texture flags
|
||||
case AI_LWO_TFLG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
|
||||
|
||||
if (nullptr != pTex) {
|
||||
const uint16_t s = GetU2();
|
||||
if (s & 1)
|
||||
pTex->majorAxis = LWO::Texture::AXIS_X;
|
||||
else if (s & 2)
|
||||
pTex->majorAxis = LWO::Texture::AXIS_Y;
|
||||
else if (s & 4)
|
||||
pTex->majorAxis = LWO::Texture::AXIS_Z;
|
||||
|
||||
if (s & 16) {
|
||||
ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture");
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
715
Engine/lib/assimp/code/AssetLib/LWO/LWOFileData.h
Normal file
715
Engine/lib/assimp/code/AssetLib/LWO/LWOFileData.h
Normal file
|
|
@ -0,0 +1,715 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file LWOFileData.h
|
||||
* @brief Defines chunk constants used by the LWO file format
|
||||
|
||||
The chunks are taken from the official LightWave SDK headers.
|
||||
|
||||
*/
|
||||
#ifndef AI_LWO_FILEDATA_INCLUDED
|
||||
#define AI_LWO_FILEDATA_INCLUDED
|
||||
|
||||
// STL headers
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// public ASSIMP headers
|
||||
#include <assimp/mesh.h>
|
||||
|
||||
// internal headers
|
||||
#include "AssetLib/LWO/LWOAnimation.h"
|
||||
#include "Common/IFF.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace LWO {
|
||||
|
||||
#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L', 'W', 'O', 'B')
|
||||
#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L', 'W', 'O', '2')
|
||||
#define AI_LWO_FOURCC_LWO3 AI_IFF_FOURCC('L', 'W', 'O', '3')
|
||||
#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L', 'X', 'O', 'B')
|
||||
|
||||
// chunks specific to the LWOB format
|
||||
#define AI_LWO_SRFS AI_IFF_FOURCC('S', 'R', 'F', 'S')
|
||||
#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G')
|
||||
#define AI_LWO_VLUM AI_IFF_FOURCC('V', 'L', 'U', 'M')
|
||||
#define AI_LWO_VDIF AI_IFF_FOURCC('V', 'D', 'I', 'F')
|
||||
#define AI_LWO_VSPC AI_IFF_FOURCC('V', 'S', 'P', 'C')
|
||||
#define AI_LWO_RFLT AI_IFF_FOURCC('R', 'F', 'L', 'T')
|
||||
#define AI_LWO_BTEX AI_IFF_FOURCC('B', 'T', 'E', 'X')
|
||||
#define AI_LWO_CTEX AI_IFF_FOURCC('C', 'T', 'E', 'X')
|
||||
#define AI_LWO_DTEX AI_IFF_FOURCC('D', 'T', 'E', 'X')
|
||||
#define AI_LWO_LTEX AI_IFF_FOURCC('L', 'T', 'E', 'X')
|
||||
#define AI_LWO_RTEX AI_IFF_FOURCC('R', 'T', 'E', 'X')
|
||||
#define AI_LWO_STEX AI_IFF_FOURCC('S', 'T', 'E', 'X')
|
||||
#define AI_LWO_TTEX AI_IFF_FOURCC('T', 'T', 'E', 'X')
|
||||
#define AI_LWO_TFLG AI_IFF_FOURCC('T', 'F', 'L', 'G')
|
||||
#define AI_LWO_TSIZ AI_IFF_FOURCC('T', 'S', 'I', 'Z')
|
||||
#define AI_LWO_TCTR AI_IFF_FOURCC('T', 'C', 'T', 'R')
|
||||
#define AI_LWO_TFAL AI_IFF_FOURCC('T', 'F', 'A', 'L')
|
||||
#define AI_LWO_TVEL AI_IFF_FOURCC('T', 'V', 'E', 'L')
|
||||
#define AI_LWO_TCLR AI_IFF_FOURCC('T', 'C', 'L', 'R')
|
||||
#define AI_LWO_TVAL AI_IFF_FOURCC('T', 'V', 'A', 'L')
|
||||
#define AI_LWO_TAMP AI_IFF_FOURCC('T', 'A', 'M', 'P')
|
||||
#define AI_LWO_TIMG AI_IFF_FOURCC('T', 'I', 'M', 'G')
|
||||
#define AI_LWO_TAAS AI_IFF_FOURCC('T', 'A', 'A', 'S')
|
||||
#define AI_LWO_TREF AI_IFF_FOURCC('T', 'R', 'E', 'F')
|
||||
#define AI_LWO_TOPC AI_IFF_FOURCC('T', 'O', 'P', 'C')
|
||||
#define AI_LWO_SDAT AI_IFF_FOURCC('S', 'D', 'A', 'T')
|
||||
#define AI_LWO_TFP0 AI_IFF_FOURCC('T', 'F', 'P', '0')
|
||||
#define AI_LWO_TFP1 AI_IFF_FOURCC('T', 'F', 'P', '1')
|
||||
|
||||
/* top-level chunks */
|
||||
#define AI_LWO_LAYR AI_IFF_FOURCC('L', 'A', 'Y', 'R')
|
||||
#define AI_LWO_TAGS AI_IFF_FOURCC('T', 'A', 'G', 'S')
|
||||
#define AI_LWO_PNTS AI_IFF_FOURCC('P', 'N', 'T', 'S')
|
||||
#define AI_LWO_BBOX AI_IFF_FOURCC('B', 'B', 'O', 'X')
|
||||
#define AI_LWO_VMAP AI_IFF_FOURCC('V', 'M', 'A', 'P')
|
||||
#define AI_LWO_VMAD AI_IFF_FOURCC('V', 'M', 'A', 'D')
|
||||
#define AI_LWO_POLS AI_IFF_FOURCC('P', 'O', 'L', 'S')
|
||||
#define AI_LWO_PTAG AI_IFF_FOURCC('P', 'T', 'A', 'G')
|
||||
#define AI_LWO_ENVL AI_IFF_FOURCC('E', 'N', 'V', 'L')
|
||||
#define AI_LWO_CLIP AI_IFF_FOURCC('C', 'L', 'I', 'P')
|
||||
#define AI_LWO_SURF AI_IFF_FOURCC('S', 'U', 'R', 'F')
|
||||
#define AI_LWO_DESC AI_IFF_FOURCC('D', 'E', 'S', 'C')
|
||||
#define AI_LWO_TEXT AI_IFF_FOURCC('T', 'E', 'X', 'T')
|
||||
#define AI_LWO_ICON AI_IFF_FOURCC('I', 'C', 'O', 'N')
|
||||
|
||||
/* polygon types */
|
||||
#define AI_LWO_FACE AI_IFF_FOURCC('F', 'A', 'C', 'E')
|
||||
#define AI_LWO_CURV AI_IFF_FOURCC('C', 'U', 'R', 'V')
|
||||
#define AI_LWO_PTCH AI_IFF_FOURCC('P', 'T', 'C', 'H')
|
||||
#define AI_LWO_MBAL AI_IFF_FOURCC('M', 'B', 'A', 'L')
|
||||
#define AI_LWO_BONE AI_IFF_FOURCC('B', 'O', 'N', 'E')
|
||||
#define AI_LWO_SUBD AI_IFF_FOURCC('S', 'U', 'B', 'D')
|
||||
|
||||
/* polygon tags */
|
||||
#define AI_LWO_SURF AI_IFF_FOURCC('S', 'U', 'R', 'F')
|
||||
#define AI_LWO_PART AI_IFF_FOURCC('P', 'A', 'R', 'T')
|
||||
#define AI_LWO_SMGP AI_IFF_FOURCC('S', 'M', 'G', 'P')
|
||||
|
||||
/* envelopes */
|
||||
#define AI_LWO_PRE AI_IFF_FOURCC('P', 'R', 'E', ' ')
|
||||
#define AI_LWO_POST AI_IFF_FOURCC('P', 'O', 'S', 'T')
|
||||
#define AI_LWO_KEY AI_IFF_FOURCC('K', 'E', 'Y', ' ')
|
||||
#define AI_LWO_SPAN AI_IFF_FOURCC('S', 'P', 'A', 'N')
|
||||
#define AI_LWO_TCB AI_IFF_FOURCC('T', 'C', 'B', ' ')
|
||||
#define AI_LWO_HERM AI_IFF_FOURCC('H', 'E', 'R', 'M')
|
||||
#define AI_LWO_BEZI AI_IFF_FOURCC('B', 'E', 'Z', 'I')
|
||||
#define AI_LWO_BEZ2 AI_IFF_FOURCC('B', 'E', 'Z', '2')
|
||||
#define AI_LWO_LINE AI_IFF_FOURCC('L', 'I', 'N', 'E')
|
||||
#define AI_LWO_STEP AI_IFF_FOURCC('S', 'T', 'E', 'P')
|
||||
|
||||
/* clips */
|
||||
#define AI_LWO_STIL AI_IFF_FOURCC('S', 'T', 'I', 'L')
|
||||
#define AI_LWO_ISEQ AI_IFF_FOURCC('I', 'S', 'E', 'Q')
|
||||
#define AI_LWO_ANIM AI_IFF_FOURCC('A', 'N', 'I', 'M')
|
||||
#define AI_LWO_XREF AI_IFF_FOURCC('X', 'R', 'E', 'F')
|
||||
#define AI_LWO_STCC AI_IFF_FOURCC('S', 'T', 'C', 'C')
|
||||
#define AI_LWO_TIME AI_IFF_FOURCC('T', 'I', 'M', 'E')
|
||||
#define AI_LWO_CONT AI_IFF_FOURCC('C', 'O', 'N', 'T')
|
||||
#define AI_LWO_BRIT AI_IFF_FOURCC('B', 'R', 'I', 'T')
|
||||
#define AI_LWO_SATR AI_IFF_FOURCC('S', 'A', 'T', 'R')
|
||||
#define AI_LWO_HUE AI_IFF_FOURCC('H', 'U', 'E', ' ')
|
||||
#define AI_LWO_GAMM AI_IFF_FOURCC('G', 'A', 'M', 'M')
|
||||
#define AI_LWO_NEGA AI_IFF_FOURCC('N', 'E', 'G', 'A')
|
||||
#define AI_LWO_IFLT AI_IFF_FOURCC('I', 'F', 'L', 'T')
|
||||
#define AI_LWO_PFLT AI_IFF_FOURCC('P', 'F', 'L', 'T')
|
||||
|
||||
/* surfaces */
|
||||
#define AI_LWO_COLR AI_IFF_FOURCC('C', 'O', 'L', 'R')
|
||||
#define AI_LWO_LUMI AI_IFF_FOURCC('L', 'U', 'M', 'I')
|
||||
#define AI_LWO_DIFF AI_IFF_FOURCC('D', 'I', 'F', 'F')
|
||||
#define AI_LWO_SPEC AI_IFF_FOURCC('S', 'P', 'E', 'C')
|
||||
#define AI_LWO_GLOS AI_IFF_FOURCC('G', 'L', 'O', 'S')
|
||||
#define AI_LWO_REFL AI_IFF_FOURCC('R', 'E', 'F', 'L')
|
||||
#define AI_LWO_RFOP AI_IFF_FOURCC('R', 'F', 'O', 'P')
|
||||
#define AI_LWO_RIMG AI_IFF_FOURCC('R', 'I', 'M', 'G')
|
||||
#define AI_LWO_RSAN AI_IFF_FOURCC('R', 'S', 'A', 'N')
|
||||
#define AI_LWO_TRAN AI_IFF_FOURCC('T', 'R', 'A', 'N')
|
||||
#define AI_LWO_TROP AI_IFF_FOURCC('T', 'R', 'O', 'P')
|
||||
#define AI_LWO_TIMG AI_IFF_FOURCC('T', 'I', 'M', 'G')
|
||||
#define AI_LWO_RIND AI_IFF_FOURCC('R', 'I', 'N', 'D')
|
||||
#define AI_LWO_TRNL AI_IFF_FOURCC('T', 'R', 'N', 'L')
|
||||
#define AI_LWO_BUMP AI_IFF_FOURCC('B', 'U', 'M', 'P')
|
||||
#define AI_LWO_SMAN AI_IFF_FOURCC('S', 'M', 'A', 'N')
|
||||
#define AI_LWO_SIDE AI_IFF_FOURCC('S', 'I', 'D', 'E')
|
||||
#define AI_LWO_CLRH AI_IFF_FOURCC('C', 'L', 'R', 'H')
|
||||
#define AI_LWO_CLRF AI_IFF_FOURCC('C', 'L', 'R', 'F')
|
||||
#define AI_LWO_ADTR AI_IFF_FOURCC('A', 'D', 'T', 'R')
|
||||
#define AI_LWO_SHRP AI_IFF_FOURCC('S', 'H', 'R', 'P')
|
||||
#define AI_LWO_LINE AI_IFF_FOURCC('L', 'I', 'N', 'E')
|
||||
#define AI_LWO_LSIZ AI_IFF_FOURCC('L', 'S', 'I', 'Z')
|
||||
#define AI_LWO_ALPH AI_IFF_FOURCC('A', 'L', 'P', 'H')
|
||||
#define AI_LWO_AVAL AI_IFF_FOURCC('A', 'V', 'A', 'L')
|
||||
#define AI_LWO_GVAL AI_IFF_FOURCC('G', 'V', 'A', 'L')
|
||||
#define AI_LWO_BLOK AI_IFF_FOURCC('B', 'L', 'O', 'K')
|
||||
#define AI_LWO_VCOL AI_IFF_FOURCC('V', 'C', 'O', 'L')
|
||||
|
||||
/* texture layer */
|
||||
#define AI_LWO_TYPE AI_IFF_FOURCC('T', 'Y', 'P', 'E')
|
||||
#define AI_LWO_CHAN AI_IFF_FOURCC('C', 'H', 'A', 'N')
|
||||
#define AI_LWO_NAME AI_IFF_FOURCC('N', 'A', 'M', 'E')
|
||||
#define AI_LWO_ENAB AI_IFF_FOURCC('E', 'N', 'A', 'B')
|
||||
#define AI_LWO_OPAC AI_IFF_FOURCC('O', 'P', 'A', 'C')
|
||||
#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G')
|
||||
#define AI_LWO_PROJ AI_IFF_FOURCC('P', 'R', 'O', 'J')
|
||||
#define AI_LWO_STCK AI_IFF_FOURCC('S', 'T', 'C', 'K')
|
||||
#define AI_LWO_TAMP AI_IFF_FOURCC('T', 'A', 'M', 'P')
|
||||
|
||||
/* texture coordinates */
|
||||
#define AI_LWO_TMAP AI_IFF_FOURCC('T', 'M', 'A', 'P')
|
||||
#define AI_LWO_AXIS AI_IFF_FOURCC('A', 'X', 'I', 'S')
|
||||
#define AI_LWO_CNTR AI_IFF_FOURCC('C', 'N', 'T', 'R')
|
||||
#define AI_LWO_SIZE AI_IFF_FOURCC('S', 'I', 'Z', 'E')
|
||||
#define AI_LWO_ROTA AI_IFF_FOURCC('R', 'O', 'T', 'A')
|
||||
#define AI_LWO_OREF AI_IFF_FOURCC('O', 'R', 'E', 'F')
|
||||
#define AI_LWO_FALL AI_IFF_FOURCC('F', 'A', 'L', 'L')
|
||||
#define AI_LWO_CSYS AI_IFF_FOURCC('C', 'S', 'Y', 'S')
|
||||
|
||||
/* image map */
|
||||
#define AI_LWO_IMAP AI_IFF_FOURCC('I', 'M', 'A', 'P')
|
||||
#define AI_LWO_IMAG AI_IFF_FOURCC('I', 'M', 'A', 'G')
|
||||
#define AI_LWO_WRAP AI_IFF_FOURCC('W', 'R', 'A', 'P')
|
||||
#define AI_LWO_WRPW AI_IFF_FOURCC('W', 'R', 'P', 'W')
|
||||
#define AI_LWO_WRPH AI_IFF_FOURCC('W', 'R', 'P', 'H')
|
||||
#define AI_LWO_VMAP AI_IFF_FOURCC('V', 'M', 'A', 'P')
|
||||
#define AI_LWO_AAST AI_IFF_FOURCC('A', 'A', 'S', 'T')
|
||||
#define AI_LWO_PIXB AI_IFF_FOURCC('P', 'I', 'X', 'B')
|
||||
|
||||
/* procedural */
|
||||
#define AI_LWO_PROC AI_IFF_FOURCC('P', 'R', 'O', 'C')
|
||||
#define AI_LWO_COLR AI_IFF_FOURCC('C', 'O', 'L', 'R')
|
||||
#define AI_LWO_VALU AI_IFF_FOURCC('V', 'A', 'L', 'U')
|
||||
#define AI_LWO_FUNC AI_IFF_FOURCC('F', 'U', 'N', 'C')
|
||||
#define AI_LWO_FTPS AI_IFF_FOURCC('F', 'T', 'P', 'S')
|
||||
#define AI_LWO_ITPS AI_IFF_FOURCC('I', 'T', 'P', 'S')
|
||||
#define AI_LWO_ETPS AI_IFF_FOURCC('E', 'T', 'P', 'S')
|
||||
|
||||
/* gradient */
|
||||
#define AI_LWO_GRAD AI_IFF_FOURCC('G', 'R', 'A', 'D')
|
||||
#define AI_LWO_GRST AI_IFF_FOURCC('G', 'R', 'S', 'T')
|
||||
#define AI_LWO_GREN AI_IFF_FOURCC('G', 'R', 'E', 'N')
|
||||
#define AI_LWO_PNAM AI_IFF_FOURCC('P', 'N', 'A', 'M')
|
||||
#define AI_LWO_INAM AI_IFF_FOURCC('I', 'N', 'A', 'M')
|
||||
#define AI_LWO_GRPT AI_IFF_FOURCC('G', 'R', 'P', 'T')
|
||||
#define AI_LWO_FKEY AI_IFF_FOURCC('F', 'K', 'E', 'Y')
|
||||
#define AI_LWO_IKEY AI_IFF_FOURCC('I', 'K', 'E', 'Y')
|
||||
|
||||
/* shader */
|
||||
#define AI_LWO_SHDR AI_IFF_FOURCC('S', 'H', 'D', 'R')
|
||||
#define AI_LWO_DATA AI_IFF_FOURCC('D', 'A', 'T', 'A')
|
||||
|
||||
/* VMAP types */
|
||||
#define AI_LWO_TXUV AI_IFF_FOURCC('T', 'X', 'U', 'V')
|
||||
#define AI_LWO_RGB AI_IFF_FOURCC('R', 'G', 'B', ' ')
|
||||
#define AI_LWO_RGBA AI_IFF_FOURCC('R', 'G', 'B', 'A')
|
||||
#define AI_LWO_WGHT AI_IFF_FOURCC('W', 'G', 'H', 'T')
|
||||
|
||||
#define AI_LWO_MNVW AI_IFF_FOURCC('M', 'N', 'V', 'W')
|
||||
#define AI_LWO_MORF AI_IFF_FOURCC('M', 'O', 'R', 'F')
|
||||
#define AI_LWO_SPOT AI_IFF_FOURCC('S', 'P', 'O', 'T')
|
||||
#define AI_LWO_PICK AI_IFF_FOURCC('P', 'I', 'C', 'K')
|
||||
|
||||
// Surface Part
|
||||
#define AI_LWO_NODS AI_IFF_FOURCC('N', 'O', 'D', 'S')
|
||||
#define AI_LWO_NNDS AI_IFF_FOURCC('N', 'N', 'D', 'S')
|
||||
#define AI_LWO_NTAG AI_IFF_FOURCC('N', 'T', 'A', 'G')
|
||||
#define AI_LWO_NRNM AI_IFF_FOURCC('N', 'R', 'N', 'M')
|
||||
#define AI_LWO_NRME AI_IFF_FOURCC('N', 'R', 'M', 'E')
|
||||
#define AI_LWO_NDTA AI_IFF_FOURCC('N', 'D', 'T', 'A')
|
||||
#define AI_LWO_ATTR AI_IFF_FOURCC('A', 'T', 'T', 'R')
|
||||
#define AI_LWO_VERS AI_IFF_FOURCC('V', 'E', 'R', 'S')
|
||||
#define AI_LWO_ENUM AI_IFF_FOURCC('E', 'N', 'U', 'M')
|
||||
#define AI_LWO_ENTR AI_IFF_FOURCC('E', 'N', 'T', 'R')
|
||||
#define AI_LWO_NAME AI_IFF_FOURCC('N', 'A', 'M', 'E')
|
||||
#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G')
|
||||
#define AI_LWO_TAG AI_IFF_FOURCC('T', 'A', 'G', ' ')
|
||||
#define AI_LWO_VALU AI_IFF_FOURCC('V', 'A', 'L', 'U')
|
||||
#define AI_LWO_IBGC AI_IFF_FOURCC('I', 'B', 'G', 'C')
|
||||
#define AI_LWO_IOPC AI_IFF_FOURCC('I', 'O', 'P', 'C')
|
||||
#define AI_LWO_IIMG AI_IFF_FOURCC('I', 'I', 'M', 'G')
|
||||
#define AI_LWO_TXTR AI_IFF_FOURCC('T', 'X', 'T', 'R')
|
||||
|
||||
#define AI_LWO_IFAL AI_IFF_FOURCC('I', 'F', 'A', 'L')
|
||||
#define AI_LWO_ISCL AI_IFF_FOURCC('I', 'S', 'C', 'L')
|
||||
#define AI_LWO_IPOS AI_IFF_FOURCC('I', 'P', 'O', 'S')
|
||||
#define AI_LWO_IROT AI_IFF_FOURCC('I', 'R', 'O', 'T')
|
||||
#define AI_LWO_IBMP AI_IFF_FOURCC('I', 'B', 'M', 'P')
|
||||
#define AI_LWO_IUTD AI_IFF_FOURCC('I', 'U', 'T', 'D')
|
||||
#define AI_LWO_IVTD AI_IFF_FOURCC('I', 'V', 'T', 'D')
|
||||
|
||||
#define AI_LWO_IPIX AI_IFF_FOURCC('I', 'P', 'I', 'X')
|
||||
#define AI_LWO_IMIP AI_IFF_FOURCC('I', 'M', 'I', 'P')
|
||||
#define AI_LWO_IMOD AI_IFF_FOURCC('I', 'M', 'O', 'D')
|
||||
#define AI_LWO_AMOD AI_IFF_FOURCC('A', 'M', 'O', 'D')
|
||||
#define AI_LWO_IINV AI_IFF_FOURCC('I', 'I', 'N', 'V')
|
||||
#define AI_LWO_INCR AI_IFF_FOURCC('I', 'N', 'C', 'R')
|
||||
#define AI_LWO_IAXS AI_IFF_FOURCC('I', 'A', 'X', 'S')
|
||||
#define AI_LWO_IFOT AI_IFF_FOURCC('I', 'F', 'O', 'T')
|
||||
#define AI_LWO_ITIM AI_IFF_FOURCC('I', 'T', 'I', 'M')
|
||||
#define AI_LWO_IWRL AI_IFF_FOURCC('I', 'W', 'R', 'L')
|
||||
#define AI_LWO_IUTI AI_IFF_FOURCC('I', 'U', 'T', 'I')
|
||||
#define AI_LWO_IINX AI_IFF_FOURCC('I', 'I', 'N', 'X')
|
||||
#define AI_LWO_IINY AI_IFF_FOURCC('I', 'I', 'N', 'Y')
|
||||
#define AI_LWO_IINZ AI_IFF_FOURCC('I', 'I', 'N', 'Z')
|
||||
#define AI_LWO_IREF AI_IFF_FOURCC('I', 'R', 'E', 'F')
|
||||
#define AI_LWO_IMST AI_IFF_FOURCC('I', 'M', 'S', 'T')
|
||||
#define AI_LWO_VPVL AI_IFF_FOURCC('V', 'P', 'V', 'L')
|
||||
#define AI_LWO_VPRM AI_IFF_FOURCC('V', 'P', 'R', 'M')
|
||||
#define AI_LWO_IMAP AI_IFF_FOURCC('I', 'M', 'A', 'P')
|
||||
#define AI_LWO_IUVI AI_IFF_FOURCC('I', 'U', 'V', 'I')
|
||||
#define AI_LWO_IUTL AI_IFF_FOURCC('I', 'U', 'T', 'L')
|
||||
#define AI_LWO_IVTL AI_IFF_FOURCC('I', 'V', 'T', 'L')
|
||||
|
||||
// MODO extension - per-vertex normal vectors
|
||||
#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M')
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a face in a LWO file
|
||||
*
|
||||
* \note We can't use the code in SmoothingGroups.inl here - the mesh
|
||||
* structures of 3DS/ASE and LWO are too different.
|
||||
*/
|
||||
struct Face : public aiFace {
|
||||
//! Default construction
|
||||
Face() AI_NO_EXCEPT
|
||||
: surfaceIndex(0),
|
||||
smoothGroup(0),
|
||||
type(AI_LWO_FACE) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Construction from given type
|
||||
explicit Face(uint32_t _type) :
|
||||
surfaceIndex(0), smoothGroup(0), type(_type) {}
|
||||
|
||||
//! Copy construction
|
||||
Face(const Face &f) :
|
||||
aiFace() {
|
||||
*this = f;
|
||||
}
|
||||
|
||||
//! Zero-based index into tags chunk
|
||||
unsigned int surfaceIndex;
|
||||
|
||||
//! Smooth group this face is assigned to
|
||||
unsigned int smoothGroup;
|
||||
|
||||
//! Type of face
|
||||
uint32_t type;
|
||||
|
||||
//! Assignment operator
|
||||
Face &operator=(const LWO::Face &f) {
|
||||
aiFace::operator=(f);
|
||||
surfaceIndex = f.surfaceIndex;
|
||||
smoothGroup = f.smoothGroup;
|
||||
type = f.type;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Base structure for all vertex map representations
|
||||
*/
|
||||
struct VMapEntry {
|
||||
explicit VMapEntry(unsigned int _dims) :
|
||||
dims(_dims) {}
|
||||
|
||||
virtual ~VMapEntry() {}
|
||||
|
||||
//! allocates memory for the vertex map
|
||||
virtual void Allocate(unsigned int num) {
|
||||
if (!rawData.empty())
|
||||
return; // return if already allocated
|
||||
|
||||
const unsigned int m = num * dims;
|
||||
rawData.reserve(m + (m >> 2u)); // 25% as extra storage for VMADs
|
||||
rawData.resize(m, 0.f);
|
||||
abAssigned.resize(num, false);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
unsigned int dims;
|
||||
|
||||
std::vector<float> rawData;
|
||||
std::vector<bool> abAssigned;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Represents an extra vertex color channel
|
||||
*/
|
||||
struct VColorChannel : public VMapEntry {
|
||||
VColorChannel() :
|
||||
VMapEntry(4) {}
|
||||
|
||||
//! need to overwrite this function - the alpha channel must
|
||||
//! be initialized to 1.0 by default
|
||||
virtual void Allocate(unsigned int num) {
|
||||
if (!rawData.empty())
|
||||
return; // return if already allocated
|
||||
|
||||
unsigned int m = num * dims;
|
||||
rawData.reserve(m + (m >> 2u)); // 25% as extra storage for VMADs
|
||||
rawData.resize(m);
|
||||
|
||||
for (aiColor4D *p = (aiColor4D *)&rawData[0]; p < (aiColor4D *)&rawData[m - 1]; ++p)
|
||||
p->a = 1.f;
|
||||
|
||||
abAssigned.resize(num, false);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Represents an extra vertex UV channel
|
||||
*/
|
||||
struct UVChannel : public VMapEntry {
|
||||
UVChannel() :
|
||||
VMapEntry(2) {}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Represents a weight map
|
||||
*/
|
||||
struct WeightChannel : public VMapEntry {
|
||||
WeightChannel() :
|
||||
VMapEntry(1) {}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Represents a vertex-normals channel (MODO extension)
|
||||
*/
|
||||
struct NormalChannel : public VMapEntry {
|
||||
NormalChannel() :
|
||||
VMapEntry(3) {}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file texture
|
||||
*/
|
||||
struct Texture {
|
||||
// we write the enum values out here to make debugging easier ...
|
||||
enum BlendType {
|
||||
Normal = 0,
|
||||
Subtractive = 1,
|
||||
Difference = 2,
|
||||
Multiply = 3,
|
||||
Divide = 4,
|
||||
Alpha = 5,
|
||||
TextureDispl = 6,
|
||||
Additive = 7
|
||||
};
|
||||
|
||||
enum MappingMode {
|
||||
Planar = 0,
|
||||
Cylindrical = 1,
|
||||
Spherical = 2,
|
||||
Cubic = 3,
|
||||
FrontProjection = 4,
|
||||
UV = 5
|
||||
};
|
||||
|
||||
enum Axes {
|
||||
AXIS_X = 0,
|
||||
AXIS_Y = 1,
|
||||
AXIS_Z = 2
|
||||
};
|
||||
|
||||
enum Wrap {
|
||||
RESET = 0,
|
||||
REPEAT = 1,
|
||||
MIRROR = 2,
|
||||
EDGE = 3
|
||||
};
|
||||
|
||||
Texture() :
|
||||
mClipIdx(UINT_MAX), mStrength(1.0f), type(), mUVChannelIndex("unknown"), mRealUVIndex(UINT_MAX), enabled(true), blendType(Additive), bCanUse(true), mapMode(UV), majorAxis(AXIS_X), wrapAmountH(1.0f), wrapAmountW(1.0f), wrapModeWidth(REPEAT), wrapModeHeight(REPEAT), ordinal("\x00") {}
|
||||
|
||||
//! File name of the texture
|
||||
std::string mFileName;
|
||||
|
||||
//! Clip index
|
||||
unsigned int mClipIdx;
|
||||
|
||||
//! Strength of the texture - blend factor
|
||||
float mStrength;
|
||||
|
||||
uint32_t type; // type of the texture
|
||||
|
||||
//! Name of the corresponding UV channel
|
||||
std::string mUVChannelIndex;
|
||||
unsigned int mRealUVIndex;
|
||||
|
||||
//! is the texture enabled?
|
||||
bool enabled;
|
||||
|
||||
//! blend type
|
||||
BlendType blendType;
|
||||
|
||||
//! are we able to use the texture?
|
||||
bool bCanUse;
|
||||
|
||||
//! mapping mode
|
||||
MappingMode mapMode;
|
||||
|
||||
//! major axis for planar, cylindrical, spherical projections
|
||||
Axes majorAxis;
|
||||
|
||||
//! wrap amount for cylindrical and spherical projections
|
||||
float wrapAmountH, wrapAmountW;
|
||||
|
||||
//! wrapping mode for the texture
|
||||
Wrap wrapModeWidth, wrapModeHeight;
|
||||
|
||||
//! ordinal string of the texture
|
||||
std::string ordinal;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file clip
|
||||
*/
|
||||
struct Clip {
|
||||
enum Type {
|
||||
STILL,
|
||||
SEQ,
|
||||
REF,
|
||||
UNSUPPORTED
|
||||
} type;
|
||||
|
||||
Clip() :
|
||||
type(UNSUPPORTED), clipRef(), idx(0), negate(false) {}
|
||||
|
||||
//! path to the base texture -
|
||||
std::string path;
|
||||
|
||||
//! reference to another CLIP
|
||||
unsigned int clipRef;
|
||||
|
||||
//! index of the clip
|
||||
unsigned int idx;
|
||||
|
||||
//! Negate the clip?
|
||||
bool negate;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file shader
|
||||
*
|
||||
* Later
|
||||
*/
|
||||
struct Shader {
|
||||
Shader() :
|
||||
ordinal("\x00"), functionName("unknown"), enabled(true) {}
|
||||
|
||||
std::string ordinal;
|
||||
std::string functionName;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
typedef std::list<Texture> TextureList;
|
||||
typedef std::list<Shader> ShaderList;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file surface (= material)
|
||||
*/
|
||||
struct Surface {
|
||||
Surface() :
|
||||
mColor(0.78431f, 0.78431f, 0.78431f), bDoubleSided(false), mDiffuseValue(1.f), mSpecularValue(0.f), mTransparency(0.f), mGlossiness(0.4f), mLuminosity(0.f), mColorHighlights(0.f), mMaximumSmoothAngle(0.f) // 0 == not specified, no smoothing
|
||||
,
|
||||
mVCMap(),
|
||||
mVCMapType(AI_LWO_RGBA),
|
||||
mIOR(1.f) // vakuum
|
||||
,
|
||||
mBumpIntensity(1.f),
|
||||
mWireframe(false),
|
||||
mAdditiveTransparency(0.f) {}
|
||||
|
||||
//! Name of the surface
|
||||
std::string mName;
|
||||
|
||||
//! Color of the surface
|
||||
aiColor3D mColor;
|
||||
|
||||
//! true for two-sided materials
|
||||
bool bDoubleSided;
|
||||
|
||||
//! Various material parameters
|
||||
float mDiffuseValue, mSpecularValue, mTransparency, mGlossiness, mLuminosity, mColorHighlights;
|
||||
|
||||
//! Maximum angle between two adjacent triangles
|
||||
//! that they can be smoothed - in degrees
|
||||
float mMaximumSmoothAngle;
|
||||
|
||||
//! Vertex color map to be used to color the surface
|
||||
std::string mVCMap;
|
||||
uint32_t mVCMapType;
|
||||
|
||||
//! Names of the special shaders to be applied to the surface
|
||||
ShaderList mShaders;
|
||||
|
||||
//! Textures - the first entry in the list is evaluated first
|
||||
TextureList mColorTextures, // color textures are added to both diffuse and specular texture stacks
|
||||
mDiffuseTextures,
|
||||
mSpecularTextures,
|
||||
mOpacityTextures,
|
||||
mBumpTextures,
|
||||
mGlossinessTextures,
|
||||
mReflectionTextures;
|
||||
|
||||
//! Index of refraction
|
||||
float mIOR;
|
||||
|
||||
//! Bump intensity scaling
|
||||
float mBumpIntensity;
|
||||
|
||||
//! Wireframe flag
|
||||
bool mWireframe;
|
||||
|
||||
//! Intensity of additive blending
|
||||
float mAdditiveTransparency;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO node
|
||||
*/
|
||||
struct Node {
|
||||
// Name of node
|
||||
std::string mName;
|
||||
|
||||
// RefName of node
|
||||
std::string mRefName;
|
||||
|
||||
// Ref FileName
|
||||
std::string fileName;
|
||||
};
|
||||
|
||||
struct NodeAttribute {
|
||||
//! Color of the surface
|
||||
aiColor3D mColor;
|
||||
|
||||
//! true for two-sided materials
|
||||
bool bDoubleSided;
|
||||
|
||||
//! Various material parameters
|
||||
float mDiffuseValue, mSpecularValue, mTransparency, mGlossiness, mLuminosity, mColorHighlights;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length, name, size) \
|
||||
if (length < size) { \
|
||||
throw DeadlyImportError("LWO: " #name " chunk is too small"); \
|
||||
}
|
||||
|
||||
// some typedefs ... to make life with loader monsters like this easier
|
||||
typedef std::vector<aiVector3D> PointList;
|
||||
typedef std::vector<LWO::Face> FaceList;
|
||||
typedef std::vector<LWO::Surface> SurfaceList;
|
||||
typedef std::vector<std::string> TagList;
|
||||
typedef std::vector<unsigned int> TagMappingTable;
|
||||
typedef std::vector<unsigned int> ReferrerList;
|
||||
typedef std::vector<WeightChannel> WeightChannelList;
|
||||
typedef std::vector<VColorChannel> VColorChannelList;
|
||||
typedef std::vector<UVChannel> UVChannelList;
|
||||
typedef std::vector<Clip> ClipList;
|
||||
typedef std::vector<Envelope> EnvelopeList;
|
||||
typedef std::vector<unsigned int> SortedRep;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Represents a layer in the file
|
||||
*/
|
||||
struct Layer {
|
||||
Layer() :
|
||||
mFaceIDXOfs(0), mPointIDXOfs(0), mParent(0x0), mIndex(0xffff), skip(false) {}
|
||||
|
||||
/** Temporary point list from the file */
|
||||
PointList mTempPoints;
|
||||
|
||||
/** Lists for every point the index of another point
|
||||
that has been copied from *this* point or UINT_MAX if
|
||||
no copy of the point has been made */
|
||||
ReferrerList mPointReferrers;
|
||||
|
||||
/** Weight channel list from the file */
|
||||
WeightChannelList mWeightChannels;
|
||||
|
||||
/** Subdivision weight channel list from the file */
|
||||
WeightChannelList mSWeightChannels;
|
||||
|
||||
/** Vertex color list from the file */
|
||||
VColorChannelList mVColorChannels;
|
||||
|
||||
/** UV channel list from the file */
|
||||
UVChannelList mUVChannels;
|
||||
|
||||
/** Normal vector channel from the file */
|
||||
NormalChannel mNormals;
|
||||
|
||||
/** Temporary face list from the file*/
|
||||
FaceList mFaces;
|
||||
|
||||
/** Current face indexing offset from the beginning of the buffers*/
|
||||
unsigned int mFaceIDXOfs;
|
||||
|
||||
/** Current point indexing offset from the beginning of the buffers*/
|
||||
unsigned int mPointIDXOfs;
|
||||
|
||||
/** Parent index */
|
||||
uint16_t mParent;
|
||||
|
||||
/** Index of the layer */
|
||||
uint16_t mIndex;
|
||||
|
||||
/** Name of the layer */
|
||||
std::string mName;
|
||||
|
||||
/** Pivot point of the layer */
|
||||
aiVector3D mPivot;
|
||||
|
||||
/** Skip this layer? */
|
||||
bool skip;
|
||||
};
|
||||
|
||||
typedef std::list<LWO::Layer> LayerList;
|
||||
|
||||
} // namespace LWO
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !! AI_LWO_FILEDATA_INCLUDED
|
||||
1618
Engine/lib/assimp/code/AssetLib/LWO/LWOLoader.cpp
Normal file
1618
Engine/lib/assimp/code/AssetLib/LWO/LWOLoader.cpp
Normal file
File diff suppressed because it is too large
Load diff
500
Engine/lib/assimp/code/AssetLib/LWO/LWOLoader.h
Normal file
500
Engine/lib/assimp/code/AssetLib/LWO/LWOLoader.h
Normal file
|
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file Declaration of the LWO importer class. */
|
||||
#pragma once
|
||||
#ifndef AI_LWOLOADER_H_INCLUDED
|
||||
#define AI_LWOLOADER_H_INCLUDED
|
||||
|
||||
#include "LWOFileData.h"
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
struct aiTexture;
|
||||
struct aiNode;
|
||||
struct aiMaterial;
|
||||
|
||||
namespace Assimp {
|
||||
using namespace LWO;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Class to load LWO files.
|
||||
*
|
||||
* @note Methods named "xxxLWO2[xxx]" are used with the newer LWO2 format.
|
||||
* Methods named "xxxLWOB[xxx]" are used with the older LWOB format.
|
||||
* Methods named "xxxLWO[xxx]" are used with both formats.
|
||||
* Methods named "xxx" are used to preprocess the loaded data -
|
||||
* they aren't specific to one format version
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
class LWOImporter : public BaseImporter {
|
||||
public:
|
||||
LWOImporter();
|
||||
~LWOImporter() override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
*/
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
|
||||
bool checkSig) const override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ReadFile().
|
||||
* The function is a request to the importer to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer *pImp) override;
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------
|
||||
// Get list of supported extensions
|
||||
const aiImporterDesc *GetInfo() const override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Imports the given file into the given scene structure.
|
||||
* See BaseImporter::InternReadFile() for details
|
||||
*/
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene,
|
||||
IOSystem *pIOHandler) override;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a LWO file in the older LWOB format (LW < 6)
|
||||
*/
|
||||
void LoadLWOBFile();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a LWO file in the newer LWO2 format (LW >= 6)
|
||||
*/
|
||||
void LoadLWO2File();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parsing functions used for all file format versions
|
||||
*/
|
||||
inline void GetS0(std::string &out, unsigned int max);
|
||||
inline float GetF4();
|
||||
inline float GetF8();
|
||||
inline uint64_t GetU8();
|
||||
inline uint32_t GetU4();
|
||||
inline uint16_t GetU2();
|
||||
inline uint8_t GetU1();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a surface chunk from an LWOB file
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
*/
|
||||
void LoadLWOBSurface(unsigned int size);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a surface chunk from an LWO2 file
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
*/
|
||||
void LoadLWO2Surface(unsigned int size);
|
||||
void LoadLWO3Surface(unsigned int size);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a texture block from a LWO2 file.
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
* @param head Header of the SUF.BLOK header
|
||||
*/
|
||||
void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head,
|
||||
unsigned int size);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a shader block from a LWO2 file.
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
* @param head Header of the SUF.BLOK header
|
||||
*/
|
||||
void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader *head,
|
||||
unsigned int size);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads an image map from a LWO2 file
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
* @param tex Texture object to be filled
|
||||
*/
|
||||
void LoadLWO2ImageMap(unsigned int size, LWO::Texture &tex);
|
||||
void LoadLWO2Gradient(unsigned int size, LWO::Texture &tex);
|
||||
void LoadLWO2Procedural(unsigned int size, LWO::Texture &tex);
|
||||
|
||||
// loads the header - used by thethree functions above
|
||||
void LoadLWO2TextureHeader(unsigned int size, LWO::Texture &tex);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads the LWO tag list from the file
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
*/
|
||||
void LoadLWOTags(unsigned int size);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load polygons from a POLS chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWO2Polygons(unsigned int length);
|
||||
void LoadLWOBPolygons(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load polygon tags from a PTAG chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWO2PolygonTags(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load a vertex map from a VMAP/VMAD chunk
|
||||
* @param length Size of the chunk
|
||||
* @param perPoly Operate on per-polygon base?
|
||||
*/
|
||||
void LoadLWO2VertexMap(unsigned int length, bool perPoly);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load polygons from a PNTS chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWOPoints(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load a clip from a CLIP chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWO2Clip(unsigned int length);
|
||||
void LoadLWO3Clip(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load an envelope from an EVL chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWO2Envelope(unsigned int length);
|
||||
void LoadLWO3Envelope(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load an nodal blocks from surface form
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadNodalBlocks(unsigned int length);
|
||||
void LoadNodes(unsigned int length);
|
||||
void LoadNodeTag(unsigned int length);
|
||||
void LoadNodeData(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Count vertices and faces in a LWOB/LWO2 file
|
||||
*/
|
||||
void CountVertsAndFacesLWO2(unsigned int &verts,
|
||||
unsigned int &faces,
|
||||
uint16_t *&cursor,
|
||||
const uint16_t *const end,
|
||||
unsigned int max = UINT_MAX);
|
||||
|
||||
void CountVertsAndFacesLWOB(unsigned int &verts,
|
||||
unsigned int &faces,
|
||||
LE_NCONST uint16_t *&cursor,
|
||||
const uint16_t *const end,
|
||||
unsigned int max = UINT_MAX);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Read vertices and faces in a LWOB/LWO2 file
|
||||
*/
|
||||
void CopyFaceIndicesLWO2(LWO::FaceList::iterator &it,
|
||||
uint16_t *&cursor,
|
||||
const uint16_t *const end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void CopyFaceIndicesLWOB(LWO::FaceList::iterator &it,
|
||||
LE_NCONST uint16_t *&cursor,
|
||||
const uint16_t *const end,
|
||||
unsigned int max = UINT_MAX);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Resolve the tag and surface lists that have been loaded.
|
||||
* Generates the mMapping table.
|
||||
*/
|
||||
void ResolveTags();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Resolve the clip list that has been loaded.
|
||||
* Replaces clip references with real clips.
|
||||
*/
|
||||
void ResolveClips();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Add a texture list to an output material description.
|
||||
*
|
||||
* @param pcMat Output material
|
||||
* @param in Input texture list
|
||||
* @param type Type identifier of the texture list
|
||||
*/
|
||||
bool HandleTextures(aiMaterial *pcMat, const TextureList &in,
|
||||
aiTextureType type);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Adjust a texture path
|
||||
*/
|
||||
void AdjustTexturePath(std::string &out);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Convert a LWO surface description to an ASSIMP material
|
||||
*/
|
||||
void ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Get a list of all UV/VC channels required by a specific surface.
|
||||
*
|
||||
* @param surf Working surface
|
||||
* @param layer Working layer
|
||||
* @param out Output list. The members are indices into the
|
||||
* UV/VC channel lists of the layer
|
||||
*/
|
||||
void FindUVChannels(/*const*/ LWO::Surface &surf,
|
||||
LWO::SortedRep &sorted,
|
||||
/*const*/ LWO::Layer &layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
char FindUVChannels(LWO::TextureList &list,
|
||||
LWO::Layer &layer, LWO::UVChannel &uv, unsigned int next);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void FindVCChannels(const LWO::Surface &surf,
|
||||
LWO::SortedRep &sorted,
|
||||
const LWO::Layer &layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Generate the final node graph
|
||||
* Unused nodes are deleted.
|
||||
* @param apcNodes Flat list of nodes
|
||||
*/
|
||||
void GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Add children to a node
|
||||
* @param node Node to become a father
|
||||
* @param parent Index of the node
|
||||
* @param apcNodes Flat list of nodes - used nodes are set to nullptr.
|
||||
*/
|
||||
void AddChildren(aiNode *node, uint16_t parent,
|
||||
std::vector<aiNode *> &apcNodes);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Read a variable sized integer
|
||||
* @param inout Input and output buffer
|
||||
*/
|
||||
int ReadVSizedIntLWO2(uint8_t *&inout);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Assign a value from a VMAP to a vertex and all vertices
|
||||
* attached to it.
|
||||
* @param base VMAP destination data
|
||||
* @param numRead Number of float's to be read
|
||||
* @param idx Absolute index of the first vertex
|
||||
* @param data Value of the VMAP to be assigned - read numRead
|
||||
* floats from this array.
|
||||
*/
|
||||
void DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead,
|
||||
unsigned int idx, float *data);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Compute normal vectors for a mesh
|
||||
* @param mesh Input mesh
|
||||
* @param smoothingGroups Smoothing-groups-per-face array
|
||||
* @param surface Surface for the mesh
|
||||
*/
|
||||
void ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &smoothingGroups,
|
||||
const LWO::Surface &surface);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Setup a new texture after the corresponding chunk was
|
||||
* encountered in the file.
|
||||
* @param list Texture list
|
||||
* @param size Maximum number of bytes to be read
|
||||
* @return Pointer to new texture
|
||||
*/
|
||||
LWO::Texture *SetupNewTextureLWOB(LWO::TextureList &list,
|
||||
unsigned int size);
|
||||
|
||||
protected:
|
||||
/** true if the file is a LWO2 file*/
|
||||
bool mIsLWO2;
|
||||
|
||||
/** true if the file is a LXOB file*/
|
||||
bool mIsLXOB;
|
||||
|
||||
bool mIsLWO3;
|
||||
|
||||
/** Temporary list of layers from the file */
|
||||
LayerList *mLayers;
|
||||
|
||||
/** Pointer to the current layer */
|
||||
LWO::Layer *mCurLayer;
|
||||
|
||||
/** Temporary tag list from the file */
|
||||
TagList *mTags;
|
||||
|
||||
/** Mapping table to convert from tag to surface indices.
|
||||
UINT_MAX indicates that a no corresponding surface is available */
|
||||
TagMappingTable *mMapping;
|
||||
|
||||
/** Temporary surface list from the file */
|
||||
SurfaceList *mSurfaces;
|
||||
|
||||
/** Temporary clip list from the file */
|
||||
ClipList mClips;
|
||||
|
||||
/** Temporary envelope list from the file */
|
||||
EnvelopeList mEnvelopes;
|
||||
|
||||
/** file buffer */
|
||||
uint8_t *mFileBuffer;
|
||||
|
||||
/** Size of the file, in bytes */
|
||||
unsigned int fileSize;
|
||||
|
||||
/** Output scene */
|
||||
aiScene *mScene;
|
||||
|
||||
/** Configuration option: speed flag set? */
|
||||
bool configSpeedFlag;
|
||||
|
||||
/** Configuration option: index of layer to be loaded */
|
||||
unsigned int configLayerIndex;
|
||||
|
||||
/** Configuration option: name of layer to be loaded */
|
||||
std::string configLayerName;
|
||||
|
||||
/** True if we have a named layer */
|
||||
bool hasNamedLayer;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline float LWOImporter::GetF4() {
|
||||
float f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
inline float LWOImporter::GetF8() {
|
||||
double f;
|
||||
::memcpy(&f, mFileBuffer, 8);
|
||||
mFileBuffer += 8;
|
||||
AI_LSWAP8(f);
|
||||
return (float)f;
|
||||
}
|
||||
|
||||
inline uint64_t LWOImporter::GetU8() {
|
||||
uint64_t f;
|
||||
::memcpy(&f, mFileBuffer, 8);
|
||||
mFileBuffer += 8;
|
||||
AI_LSWAP8(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint32_t LWOImporter::GetU4() {
|
||||
uint32_t f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint16_t LWOImporter::GetU2() {
|
||||
uint16_t f;
|
||||
::memcpy(&f, mFileBuffer, 2);
|
||||
mFileBuffer += 2;
|
||||
AI_LSWAP2(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint8_t LWOImporter::GetU1() {
|
||||
return *mFileBuffer++;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline int LWOImporter::ReadVSizedIntLWO2(uint8_t *&inout) {
|
||||
int i;
|
||||
int c = *inout;
|
||||
inout++;
|
||||
if (c != 0xFF) {
|
||||
i = c << 8;
|
||||
c = *inout;
|
||||
inout++;
|
||||
i |= c;
|
||||
} else {
|
||||
c = *inout;
|
||||
inout++;
|
||||
i = c << 16;
|
||||
c = *inout;
|
||||
inout++;
|
||||
i |= c << 8;
|
||||
c = *inout;
|
||||
inout++;
|
||||
i |= c;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline void LWOImporter::GetS0(std::string &out, unsigned int max) {
|
||||
unsigned int iCursor = 0;
|
||||
const char *sz = (const char *)mFileBuffer;
|
||||
while (*mFileBuffer) {
|
||||
if (++iCursor > max) {
|
||||
ASSIMP_LOG_WARN("LWO: Invalid file, string is is too long");
|
||||
break;
|
||||
}
|
||||
++mFileBuffer;
|
||||
}
|
||||
size_t len = (size_t)((const char *)mFileBuffer - sz);
|
||||
out = std::string(sz, len);
|
||||
mFileBuffer += (len & 0x1 ? 1 : 2);
|
||||
}
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_LWOIMPORTER_H_INCLUDED
|
||||
1155
Engine/lib/assimp/code/AssetLib/LWO/LWOMaterial.cpp
Normal file
1155
Engine/lib/assimp/code/AssetLib/LWO/LWOMaterial.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue