mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Merge branch 'master' into shadersystem
Conflicts: components/nifogre/ogre_nif_loader.cpp
This commit is contained in:
commit
7d5b94709d
51 changed files with 2237 additions and 1782 deletions
|
@ -20,6 +20,12 @@ set (OPENMW_VERSION_RELEASE 0)
|
||||||
|
|
||||||
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
|
||||||
|
# Debug suffix for plugins
|
||||||
|
set(DEBUG_SUFFIX "")
|
||||||
|
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||||
|
set(DEBUG_SUFFIX "_d")
|
||||||
|
endif()
|
||||||
|
|
||||||
# doxygen main page
|
# doxygen main page
|
||||||
|
|
||||||
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
|
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
|
||||||
|
|
|
@ -39,7 +39,7 @@ add_openmw_dir (mwscript
|
||||||
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
|
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
|
||||||
guiextensions soundextensions skyextensions statsextensions containerextensions
|
guiextensions soundextensions skyextensions statsextensions containerextensions
|
||||||
aiextensions controlextensions extensions globalscripts ref dialogueextensions
|
aiextensions controlextensions extensions globalscripts ref dialogueextensions
|
||||||
animationextensions
|
animationextensions transformationextensions
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
|
|
|
@ -178,6 +178,10 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
||||||
|
|
||||||
|
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
|
||||||
|
|
||||||
|
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z) = 0;
|
||||||
|
|
||||||
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
|
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
|
||||||
const = 0;
|
const = 0;
|
||||||
///< Convert cell numbers to position.
|
///< Convert cell numbers to position.
|
||||||
|
|
|
@ -125,10 +125,14 @@ namespace MWClass
|
||||||
|
|
||||||
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
||||||
{
|
{
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
||||||
ptr.get<ESM::NPC>();
|
ptr.get<ESM::NPC>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::string headID = ref->base->head;
|
std::string headID = ref->base->head;
|
||||||
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||||
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||||
|
@ -138,6 +142,7 @@ namespace MWClass
|
||||||
smodel = "meshes\\base_animkna.nif";
|
smodel = "meshes\\base_animkna.nif";
|
||||||
physics.insertActorPhysics(ptr, smodel);
|
physics.insertActorPhysics(ptr, smodel);
|
||||||
|
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
|
MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,4 +347,11 @@ namespace MWClass
|
||||||
|
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
|
||||||
|
{
|
||||||
|
y = 0;
|
||||||
|
x = 0;
|
||||||
|
std::cout << "dfdfdfdfnzdofnmqsldgnmqskdhblqkdbv lqksdf";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace MWClass
|
||||||
///< Returns total weight of objects inside this object (including modifications from magic
|
///< Returns total weight of objects inside this object (including modifications from magic
|
||||||
/// effects). Throws an exception, if the object can't hold other objects.
|
/// effects). Throws an exception, if the object can't hold other objects.
|
||||||
|
|
||||||
|
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -706,7 +706,7 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (const Compiler::SourceException& error)
|
catch (const Compiler::SourceException& /* error */)
|
||||||
{
|
{
|
||||||
// error has already been reported via error handler
|
// error has already been reported via error handler
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& /* e */)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,9 @@ namespace MWGui
|
||||||
&& (type != typeid(ESM::Potion).name()))
|
&& (type != typeid(ESM::Potion).name()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MWWorld::Class::get(object).getName(object) == "") // objects without name presented to user can never be picked up
|
||||||
|
return;
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1);
|
MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1);
|
||||||
|
|
|
@ -12,6 +12,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReferenceInterface::~ReferenceInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ReferenceInterface::checkReferenceAvailable()
|
void ReferenceInterface::checkReferenceAvailable()
|
||||||
{
|
{
|
||||||
if (mPtr.isEmpty())
|
if (mPtr.isEmpty())
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReferenceInterface();
|
ReferenceInterface();
|
||||||
|
virtual ~ReferenceInterface();
|
||||||
|
|
||||||
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ void ToolTips::onFrame(float frameDuration)
|
||||||
{
|
{
|
||||||
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception /* & e */)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,4 +165,9 @@ op 0x2000160: SetFlee
|
||||||
op 0x2000161: SetFlee, explicit reference
|
op 0x2000161: SetFlee, explicit reference
|
||||||
op 0x2000162: SetAlarm
|
op 0x2000162: SetAlarm
|
||||||
op 0x2000163: SetAlarm, explicit reference
|
op 0x2000163: SetAlarm, explicit reference
|
||||||
opcodes 0x2000164-0x3ffffff unused
|
op 0x2000164: SetScale
|
||||||
|
op 0x2000165: SetScale, explicit reference
|
||||||
|
op 0x2000166: SetAngle
|
||||||
|
op 0x2000167: SetAngle, explicit reference
|
||||||
|
opcodes 0x2000168-0x3ffffff unused
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "controlextensions.hpp"
|
#include "controlextensions.hpp"
|
||||||
#include "dialogueextensions.hpp"
|
#include "dialogueextensions.hpp"
|
||||||
#include "animationextensions.hpp"
|
#include "animationextensions.hpp"
|
||||||
|
#include "transformationextensions.hpp"
|
||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,7 @@ namespace MWScript
|
||||||
Control::registerExtensions (extensions);
|
Control::registerExtensions (extensions);
|
||||||
Dialogue::registerExtensions (extensions);
|
Dialogue::registerExtensions (extensions);
|
||||||
Animation::registerExtensions (extensions);
|
Animation::registerExtensions (extensions);
|
||||||
|
Transformation::registerExtensions (extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -47,5 +49,6 @@ namespace MWScript
|
||||||
Control::installOpcodes (interpreter);
|
Control::installOpcodes (interpreter);
|
||||||
Dialogue::installOpcodes (interpreter);
|
Dialogue::installOpcodes (interpreter);
|
||||||
Animation::installOpcodes (interpreter);
|
Animation::installOpcodes (interpreter);
|
||||||
|
Transformation::installOpcodes (interpreter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,6 +505,7 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const int numberOfAttributes = 8;
|
const int numberOfAttributes = 8;
|
||||||
|
|
||||||
const int opcodeGetAttribute = 0x2000027;
|
const int opcodeGetAttribute = 0x2000027;
|
||||||
|
|
140
apps/openmw/mwscript/transformationextensions.cpp
Normal file
140
apps/openmw/mwscript/transformationextensions.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include <components/esm_store/store.hpp>
|
||||||
|
|
||||||
|
#include <components/compiler/extensions.hpp>
|
||||||
|
|
||||||
|
#include <components/interpreter/interpreter.hpp>
|
||||||
|
#include <components/interpreter/runtime.hpp>
|
||||||
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "interpretercontext.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
|
#include "OgreSceneNode.h"
|
||||||
|
|
||||||
|
namespace MWScript
|
||||||
|
{
|
||||||
|
namespace Transformation
|
||||||
|
{
|
||||||
|
template<class R>
|
||||||
|
class OpSetScale : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
Interpreter::Type_Float scale = runtime[0].mFloat;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->scaleObject(ptr,scale);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpGetScale : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
runtime.push(ptr.getCellRef().scale);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpSetAngle : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
Interpreter::Type_Float angle = runtime[0].mFloat;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees();
|
||||||
|
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
|
||||||
|
float az = Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees();
|
||||||
|
|
||||||
|
if(axis == "X")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az);
|
||||||
|
}
|
||||||
|
if(axis == "Y")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az);
|
||||||
|
}
|
||||||
|
if(axis == "Z")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpGetAngle : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
if(axis == "X")
|
||||||
|
{
|
||||||
|
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees());
|
||||||
|
}
|
||||||
|
if(axis == "Y")
|
||||||
|
{
|
||||||
|
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees());
|
||||||
|
}
|
||||||
|
if(axis == "Z")
|
||||||
|
{
|
||||||
|
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int opcodeSetScale = 0x2000164;
|
||||||
|
const int opcodeSetScaleExplicit = 0x2000165;
|
||||||
|
const int opcodeSetAngle = 0x2000166;
|
||||||
|
const int opcodeSetAngleExplicit = 0x2000167;
|
||||||
|
const int opcodeGetScale = 0x2000168;
|
||||||
|
const int opcodeGetScaleExplicit = 0x2000169;
|
||||||
|
const int opcodeGetAngle = 0x200016a;
|
||||||
|
const int opcodeGetAngleExplicit = 0x200016b;
|
||||||
|
|
||||||
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
|
{
|
||||||
|
extensions.registerInstruction("setscale","f",opcodeSetScale,opcodeSetScaleExplicit);
|
||||||
|
extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit);
|
||||||
|
extensions.registerInstruction("setangle","Sf",opcodeSetAngle,opcodeSetAngleExplicit);
|
||||||
|
extensions.registerFunction("getangle",'f',"S",opcodeGetAngle,opcodeGetAngleExplicit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
{
|
||||||
|
interpreter.installSegment5(opcodeSetScale,new OpSetScale<ImplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeSetScaleExplicit,new OpSetScale<ExplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeSetAngle,new OpSetAngle<ImplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeSetAngleExplicit,new OpSetAngle<ExplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeGetScale,new OpGetScale<ImplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeGetScaleExplicit,new OpGetScale<ExplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeGetAngle,new OpGetAngle<ImplicitRef>);
|
||||||
|
interpreter.installSegment5(opcodeGetAngleExplicit,new OpGetAngle<ExplicitRef>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
apps/openmw/mwscript/transformationextensions.hpp
Normal file
25
apps/openmw/mwscript/transformationextensions.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef GAME_SCRIPT_TRANSFORMATIONEXTENSIONS_H
|
||||||
|
#define GAME_SCRIPT_TRANSFORMATIONEXTENSIONS_H
|
||||||
|
|
||||||
|
namespace Compiler
|
||||||
|
{
|
||||||
|
class Extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Interpreter
|
||||||
|
{
|
||||||
|
class Interpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWScript
|
||||||
|
{
|
||||||
|
/// \brief stats-related script functionality (creatures and NPCs)
|
||||||
|
namespace Transformation
|
||||||
|
{
|
||||||
|
void registerExtensions (Compiler::Extensions& extensions);
|
||||||
|
|
||||||
|
void installOpcodes (Interpreter::Interpreter& interpreter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -90,7 +90,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
if(devname.empty())
|
if(devname.empty())
|
||||||
throw;
|
throw;
|
||||||
std::cout <<"Failed to open device \""<<devname<<"\", trying default"<< std::endl;
|
std::cout <<"Failed to open device \""<<devname<<"\", trying default."<< std::endl << "The error given was: " << e.what() << std::endl;
|
||||||
mOutput->init();
|
mOutput->init();
|
||||||
Settings::Manager::setString("device", "Sound", "");
|
Settings::Manager::setString("device", "Sound", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellS
|
||||||
|
|
||||||
MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader)
|
MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader)
|
||||||
: mStore (store), mReader (reader),
|
: mStore (store), mReader (reader),
|
||||||
mIdCache (20, std::pair<std::string, Ptr::CellStore *> ("", 0)), /// \todo make cache size configurable
|
mIdCache (20, std::pair<std::string, Ptr::CellStore *> ("", (Ptr::CellStore*)0)), /// \todo make cache size configurable
|
||||||
mIdCacheIndex (0)
|
mIdCacheIndex (0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -194,4 +194,12 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Class::adjustScale(const MWWorld::Ptr& ptr,float& scale) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Class::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,6 +187,10 @@ namespace MWWorld
|
||||||
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
||||||
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
||||||
/// (default implementation: return empty string)
|
/// (default implementation: return empty string)
|
||||||
|
|
||||||
|
virtual void adjustScale(const MWWorld::Ptr& ptr,float& scale) const;
|
||||||
|
|
||||||
|
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,9 +165,6 @@ namespace MWWorld
|
||||||
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
|
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
|
||||||
iter!=actors.end(); ++iter)
|
iter!=actors.end(); ++iter)
|
||||||
{
|
{
|
||||||
OEngine::Physic::PhysicActor* act = mEngine->getCharacter(iter->first);
|
|
||||||
//if(iter->first == "player")
|
|
||||||
// std::cout << "This is player\n";
|
|
||||||
//dirty stuff to get the camera orientation. Must be changed!
|
//dirty stuff to get the camera orientation. Must be changed!
|
||||||
|
|
||||||
Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first);
|
Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first);
|
||||||
|
@ -177,46 +174,28 @@ namespace MWWorld
|
||||||
Ogre::Quaternion yawQuat = yawNode->getOrientation();
|
Ogre::Quaternion yawQuat = yawNode->getOrientation();
|
||||||
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
||||||
|
|
||||||
// unused
|
|
||||||
//Ogre::Quaternion both = yawQuat * pitchQuat;
|
|
||||||
|
|
||||||
playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
||||||
playerphysics->ps.viewangles.z = 0;
|
|
||||||
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90;
|
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90;
|
||||||
|
|
||||||
if(mFreeFly)
|
|
||||||
{
|
|
||||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
|
||||||
|
|
||||||
pm_ref.rightmove = -dir1.x;
|
|
||||||
pm_ref.forwardmove = dir1.z;
|
|
||||||
pm_ref.upmove = dir1.y;
|
|
||||||
|
|
||||||
|
|
||||||
//std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n";
|
|
||||||
//playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
|
||||||
//std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n";
|
|
||||||
dir = 0.07*(yawQuat*pitchQuat*dir1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
Ogre::Quaternion quat = yawNode->getOrientation();
|
Ogre::Quaternion quat = yawNode->getOrientation();
|
||||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
||||||
|
|
||||||
pm_ref.rightmove = -dir1.x;
|
pm_ref.rightmove = -iter->second.x;
|
||||||
pm_ref.forwardmove = dir1.z;
|
pm_ref.forwardmove = -iter->second.y;
|
||||||
pm_ref.upmove = dir1.y;
|
pm_ref.upmove = iter->second.z;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dir = 0.025*(quat*dir1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//set the walk direction
|
|
||||||
act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y));
|
|
||||||
}
|
|
||||||
mEngine->stepSimulation(dt);
|
mEngine->stepSimulation(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,10 +213,6 @@ namespace MWWorld
|
||||||
if(it->first == "player"){
|
if(it->first == "player"){
|
||||||
|
|
||||||
coord = playerphysics->ps.origin;
|
coord = playerphysics->ps.origin;
|
||||||
//std::cout << "ZCoord: " << coord.z << "\n";
|
|
||||||
//std::cout << "Coord" << coord << "\n";
|
|
||||||
//coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,6 +237,7 @@ namespace MWWorld
|
||||||
void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh,
|
void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh,
|
||||||
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
|
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
|
||||||
{
|
{
|
||||||
|
handleToMesh[handle] = mesh;
|
||||||
OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale);
|
OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale);
|
||||||
mEngine->addRigidBody(body);
|
mEngine->addRigidBody(body);
|
||||||
btTransform tr;
|
btTransform tr;
|
||||||
|
@ -316,15 +292,25 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
||||||
{
|
{
|
||||||
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
|
|
||||||
// start positions others than 0, 0, 0
|
|
||||||
act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
|
act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
|
||||||
}
|
}
|
||||||
|
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
|
||||||
|
{
|
||||||
|
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::scaleObject (const std::string& handle, float scale)
|
void PhysicsSystem::scaleObject (const std::string& handle, float scale)
|
||||||
{
|
{
|
||||||
|
if(handleToMesh.find(handle) != handleToMesh.end())
|
||||||
|
{
|
||||||
|
btTransform transform = mEngine->getRigidBody(handle)->getWorldTransform();
|
||||||
|
removeObject(handle);
|
||||||
|
|
||||||
|
Ogre::Quaternion quat = Ogre::Quaternion(transform.getRotation().getW(), transform.getRotation().getX(), transform.getRotation().getY(), transform.getRotation().getZ());
|
||||||
|
Ogre::Vector3 vec = Ogre::Vector3(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ());
|
||||||
|
addObject(handle, handleToMesh[handle], quat, scale, vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::toggleCollisionMode()
|
bool PhysicsSystem::toggleCollisionMode()
|
||||||
|
|
|
@ -72,6 +72,7 @@ namespace MWWorld
|
||||||
OEngine::Physic::PhysicEngine* mEngine;
|
OEngine::Physic::PhysicEngine* mEngine;
|
||||||
bool mFreeFly;
|
bool mFreeFly;
|
||||||
playerMove* playerphysics;
|
playerMove* playerphysics;
|
||||||
|
std::map<std::string, std::string> handleToMesh;
|
||||||
|
|
||||||
PhysicsSystem (const PhysicsSystem&);
|
PhysicsSystem (const PhysicsSystem&);
|
||||||
PhysicsSystem& operator= (const PhysicsSystem&);
|
PhysicsSystem& operator= (const PhysicsSystem&);
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include "../mwmechanics/drawstate.hpp"
|
#include "../mwmechanics/drawstate.hpp"
|
||||||
|
|
||||||
|
#undef DrawState // How did this get defined again?
|
||||||
|
// Maybe it's defined by default in every file for windows?
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
class World;
|
class World;
|
||||||
|
|
|
@ -597,6 +597,31 @@ namespace MWWorld
|
||||||
mPhysics->moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
|
mPhysics->moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::scaleObject (const Ptr& ptr, float scale)
|
||||||
|
{
|
||||||
|
MWWorld::Class::get(ptr).adjustScale(ptr,scale);
|
||||||
|
|
||||||
|
ptr.getCellRef().scale = scale;
|
||||||
|
//scale = scale/ptr.getRefData().getBaseNode()->getScale().x;
|
||||||
|
ptr.getRefData().getBaseNode()->setScale(scale,scale,scale);
|
||||||
|
mPhysics->scaleObject( ptr.getRefData().getHandle(), scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::rotateObject (const Ptr& ptr,float x,float y,float z)
|
||||||
|
{
|
||||||
|
MWWorld::Class::get(ptr).adjustRotation(ptr,x,y,z);
|
||||||
|
|
||||||
|
ptr.getRefData().getPosition().rot[0] = Ogre::Degree(x).valueRadians();
|
||||||
|
ptr.getRefData().getPosition().rot[1] = Ogre::Degree(y).valueRadians();
|
||||||
|
ptr.getRefData().getPosition().rot[2] = Ogre::Degree(z).valueRadians();
|
||||||
|
|
||||||
|
Ogre::Quaternion rotx(Ogre::Degree(x),Ogre::Vector3::UNIT_X);
|
||||||
|
Ogre::Quaternion roty(Ogre::Degree(y),Ogre::Vector3::UNIT_Y);
|
||||||
|
Ogre::Quaternion rotz(Ogre::Degree(z),Ogre::Vector3::UNIT_Z);
|
||||||
|
ptr.getRefData().getBaseNode()->setOrientation(rotz*roty*rotx);
|
||||||
|
mPhysics->rotateObject(ptr.getRefData().getHandle(),ptr.getRefData().getBaseNode()->getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
|
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
|
||||||
{
|
{
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
|
|
|
@ -188,7 +188,7 @@ namespace MWWorld
|
||||||
virtual bool toggleSky();
|
virtual bool toggleSky();
|
||||||
///< \return Resulting mode
|
///< \return Resulting mode
|
||||||
|
|
||||||
virtual void changeWeather (const std::string& region, const unsigned int id);
|
virtual void changeWeather (const std::string& region, unsigned int id);
|
||||||
|
|
||||||
virtual int getCurrentWeather() const;
|
virtual int getCurrentWeather() const;
|
||||||
|
|
||||||
|
@ -219,6 +219,10 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual void moveObject (const Ptr& ptr, float x, float y, float z);
|
virtual void moveObject (const Ptr& ptr, float x, float y, float z);
|
||||||
|
|
||||||
|
virtual void scaleObject (const Ptr& ptr, float scale);
|
||||||
|
|
||||||
|
virtual void rotateObject (const Ptr& ptr,float x,float y,float z);
|
||||||
|
|
||||||
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
|
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
|
||||||
const;
|
const;
|
||||||
///< Convert cell numbers to position.
|
///< Convert cell numbers to position.
|
||||||
|
|
|
@ -73,14 +73,16 @@ class DirArchive: public Ogre::FileSystemArchive
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
String passed = filename;
|
String passed = filename;
|
||||||
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
|
||||||
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
|
||||||
|| filename.at(filename.length() - 1) == '|')
|
|
||||||
{
|
|
||||||
passed = filename.substr(0, filename.length() - 2);
|
|
||||||
}
|
|
||||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||||
passed = filename.substr(0, filename.length() - 6);
|
passed = filename.substr(0, filename.length() - 6);
|
||||||
|
else if(filename.at(filename.length() - 2) == '"')
|
||||||
|
passed = filename.substr(0, filename.length() - 9);
|
||||||
|
else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||||
|
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||||
|
|| filename.at(filename.length() - 1) == '|')
|
||||||
|
passed = filename.substr(0, filename.length() - 2);
|
||||||
|
|
||||||
|
|
||||||
copy = passed;
|
copy = passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,14 +228,16 @@ public:
|
||||||
BSAFile *narc = (BSAFile*)&arc;
|
BSAFile *narc = (BSAFile*)&arc;
|
||||||
|
|
||||||
String passed = filename;
|
String passed = filename;
|
||||||
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
|
||||||
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
|
||||||
|| filename.at(filename.length() - 1) == '|')
|
|
||||||
{
|
|
||||||
passed = filename.substr(0, filename.length() - 2);
|
|
||||||
}
|
|
||||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||||
passed = filename.substr(0, filename.length() - 6);
|
passed = filename.substr(0, filename.length() - 6);
|
||||||
|
else if(filename.at(filename.length() - 2) == '"')
|
||||||
|
passed = filename.substr(0, filename.length() - 9);
|
||||||
|
else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||||
|
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||||
|
|| filename.at(filename.length() - 1) == '|')
|
||||||
|
passed = filename.substr(0, filename.length() - 2);
|
||||||
|
|
||||||
|
|
||||||
// Open the file
|
// Open the file
|
||||||
StreamPtr strm = narc->getFile(passed.c_str());
|
StreamPtr strm = narc->getFile(passed.c_str());
|
||||||
|
|
||||||
|
@ -248,14 +252,16 @@ bool exists(const String& filename) {
|
||||||
// Check if the file exists.
|
// Check if the file exists.
|
||||||
bool cexists(const String& filename) const {
|
bool cexists(const String& filename) const {
|
||||||
String passed = filename;
|
String passed = filename;
|
||||||
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
|
||||||
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
|
||||||
|| filename.at(filename.length() - 1) == '|')
|
|
||||||
{
|
|
||||||
passed = filename.substr(0, filename.length() - 2);
|
|
||||||
}
|
|
||||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||||
passed = filename.substr(0, filename.length() - 6);
|
passed = filename.substr(0, filename.length() - 6);
|
||||||
|
else if(filename.at(filename.length() - 2) == '"')
|
||||||
|
passed = filename.substr(0, filename.length() - 9);
|
||||||
|
else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||||
|
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||||
|
|| filename.at(filename.length() - 1) == '|')
|
||||||
|
passed = filename.substr(0, filename.length() - 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return arc.exists(passed.c_str());
|
return arc.exists(passed.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define _NIF_CONTROLLED_H_
|
#define _NIF_CONTROLLED_H_
|
||||||
|
|
||||||
#include "extra.hpp"
|
#include "extra.hpp"
|
||||||
|
#include "controller.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -40,13 +41,19 @@ public:
|
||||||
Extra::read(nif);
|
Extra::read(nif);
|
||||||
controller.read(nif);
|
controller.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Extra::post(nif);
|
||||||
|
controller.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Has name, extra-data and controller
|
/// Has name, extra-data and controller
|
||||||
class Named : public Controlled
|
class Named : public Controlled
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Misc::SString name;
|
std::string name;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +85,12 @@ public:
|
||||||
Controlled::read(nif);
|
Controlled::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controlled::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiGravity : public Controlled
|
class NiGravity : public Controlled
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
{
|
{
|
||||||
next.read(nif);
|
next.read(nif);
|
||||||
|
|
||||||
flags = nif->getShort();
|
flags = nif->getUShort();
|
||||||
|
|
||||||
frequency = nif->getFloat();
|
frequency = nif->getFloat();
|
||||||
phase = nif->getFloat();
|
phase = nif->getFloat();
|
||||||
|
@ -53,6 +53,13 @@ public:
|
||||||
|
|
||||||
target.read(nif);
|
target.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Record::post(nif);
|
||||||
|
next.post(nif);
|
||||||
|
target.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiBSPArrayController : public Controller
|
class NiBSPArrayController : public Controller
|
||||||
|
@ -64,7 +71,7 @@ public:
|
||||||
|
|
||||||
// At the moment, just skip it all
|
// At the moment, just skip it all
|
||||||
nif->skip(111);
|
nif->skip(111);
|
||||||
int s = nif->getShort();
|
int s = nif->getUShort();
|
||||||
nif->skip(15 + s*40);
|
nif->skip(15 + s*40);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -80,6 +87,12 @@ public:
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiPathController : public Controller
|
class NiPathController : public Controller
|
||||||
|
@ -101,6 +114,14 @@ public:
|
||||||
posData.read(nif);
|
posData.read(nif);
|
||||||
floatData.read(nif);
|
floatData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
|
||||||
|
posData.post(nif);
|
||||||
|
floatData.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiUVController : public Controller
|
class NiUVController : public Controller
|
||||||
|
@ -112,9 +133,15 @@ public:
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
|
|
||||||
nif->getShort(); // always 0
|
nif->getUShort(); // always 0
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiKeyframeController : public Controller
|
class NiKeyframeController : public Controller
|
||||||
|
@ -127,6 +154,12 @@ public:
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiAlphaController : public Controller
|
class NiAlphaController : public Controller
|
||||||
|
@ -139,6 +172,12 @@ public:
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiGeomMorpherController : public Controller
|
class NiGeomMorpherController : public Controller
|
||||||
|
@ -150,7 +189,13 @@ public:
|
||||||
{
|
{
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
nif->getByte(); // always 0
|
nif->getChar(); // always 0
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,6 +209,12 @@ public:
|
||||||
Controller::read(nif);
|
Controller::read(nif);
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Controller::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -35,12 +35,11 @@ namespace Nif
|
||||||
class NiSourceTexture : public Named
|
class NiSourceTexture : public Named
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Is this an external (references a separate texture file) or
|
// Is this an external (references a separate texture file) or
|
||||||
// internal (data is inside the nif itself) texture?
|
// internal (data is inside the nif itself) texture?
|
||||||
bool external;
|
bool external;
|
||||||
|
|
||||||
Misc::SString filename; // In case of external textures
|
std::string filename; // In case of external textures
|
||||||
NiPixelDataPtr data; // In case of internal textures
|
NiPixelDataPtr data; // In case of internal textures
|
||||||
|
|
||||||
/* Pixel layout
|
/* Pixel layout
|
||||||
|
@ -70,12 +69,12 @@ public:
|
||||||
{
|
{
|
||||||
Named::read(nif);
|
Named::read(nif);
|
||||||
|
|
||||||
external = !!nif->getByte();
|
external = !!nif->getChar();
|
||||||
|
if(external)
|
||||||
if(external) filename = nif->getString();
|
filename = nif->getString();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nif->getByte(); // always 1
|
nif->getChar(); // always 1
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +82,13 @@ public:
|
||||||
mipmap = nif->getInt();
|
mipmap = nif->getInt();
|
||||||
alpha = nif->getInt();
|
alpha = nif->getInt();
|
||||||
|
|
||||||
nif->getByte(); // always 1
|
nif->getChar(); // always 1
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Named::post(nif);
|
||||||
|
data.post(nif);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,34 +96,33 @@ public:
|
||||||
class ShapeData : public Record
|
class ShapeData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Misc::FloatArray vertices, normals, colors, uvlist;
|
std::vector<float> vertices, normals, colors, uvlist;
|
||||||
const Vector *center;
|
Ogre::Vector3 center;
|
||||||
float radius;
|
float radius;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int verts = nif->getShort();
|
int verts = nif->getUShort();
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
vertices = nif->getFloatLen(verts*3);
|
nif->getFloats(vertices, verts*3);
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
normals = nif->getFloatLen(verts*3);
|
nif->getFloats(normals, verts*3);
|
||||||
|
|
||||||
center = nif->getVector();
|
center = nif->getVector3();
|
||||||
radius = nif->getFloat();
|
radius = nif->getFloat();
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
colors = nif->getFloatLen(verts*4);
|
nif->getFloats(colors, verts*4);
|
||||||
|
|
||||||
int uvs = nif->getShort();
|
|
||||||
|
|
||||||
// Only the first 6 bits are used as a count. I think the rest are
|
// Only the first 6 bits are used as a count. I think the rest are
|
||||||
// flags of some sort.
|
// flags of some sort.
|
||||||
|
int uvs = nif->getUShort();
|
||||||
uvs &= 0x3f;
|
uvs &= 0x3f;
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
uvlist = nif->getFloatLen(uvs*verts*2);
|
nif->getFloats(uvlist, uvs*verts*2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,35 +130,32 @@ class NiTriShapeData : public ShapeData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Triangles, three vertex indices per triangle
|
// Triangles, three vertex indices per triangle
|
||||||
Misc::SliceArray<short> triangles;
|
std::vector<short> triangles;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
ShapeData::read(nif);
|
ShapeData::read(nif);
|
||||||
|
|
||||||
int tris = nif->getShort();
|
int tris = nif->getUShort();
|
||||||
if(tris)
|
if(tris)
|
||||||
{
|
{
|
||||||
// We have three times as many vertices as triangles, so this
|
// We have three times as many vertices as triangles, so this
|
||||||
// is always equal to tris*3.
|
// is always equal to tris*3.
|
||||||
int cnt = nif->getInt();
|
int cnt = nif->getInt();
|
||||||
triangles = nif->getArrayLen<short>(cnt);
|
nif->getShorts(triangles, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the match list, which lists the vertices that are equal to
|
// Read the match list, which lists the vertices that are equal to
|
||||||
// vertices. We don't actually need need this for anything, so
|
// vertices. We don't actually need need this for anything, so
|
||||||
// just skip it.
|
// just skip it.
|
||||||
int verts = nif->getShort();
|
int verts = nif->getUShort();
|
||||||
if(verts)
|
|
||||||
{
|
|
||||||
for(int i=0;i<verts;i++)
|
for(int i=0;i<verts;i++)
|
||||||
{
|
{
|
||||||
// Number of vertices matching vertex 'i'
|
// Number of vertices matching vertex 'i'
|
||||||
short num = nif->getShort();
|
int num = nif->getUShort();
|
||||||
nif->skip(num * sizeof(short));
|
nif->skip(num * sizeof(short));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiAutoNormalParticlesData : public ShapeData
|
class NiAutoNormalParticlesData : public ShapeData
|
||||||
|
@ -167,15 +168,17 @@ public:
|
||||||
ShapeData::read(nif);
|
ShapeData::read(nif);
|
||||||
|
|
||||||
// Should always match the number of vertices
|
// Should always match the number of vertices
|
||||||
activeCount = nif->getShort();
|
activeCount = nif->getUShort();
|
||||||
|
|
||||||
// Skip all the info, we don't support particles yet
|
// Skip all the info, we don't support particles yet
|
||||||
nif->getFloat(); // Active radius ?
|
nif->getFloat(); // Active radius ?
|
||||||
nif->getShort(); // Number of valid entries in the following arrays ?
|
nif->getUShort(); // Number of valid entries in the following arrays ?
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
|
{
|
||||||
// Particle sizes
|
// Particle sizes
|
||||||
nif->getFloatLen(activeCount);
|
nif->skip(activeCount * sizeof(float));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,10 +190,12 @@ public:
|
||||||
NiAutoNormalParticlesData::read(nif);
|
NiAutoNormalParticlesData::read(nif);
|
||||||
|
|
||||||
if(nif->getInt())
|
if(nif->getInt())
|
||||||
|
{
|
||||||
// Rotation quaternions. I THINK activeCount is correct here,
|
// Rotation quaternions. I THINK activeCount is correct here,
|
||||||
// but verts (vertex number) might also be correct, if there is
|
// but verts (vertex number) might also be correct, if there is
|
||||||
// any case where the two don't match.
|
// any case where the two don't match.
|
||||||
nif->getArrayLen<Vector4>(activeCount);
|
nif->skip(activeCount * 4*sizeof(float));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,12 +214,12 @@ public:
|
||||||
for(int i=0; i<count; i++)
|
for(int i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
/*float time =*/ nif->getFloat();
|
/*float time =*/ nif->getFloat();
|
||||||
nif->getVector(); // This isn't really shared between type 1
|
nif->getVector3(); // This isn't really shared between type 1
|
||||||
// and type 2, most likely
|
// and type 2, most likely
|
||||||
if(type == 2)
|
if(type == 2)
|
||||||
{
|
{
|
||||||
nif->getVector();
|
nif->getVector3();
|
||||||
nif->getVector();
|
nif->getVector3();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,15 +234,13 @@ public:
|
||||||
// also used in FloatData and KeyframeData. We could probably
|
// also used in FloatData and KeyframeData. We could probably
|
||||||
// reuse and refactor a lot of this if we actually use it at some
|
// reuse and refactor a lot of this if we actually use it at some
|
||||||
// point.
|
// point.
|
||||||
|
|
||||||
for(int i=0; i<2; i++)
|
for(int i=0; i<2; i++)
|
||||||
{
|
{
|
||||||
int count = nif->getInt();
|
int count = nif->getInt();
|
||||||
|
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
nif->getInt(); // always 2
|
nif->getInt(); // always 2
|
||||||
nif->getArrayLen<Vector4>(count); // Really one time float + one vector
|
nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Always 0
|
// Always 0
|
||||||
|
@ -253,7 +256,7 @@ public:
|
||||||
{
|
{
|
||||||
int count = nif->getInt();
|
int count = nif->getInt();
|
||||||
nif->getInt(); // always 2
|
nif->getInt(); // always 2
|
||||||
nif->getArrayLen<Vector4>(count); // Really one time float + one vector
|
nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -302,7 +305,7 @@ public:
|
||||||
struct ColorData
|
struct ColorData
|
||||||
{
|
{
|
||||||
float time;
|
float time;
|
||||||
Vector4 rgba;
|
Ogre::Vector4 rgba;
|
||||||
};
|
};
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
|
@ -311,25 +314,23 @@ public:
|
||||||
nif->getInt(); // always 1
|
nif->getInt(); // always 1
|
||||||
|
|
||||||
// Skip the data
|
// Skip the data
|
||||||
assert(sizeof(ColorData) == 4*5);
|
nif->skip(count * 5*sizeof(float));
|
||||||
nif->skip(sizeof(ColorData) * count);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiVisData : public Record
|
class NiVisData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct VisData {
|
||||||
|
float time;
|
||||||
|
char isSet;
|
||||||
|
};
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int count = nif->getInt();
|
int count = nif->getInt();
|
||||||
/*
|
|
||||||
Each VisData consists of:
|
|
||||||
float time;
|
|
||||||
byte isSet;
|
|
||||||
|
|
||||||
If you implement this, make sure you use a packed struct
|
/* Skip VisData */
|
||||||
(sizeof==5), or read each element individually.
|
|
||||||
*/
|
|
||||||
nif->skip(count*5);
|
nif->skip(count*5);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -346,9 +347,6 @@ public:
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
root.read(nif);
|
root.read(nif);
|
||||||
bones.read(nif);
|
bones.read(nif);
|
||||||
|
|
||||||
if(data.empty() || root.empty())
|
|
||||||
nif->fail("NiSkinInstance missing root or data");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void post(NIFFile *nif);
|
void post(NIFFile *nif);
|
||||||
|
@ -357,15 +355,10 @@ public:
|
||||||
class NiSkinData : public Record
|
class NiSkinData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// This is to make sure the structs are packed, ie. that the
|
|
||||||
// compiler doesn't mess them up with extra alignment bytes.
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
struct BoneTrafo
|
struct BoneTrafo
|
||||||
{
|
{
|
||||||
Matrix rotation; // Rotation offset from bone?
|
Ogre::Matrix3 rotation; // Rotation offset from bone?
|
||||||
Vector trans; // Translation
|
Ogre::Vector3 trans; // Translation
|
||||||
float scale; // Probably scale (always 1)
|
float scale; // Probably scale (always 1)
|
||||||
};
|
};
|
||||||
struct BoneTrafoCopy
|
struct BoneTrafoCopy
|
||||||
|
@ -380,20 +373,20 @@ public:
|
||||||
short vertex;
|
short vertex;
|
||||||
float weight;
|
float weight;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
struct BoneInfo
|
struct BoneInfo
|
||||||
{
|
{
|
||||||
const BoneTrafo *trafo;
|
BoneTrafo trafo;
|
||||||
const Vector4 *unknown;
|
Ogre::Vector4 unknown;
|
||||||
Misc::SliceArray<VertWeight> weights;
|
std::vector<VertWeight> weights;
|
||||||
};
|
};
|
||||||
struct BoneInfoCopy
|
struct BoneInfoCopy
|
||||||
{
|
{
|
||||||
std::string bonename;
|
std::string bonename;
|
||||||
unsigned short bonehandle;
|
unsigned short bonehandle;
|
||||||
BoneTrafoCopy trafo;
|
BoneTrafoCopy trafo;
|
||||||
Vector4 unknown;
|
Ogre::Vector4 unknown;
|
||||||
//std::vector<VertWeight> weights;
|
//std::vector<VertWeight> weights;
|
||||||
};
|
};
|
||||||
struct IndividualWeight
|
struct IndividualWeight
|
||||||
|
@ -402,31 +395,35 @@ public:
|
||||||
unsigned int boneinfocopyindex;
|
unsigned int boneinfocopyindex;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BoneTrafo *trafo;
|
BoneTrafo trafo;
|
||||||
std::vector<BoneInfo> bones;
|
std::vector<BoneInfo> bones;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
assert(sizeof(BoneTrafo) == 4*(9+3+1));
|
trafo.rotation = nif->getMatrix3();
|
||||||
assert(sizeof(VertWeight) == 6);
|
trafo.trans = nif->getVector3();
|
||||||
|
trafo.scale = nif->getFloat();
|
||||||
trafo = nif->getPtr<BoneTrafo>();
|
|
||||||
|
|
||||||
int boneNum = nif->getInt();
|
int boneNum = nif->getInt();
|
||||||
nif->getInt(); // -1
|
nif->getInt(); // -1
|
||||||
|
|
||||||
bones.resize(boneNum);
|
bones.resize(boneNum);
|
||||||
|
|
||||||
for(int i=0;i<boneNum;i++)
|
for(int i=0;i<boneNum;i++)
|
||||||
{
|
{
|
||||||
BoneInfo &bi = bones[i];
|
BoneInfo &bi = bones[i];
|
||||||
|
|
||||||
bi.trafo = nif->getPtr<BoneTrafo>();
|
bi.trafo.rotation = nif->getMatrix3();
|
||||||
|
bi.trafo.trans = nif->getVector3();
|
||||||
|
bi.trafo.scale = nif->getFloat();
|
||||||
bi.unknown = nif->getVector4();
|
bi.unknown = nif->getVector4();
|
||||||
|
|
||||||
// Number of vertex weights
|
// Number of vertex weights
|
||||||
int count = nif->getShort();
|
bi.weights.resize(nif->getUShort());
|
||||||
bi.weights = nif->getArrayLen<VertWeight>(count);
|
for(size_t j = 0;j < bi.weights.size();j++)
|
||||||
|
{
|
||||||
|
bi.weights[j].vertex = nif->getUShort();
|
||||||
|
bi.weights[j].weight = nif->getFloat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -440,43 +437,36 @@ class NiMorphData : public Record
|
||||||
std::vector<std::vector<Ogre::Vector3> > relevantData;
|
std::vector<std::vector<Ogre::Vector3> > relevantData;
|
||||||
std::vector<std::vector<Ogre::Vector3> > additionalVertices;
|
std::vector<std::vector<Ogre::Vector3> > additionalVertices;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float getStartTime(){
|
float getStartTime() const
|
||||||
return startTime;
|
{ return startTime; }
|
||||||
}
|
float getStopTime() const
|
||||||
float getStopTime(){
|
{ return stopTime; }
|
||||||
return stopTime;
|
|
||||||
}
|
|
||||||
void setStartTime(float time){
|
|
||||||
startTime = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStopTime(float time){
|
void setStartTime(float time)
|
||||||
stopTime = time;
|
{ startTime = time; }
|
||||||
}
|
void setStopTime(float time)
|
||||||
std::vector<Ogre::Vector3> getInitialVertices(){
|
{ stopTime = time; }
|
||||||
return initialVertices;
|
|
||||||
}
|
const std::vector<Ogre::Vector3>& getInitialVertices() const
|
||||||
std::vector<std::vector<Ogre::Vector3> > getRelevantData(){
|
{ return initialVertices; }
|
||||||
return relevantData;
|
const std::vector<std::vector<Ogre::Vector3> >& getRelevantData() const
|
||||||
}
|
{ return relevantData; }
|
||||||
std::vector<std::vector<float> > getRelevantTimes(){
|
const std::vector<std::vector<float> >& getRelevantTimes() const
|
||||||
return relevantTimes;
|
{ return relevantTimes; }
|
||||||
}
|
const std::vector<std::vector<Ogre::Vector3> >& getAdditionalVertices() const
|
||||||
std::vector<std::vector<Ogre::Vector3> > getAdditionalVertices(){
|
{ return additionalVertices; }
|
||||||
return additionalVertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int morphCount = nif->getInt();
|
int morphCount = nif->getInt();
|
||||||
int vertCount = nif->getInt();
|
int vertCount = nif->getInt();
|
||||||
nif->getByte();
|
nif->getChar();
|
||||||
int magic = nif->getInt();
|
int magic = nif->getInt();
|
||||||
/*int type =*/ nif->getInt();
|
/*int type =*/ nif->getInt();
|
||||||
for(int i = 0; i < vertCount; i++){
|
|
||||||
|
|
||||||
|
for(int i = 0; i < vertCount; i++)
|
||||||
|
{
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
float y = nif->getFloat();
|
float y = nif->getFloat();
|
||||||
float z = nif->getFloat();
|
float z = nif->getFloat();
|
||||||
|
@ -489,7 +479,8 @@ void read(NIFFile *nif)
|
||||||
/*type =*/ nif->getInt();
|
/*type =*/ nif->getInt();
|
||||||
std::vector<Ogre::Vector3> current;
|
std::vector<Ogre::Vector3> current;
|
||||||
std::vector<float> currentTime;
|
std::vector<float> currentTime;
|
||||||
for(int i = 0; i < magic; i++){
|
for(int i = 0; i < magic; i++)
|
||||||
|
{
|
||||||
// Time, data, forward, backward tangents
|
// Time, data, forward, backward tangents
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
|
@ -499,12 +490,16 @@ void read(NIFFile *nif)
|
||||||
currentTime.push_back(time);
|
currentTime.push_back(time);
|
||||||
//nif->getFloatLen(4*magic);
|
//nif->getFloatLen(4*magic);
|
||||||
}
|
}
|
||||||
if(magic){
|
|
||||||
|
if(magic)
|
||||||
|
{
|
||||||
relevantData.push_back(current);
|
relevantData.push_back(current);
|
||||||
relevantTimes.push_back(currentTime);
|
relevantTimes.push_back(currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Ogre::Vector3> verts;
|
std::vector<Ogre::Vector3> verts;
|
||||||
for(int i = 0; i < vertCount; i++){
|
for(int i = 0; i < vertCount; i++)
|
||||||
|
{
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
float y = nif->getFloat();
|
float y = nif->getFloat();
|
||||||
float z = nif->getFloat();
|
float z = nif->getFloat();
|
||||||
|
@ -536,7 +531,6 @@ class NiKeyframeData : public Record
|
||||||
int ttype;
|
int ttype;
|
||||||
|
|
||||||
//Scalings
|
//Scalings
|
||||||
|
|
||||||
std::vector<float> scalefactor;
|
std::vector<float> scalefactor;
|
||||||
std::vector<float> scaletime;
|
std::vector<float> scaletime;
|
||||||
std::vector<float> forwards;
|
std::vector<float> forwards;
|
||||||
|
@ -544,10 +538,8 @@ class NiKeyframeData : public Record
|
||||||
std::vector<Ogre::Vector3> tbcscale;
|
std::vector<Ogre::Vector3> tbcscale;
|
||||||
int stype;
|
int stype;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clone(NiKeyframeData c)
|
void clone(const NiKeyframeData &c)
|
||||||
{
|
{
|
||||||
quats = c.getQuat();
|
quats = c.getQuat();
|
||||||
tbc = c.getrTbc();
|
tbc = c.getrTbc();
|
||||||
|
@ -566,22 +558,15 @@ public:
|
||||||
transtime = c.gettTime();
|
transtime = c.gettTime();
|
||||||
|
|
||||||
bonename = c.getBonename();
|
bonename = c.getBonename();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBonename(std::string bone)
|
void setBonename(std::string bone)
|
||||||
{
|
{ bonename = bone; }
|
||||||
bonename = bone;
|
|
||||||
}
|
|
||||||
void setStartTime(float start)
|
void setStartTime(float start)
|
||||||
{
|
{ startTime = start; }
|
||||||
startTime = start;
|
|
||||||
}
|
|
||||||
void setStopTime(float end)
|
void setStopTime(float end)
|
||||||
{
|
{ stopTime = end; }
|
||||||
stopTime = end;
|
|
||||||
}
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
// Rotations first
|
// Rotations first
|
||||||
|
@ -590,7 +575,6 @@ public:
|
||||||
//std::vector<float> rottime(count);
|
//std::vector<float> rottime(count);
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
|
|
||||||
//TYPE1 LINEAR_KEY
|
//TYPE1 LINEAR_KEY
|
||||||
//TYPE2 QUADRATIC_KEY
|
//TYPE2 QUADRATIC_KEY
|
||||||
//TYPE3 TBC_KEY
|
//TYPE3 TBC_KEY
|
||||||
|
@ -603,7 +587,8 @@ public:
|
||||||
{
|
{
|
||||||
//We need to actually read in these values instead of skipping them
|
//We need to actually read in these values instead of skipping them
|
||||||
//nif->skip(count*4*5); // time + quaternion
|
//nif->skip(count*4*5); // time + quaternion
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float w = nif->getFloat();
|
float w = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
|
@ -617,8 +602,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(rtype == 3)
|
else if(rtype == 3)
|
||||||
{ //Example - node 116 in base_anim.nif
|
{
|
||||||
for (int i = 0; i < count; i++) {
|
//Example - node 116 in base_anim.nif
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float w = nif->getFloat();
|
float w = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
|
@ -628,6 +615,7 @@ public:
|
||||||
float tbcx = nif->getFloat();
|
float tbcx = nif->getFloat();
|
||||||
float tbcy = nif->getFloat();
|
float tbcy = nif->getFloat();
|
||||||
float tbcz = nif->getFloat();
|
float tbcz = nif->getFloat();
|
||||||
|
|
||||||
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
|
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
|
||||||
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
||||||
quats.push_back(quat);
|
quats.push_back(quat);
|
||||||
|
@ -636,8 +624,6 @@ public:
|
||||||
//if(time == 0.0 || time > 355.5)
|
//if(time == 0.0 || time > 355.5)
|
||||||
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
|
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//nif->skip(count*4*8); // rot1 + tension+bias+continuity
|
|
||||||
}
|
}
|
||||||
else if(rtype == 4)
|
else if(rtype == 4)
|
||||||
{
|
{
|
||||||
|
@ -652,28 +638,32 @@ public:
|
||||||
nif->skip(cnt*4*2); // time + unknown
|
nif->skip(cnt*4*2); // time + unknown
|
||||||
else if(type == 2)
|
else if(type == 2)
|
||||||
nif->skip(cnt*4*4); // time + unknown vector
|
nif->skip(cnt*4*4); // time + unknown vector
|
||||||
else nif->fail("Unknown sub-rotation type");
|
else
|
||||||
|
nif->fail("Unknown sub-rotation type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else nif->fail("Unknown rotation type in NiKeyframeData");
|
else
|
||||||
|
nif->fail("Unknown rotation type in NiKeyframeData");
|
||||||
}
|
}
|
||||||
//first = false;
|
//first = false;
|
||||||
|
|
||||||
// Then translation
|
// Then translation
|
||||||
count = nif->getInt();
|
count = nif->getInt();
|
||||||
|
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
ttype = nif->getInt();
|
ttype = nif->getInt();
|
||||||
|
|
||||||
//std::cout << "TransCount:" << count << " Type: " << type << "\n";
|
//std::cout << "TransCount:" << count << " Type: " << type << "\n";
|
||||||
if(ttype == 1) {
|
if(ttype == 1)
|
||||||
for (int i = 0; i < count; i++) {
|
{
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
float y = nif->getFloat();
|
float y = nif->getFloat();
|
||||||
float z = nif->getFloat();
|
float z = nif->getFloat();
|
||||||
|
|
||||||
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
||||||
translist1.push_back(trans);
|
translist1.push_back(trans);
|
||||||
transtime.push_back(time);
|
transtime.push_back(time);
|
||||||
|
@ -681,8 +671,10 @@ public:
|
||||||
//nif->getFloatLen(count*4); // time + translation
|
//nif->getFloatLen(count*4); // time + translation
|
||||||
}
|
}
|
||||||
else if(ttype == 2)
|
else if(ttype == 2)
|
||||||
{ //Example - node 116 in base_anim.nif
|
{
|
||||||
for (int i = 0; i < count; i++) {
|
//Example - node 116 in base_anim.nif
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
float y = nif->getFloat();
|
float y = nif->getFloat();
|
||||||
|
@ -693,6 +685,7 @@ public:
|
||||||
float x3 = nif->getFloat();
|
float x3 = nif->getFloat();
|
||||||
float y3 = nif->getFloat();
|
float y3 = nif->getFloat();
|
||||||
float z3 = nif->getFloat();
|
float z3 = nif->getFloat();
|
||||||
|
|
||||||
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
||||||
Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2);
|
Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2);
|
||||||
Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3);
|
Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3);
|
||||||
|
@ -704,8 +697,10 @@ public:
|
||||||
|
|
||||||
//nif->getFloatLen(count*10); // trans1 + forward + backward
|
//nif->getFloatLen(count*10); // trans1 + forward + backward
|
||||||
}
|
}
|
||||||
else if(ttype == 3){
|
else if(ttype == 3)
|
||||||
for (int i = 0; i < count; i++) {
|
{
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
float time = nif->getFloat();
|
float time = nif->getFloat();
|
||||||
float x = nif->getFloat();
|
float x = nif->getFloat();
|
||||||
float y = nif->getFloat();
|
float y = nif->getFloat();
|
||||||
|
@ -730,10 +725,8 @@ public:
|
||||||
{
|
{
|
||||||
stype = nif->getInt();
|
stype = nif->getInt();
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
for(int i = 0; i < count; i++){
|
{
|
||||||
|
|
||||||
|
|
||||||
//int size = 0;
|
//int size = 0;
|
||||||
if(stype >= 1 && stype < 4)
|
if(stype >= 1 && stype < 4)
|
||||||
{
|
{
|
||||||
|
@ -743,86 +736,70 @@ public:
|
||||||
scalefactor.push_back(scale);
|
scalefactor.push_back(scale);
|
||||||
//size = 2; // time+scale
|
//size = 2; // time+scale
|
||||||
}
|
}
|
||||||
else nif->fail("Unknown scaling type");
|
else
|
||||||
if(stype == 2){
|
nif->fail("Unknown scaling type");
|
||||||
|
|
||||||
|
if(stype == 2)
|
||||||
|
{
|
||||||
//size = 4; // 1 + forward + backward (floats)
|
//size = 4; // 1 + forward + backward (floats)
|
||||||
float forward = nif->getFloat();
|
float forward = nif->getFloat();
|
||||||
float backward = nif->getFloat();
|
float backward = nif->getFloat();
|
||||||
forwards.push_back(forward);
|
forwards.push_back(forward);
|
||||||
backwards.push_back(backward);
|
backwards.push_back(backward);
|
||||||
}
|
}
|
||||||
else if(stype == 3){
|
else if(stype == 3)
|
||||||
|
{
|
||||||
|
//size = 5; // 1 + tbc
|
||||||
float tbcx = nif->getFloat();
|
float tbcx = nif->getFloat();
|
||||||
float tbcy = nif->getFloat();
|
float tbcy = nif->getFloat();
|
||||||
float tbcz = nif->getFloat();
|
float tbcz = nif->getFloat();
|
||||||
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
||||||
tbcscale.push_back(vec);
|
tbcscale.push_back(vec);
|
||||||
|
|
||||||
//size = 5; // 1 + tbc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stype = 0;
|
stype = 0;
|
||||||
}
|
}
|
||||||
int getRtype(){
|
|
||||||
return rtype;
|
|
||||||
}
|
|
||||||
int getStype(){
|
|
||||||
return stype;
|
|
||||||
}
|
|
||||||
int getTtype(){
|
|
||||||
return ttype;
|
|
||||||
}
|
|
||||||
float getStartTime(){
|
|
||||||
return startTime;
|
|
||||||
}
|
|
||||||
float getStopTime(){
|
|
||||||
return stopTime;
|
|
||||||
}
|
|
||||||
std::vector<Ogre::Quaternion> getQuat(){
|
|
||||||
return quats;
|
|
||||||
}
|
|
||||||
std::vector<Ogre::Vector3> getrTbc(){
|
|
||||||
return tbc;
|
|
||||||
}
|
|
||||||
std::vector<float> getrTime(){
|
|
||||||
return rottime;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Ogre::Vector3> getTranslist1(){
|
int getRtype() const
|
||||||
return translist1;
|
{ return rtype; }
|
||||||
}
|
int getStype() const
|
||||||
std::vector<Ogre::Vector3> getTranslist2(){
|
{ return stype; }
|
||||||
return translist2;
|
int getTtype() const
|
||||||
}
|
{ return ttype; }
|
||||||
std::vector<Ogre::Vector3> getTranslist3(){
|
float getStartTime() const
|
||||||
return translist3;
|
{ return startTime; }
|
||||||
}
|
float getStopTime() const
|
||||||
std::vector<float> gettTime(){
|
{ return stopTime; }
|
||||||
return transtime;
|
const std::vector<Ogre::Quaternion>& getQuat() const
|
||||||
}
|
{ return quats; }
|
||||||
std::vector<float> getScalefactor(){
|
const std::vector<Ogre::Vector3>& getrTbc() const
|
||||||
return scalefactor;
|
{ return tbc; }
|
||||||
}
|
const std::vector<float>& getrTime() const
|
||||||
std::vector<float> getForwards(){
|
{ return rottime; }
|
||||||
return forwards;
|
|
||||||
}
|
|
||||||
std::vector<float> getBackwards(){
|
|
||||||
return backwards;
|
|
||||||
}
|
|
||||||
std::vector<Ogre::Vector3> getScaleTbc(){
|
|
||||||
return tbcscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float> getsTime(){
|
|
||||||
return scaletime;
|
|
||||||
}
|
|
||||||
std::string getBonename(){ return bonename;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const std::vector<Ogre::Vector3>& getTranslist1() const
|
||||||
|
{ return translist1; }
|
||||||
|
const std::vector<Ogre::Vector3>& getTranslist2() const
|
||||||
|
{ return translist2; }
|
||||||
|
const std::vector<Ogre::Vector3>& getTranslist3() const
|
||||||
|
{ return translist3; }
|
||||||
|
const std::vector<float>& gettTime() const
|
||||||
|
{ return transtime; }
|
||||||
|
const std::vector<float>& getScalefactor() const
|
||||||
|
{ return scalefactor; }
|
||||||
|
const std::vector<float>& getForwards() const
|
||||||
|
{ return forwards; }
|
||||||
|
const std::vector<float>& getBackwards() const
|
||||||
|
{ return backwards; }
|
||||||
|
const std::vector<Ogre::Vector3>& getScaleTbc() const
|
||||||
|
{ return tbcscale; }
|
||||||
|
|
||||||
|
const std::vector<float>& getsTime() const
|
||||||
|
{ return scaletime; }
|
||||||
|
const std::string& getBonename() const
|
||||||
|
{ return bonename; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -38,12 +38,19 @@ struct NiLight : Effect
|
||||||
struct SLight
|
struct SLight
|
||||||
{
|
{
|
||||||
float dimmer;
|
float dimmer;
|
||||||
Vector ambient;
|
Ogre::Vector3 ambient;
|
||||||
Vector diffuse;
|
Ogre::Vector3 diffuse;
|
||||||
Vector specular;
|
Ogre::Vector3 specular;
|
||||||
};
|
|
||||||
|
|
||||||
const SLight *light;
|
void read(NIFFile *nif)
|
||||||
|
{
|
||||||
|
dimmer = nif->getFloat();
|
||||||
|
ambient = nif->getVector3();
|
||||||
|
diffuse = nif->getVector3();
|
||||||
|
specular = nif->getVector3();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SLight light;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +58,7 @@ struct NiLight : Effect
|
||||||
|
|
||||||
nif->getInt(); // 1
|
nif->getInt(); // 1
|
||||||
nif->getInt(); // 1?
|
nif->getInt(); // 1?
|
||||||
light = nif->getPtr<SLight>();
|
light.read(nif);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,6 +93,12 @@ struct NiTextureEffect : Effect
|
||||||
*/
|
*/
|
||||||
nif->skip(23);
|
nif->skip(23);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Effect::post(nif);
|
||||||
|
texture.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
ExtraPtr extra;
|
ExtraPtr extra;
|
||||||
|
|
||||||
void read(NIFFile *nif) { extra.read(nif); }
|
void read(NIFFile *nif) { extra.read(nif); }
|
||||||
|
void post(NIFFile *nif) { extra.post(nif); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class NiVertWeightsExtraData : public Extra
|
class NiVertWeightsExtraData : public Extra
|
||||||
|
@ -53,9 +54,9 @@ public:
|
||||||
// We should have s*4+2 == i, for some reason. Might simply be the
|
// We should have s*4+2 == i, for some reason. Might simply be the
|
||||||
// size of the rest of the record, unhelpful as that may be.
|
// size of the rest of the record, unhelpful as that may be.
|
||||||
/*int i =*/ nif->getInt();
|
/*int i =*/ nif->getInt();
|
||||||
int s = nif->getShort(); // number of vertices
|
int s = nif->getUShort();
|
||||||
|
|
||||||
nif->getFloatLen(s); // vertex weights I guess
|
nif->skip(s * sizeof(float)); // vertex weights I guess
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,9 +66,8 @@ public:
|
||||||
struct TextKey
|
struct TextKey
|
||||||
{
|
{
|
||||||
float time;
|
float time;
|
||||||
Misc::SString text;
|
std::string text;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TextKey> list;
|
std::vector<TextKey> list;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
|
@ -93,7 +93,7 @@ public:
|
||||||
"MRK" - marker, only visible in the editor, not rendered in-game
|
"MRK" - marker, only visible in the editor, not rendered in-game
|
||||||
"NCO" - no collision
|
"NCO" - no collision
|
||||||
*/
|
*/
|
||||||
Misc::SString string;
|
std::string string;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,8 +46,8 @@ using namespace Misc;
|
||||||
void NIFFile::parse()
|
void NIFFile::parse()
|
||||||
{
|
{
|
||||||
// Check the header string
|
// Check the header string
|
||||||
const char* head = getString(40);
|
std::string head = getString(40);
|
||||||
if(!begins(head, "NetImmerse File Format"))
|
if(head.compare(0, 22, "NetImmerse File Format") != 0)
|
||||||
fail("Invalid NIF header");
|
fail("Invalid NIF header");
|
||||||
|
|
||||||
// Get BCD version
|
// Get BCD version
|
||||||
|
@ -70,7 +70,7 @@ void NIFFile::parse()
|
||||||
|
|
||||||
for(int i=0;i<recNum;i++)
|
for(int i=0;i<recNum;i++)
|
||||||
{
|
{
|
||||||
SString rec = getString();
|
std::string rec = getString();
|
||||||
//cout << i << ": " << rec.toString() << endl;
|
//cout << i << ": " << rec.toString() << endl;
|
||||||
|
|
||||||
Record *r = NULL;
|
Record *r = NULL;
|
||||||
|
@ -155,7 +155,7 @@ void NIFFile::parse()
|
||||||
|
|
||||||
// Failure
|
// Failure
|
||||||
else
|
else
|
||||||
fail("Unknown record type " + rec.toString());
|
fail("Unknown record type " + rec);
|
||||||
|
|
||||||
assert(r != NULL);
|
assert(r != NULL);
|
||||||
assert(r->recType != RC_MISSING);
|
assert(r->recType != RC_MISSING);
|
||||||
|
@ -190,17 +190,23 @@ void NIFFile::parse()
|
||||||
|
|
||||||
void NiSkinInstance::post(NIFFile *nif)
|
void NiSkinInstance::post(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int bnum = bones.length();
|
data.post(nif);
|
||||||
if(bnum != static_cast<int> (data->bones.size()))
|
root.post(nif);
|
||||||
|
bones.post(nif);
|
||||||
|
|
||||||
|
if(data.empty() || root.empty())
|
||||||
|
nif->fail("NiSkinInstance missing root or data");
|
||||||
|
|
||||||
|
size_t bnum = bones.length();
|
||||||
|
if(bnum != data->bones.size())
|
||||||
nif->fail("Mismatch in NiSkinData bone count");
|
nif->fail("Mismatch in NiSkinData bone count");
|
||||||
|
|
||||||
root->makeRootBone(data->trafo);
|
root->makeRootBone(&data->trafo);
|
||||||
|
|
||||||
for(int i=0; i<bnum; i++)
|
for(size_t i=0; i<bnum; i++)
|
||||||
{
|
{
|
||||||
if(!bones.has(i))
|
if(!bones.has(i))
|
||||||
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
||||||
|
|
||||||
bones[i].makeBone(i, data->bones[i]);
|
bones[i].makeBone(i, data->bones[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,11 @@
|
||||||
#ifndef _NIF_FILE_H_
|
#ifndef _NIF_FILE_H_
|
||||||
#define _NIF_FILE_H_
|
#define _NIF_FILE_H_
|
||||||
|
|
||||||
#include <libs/mangle/stream/stream.hpp>
|
#include <OgreResourceGroupManager.h>
|
||||||
#include <libs/mangle/stream/filters/buffer_stream.hpp>
|
#include <OgreDataStream.h>
|
||||||
#include <components/misc/slice_array.hpp>
|
#include <OgreVector3.h>
|
||||||
|
#include <OgreVector4.h>
|
||||||
|
#include <OgreMatrix3.h>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -36,15 +38,12 @@
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
#include "nif_types.hpp"
|
#include "nif_types.hpp"
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
class NIFFile
|
class NIFFile
|
||||||
{
|
{
|
||||||
enum NIFVersion
|
enum NIFVersion {
|
||||||
{
|
|
||||||
VER_MW = 0x04000002 // Morrowind NIFs
|
VER_MW = 0x04000002 // Morrowind NIFs
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ class NIFFile
|
||||||
int ver;
|
int ver;
|
||||||
|
|
||||||
/// Input stream
|
/// Input stream
|
||||||
StreamPtr inp;
|
Ogre::DataStreamPtr inp;
|
||||||
|
|
||||||
/// File name, used for error messages
|
/// File name, used for error messages
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
@ -63,6 +62,33 @@ class NIFFile
|
||||||
/// Parse the file
|
/// Parse the file
|
||||||
void parse();
|
void parse();
|
||||||
|
|
||||||
|
uint8_t read_byte()
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
if(inp->read(&byte, 1) != 1) return 0;
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
uint16_t read_le16()
|
||||||
|
{
|
||||||
|
uint8_t buffer[2];
|
||||||
|
if(inp->read(buffer, 2) != 2) return 0;
|
||||||
|
return buffer[0] | (buffer[1]<<8);
|
||||||
|
}
|
||||||
|
uint32_t read_le32()
|
||||||
|
{
|
||||||
|
uint8_t buffer[4];
|
||||||
|
if(inp->read(buffer, 4) != 4) return 0;
|
||||||
|
return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
|
||||||
|
}
|
||||||
|
float read_le32f()
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
} u = { read_le32() };
|
||||||
|
return u.f;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Used for error handling
|
/// Used for error handling
|
||||||
void fail(const std::string &msg)
|
void fail(const std::string &msg)
|
||||||
|
@ -73,38 +99,23 @@ class NIFFile
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a NIF stream. The name is used for error messages.
|
/// Open a NIF stream. The name is used for error messages.
|
||||||
NIFFile(StreamPtr nif, const std::string &name)
|
NIFFile(const std::string &name)
|
||||||
: filename(name)
|
: filename(name)
|
||||||
{
|
{
|
||||||
/* Load the entire file into memory. This allows us to use
|
inp = Ogre::ResourceGroupManager::getSingleton().openResource(name);
|
||||||
direct pointers to the data arrays in the NIF, instead of
|
|
||||||
individually allocating and copying each one.
|
|
||||||
|
|
||||||
The NIF data is only stored temporarily in memory, since once
|
|
||||||
the mesh data is loaded it is siphoned into OGRE and
|
|
||||||
deleted. For that reason, we might improve this further and
|
|
||||||
use a shared region/pool based allocation scheme in the
|
|
||||||
future, especially since only one NIFFile will ever be loaded
|
|
||||||
at any given time.
|
|
||||||
*/
|
|
||||||
inp = StreamPtr(new BufferStream(nif));
|
|
||||||
|
|
||||||
parse();
|
parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
~NIFFile()
|
~NIFFile()
|
||||||
{
|
{
|
||||||
for(std::size_t i=0; i<records.size(); i++)
|
for(std::size_t i=0; i<records.size(); i++)
|
||||||
{
|
|
||||||
delete records[i];
|
delete records[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a given record
|
/// Get a given record
|
||||||
Record *getRecord(int index)
|
Record *getRecord(size_t index)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index < static_cast<int> (records.size()));
|
Record *res = records.at(index);
|
||||||
Record *res = records[index];
|
|
||||||
assert(res != NULL);
|
assert(res != NULL);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -113,44 +124,76 @@ class NIFFile
|
||||||
int numRecords() { return records.size(); }
|
int numRecords() { return records.size(); }
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
|
|
||||||
Parser functions
|
Parser functions
|
||||||
|
|
||||||
****************************************************/
|
****************************************************/
|
||||||
|
|
||||||
void skip(size_t size) { inp->getPtr(size); }
|
void skip(size_t size) { inp->skip(size); }
|
||||||
|
|
||||||
template<class X> const X* getPtr() { return (const X*)inp->getPtr(sizeof(X)); }
|
char getChar() { return read_byte(); }
|
||||||
template<class X> X getType() { return *getPtr<X>(); }
|
short getShort() { return read_le16(); }
|
||||||
unsigned short getShort() { return getType<unsigned short>(); }
|
unsigned short getUShort() { return read_le16(); }
|
||||||
int getInt() { return getType<int>(); }
|
int getInt() { return read_le32(); }
|
||||||
float getFloat() { return getType<float>(); }
|
float getFloat() { return read_le32f(); }
|
||||||
char getByte() { return getType<char>(); }
|
Ogre::Vector3 getVector3()
|
||||||
|
|
||||||
template<class X>
|
|
||||||
Misc::SliceArray<X> getArrayLen(int num)
|
|
||||||
{ return Misc::SliceArray<X>((const X*)inp->getPtr(num*sizeof(X)),num); }
|
|
||||||
|
|
||||||
template<class X>
|
|
||||||
Misc::SliceArray<X> getArray()
|
|
||||||
{
|
{
|
||||||
int len = getInt();
|
float a[3];
|
||||||
return getArrayLen<X>(len);
|
for(size_t i = 0;i < 3;i++)
|
||||||
|
a[i] = getFloat();
|
||||||
|
return Ogre::Vector3(a);
|
||||||
|
}
|
||||||
|
Ogre::Vector4 getVector4()
|
||||||
|
{
|
||||||
|
float a[4];
|
||||||
|
for(size_t i = 0;i < 4;i++)
|
||||||
|
a[i] = getFloat();
|
||||||
|
return Ogre::Vector4(a);
|
||||||
|
}
|
||||||
|
Ogre::Matrix3 getMatrix3()
|
||||||
|
{
|
||||||
|
Ogre::Real a[3][3];
|
||||||
|
for(size_t i = 0;i < 3;i++)
|
||||||
|
{
|
||||||
|
for(size_t j = 0;j < 3;j++)
|
||||||
|
a[i][j] = Ogre::Real(getFloat());
|
||||||
|
}
|
||||||
|
return Ogre::Matrix3(a);
|
||||||
|
}
|
||||||
|
Transformation getTrafo()
|
||||||
|
{
|
||||||
|
Transformation t;
|
||||||
|
t.pos = getVector3();
|
||||||
|
t.rotation = getMatrix3();
|
||||||
|
t.scale = getFloat();
|
||||||
|
t.velocity = getVector3();
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Misc::SString getString() { return getArray<char>(); }
|
std::string getString(size_t length)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
str.resize(length);
|
||||||
|
if(inp->read(&str[0], length) != length)
|
||||||
|
return std::string();
|
||||||
|
return str.substr(0, str.find('\0'));
|
||||||
|
}
|
||||||
|
std::string getString()
|
||||||
|
{
|
||||||
|
size_t size = read_le32();
|
||||||
|
return getString(size);
|
||||||
|
}
|
||||||
|
|
||||||
const Vector *getVector() { return getPtr<Vector>(); }
|
void getShorts(std::vector<short> &vec, size_t size)
|
||||||
const Matrix *getMatrix() { return getPtr<Matrix>(); }
|
{
|
||||||
const Transformation *getTrafo() { return getPtr<Transformation>(); }
|
vec.resize(size);
|
||||||
const Vector4 *getVector4() { return getPtr<Vector4>(); }
|
for(size_t i = 0;i < vec.size();i++)
|
||||||
|
vec[i] = getShort();
|
||||||
Misc::FloatArray getFloatLen(int num)
|
}
|
||||||
{ return getArrayLen<float>(num); }
|
void getFloats(std::vector<float> &vec, size_t size)
|
||||||
|
{
|
||||||
// For fixed-size strings where you already know the size
|
vec.resize(size);
|
||||||
const char *getString(int size)
|
for(size_t i = 0;i < vec.size();i++)
|
||||||
{ return (const char*)inp->getPtr(size); }
|
vec[i] = getFloat();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -24,59 +24,37 @@
|
||||||
#ifndef _NIF_TYPES_H_
|
#ifndef _NIF_TYPES_H_
|
||||||
#define _NIF_TYPES_H_
|
#define _NIF_TYPES_H_
|
||||||
|
|
||||||
|
#include <OgreVector3.h>
|
||||||
|
#include <OgreMatrix3.h>
|
||||||
|
|
||||||
// Common types used in NIF files
|
// Common types used in NIF files
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
/* These packing #pragmas aren't really necessary on 32 bit
|
|
||||||
machines. I haven't tested on 64 bit yet. In any case it doesn't
|
|
||||||
hurt to include them. We can't allow any compiler-generated padding
|
|
||||||
in any of these structs, since they are used to interface directly
|
|
||||||
with raw data from the NIF files.
|
|
||||||
*/
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
struct Vector
|
|
||||||
{
|
|
||||||
float array[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vector4
|
|
||||||
{
|
|
||||||
float array[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Matrix
|
|
||||||
{
|
|
||||||
Vector v[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Transformation
|
struct Transformation
|
||||||
{
|
{
|
||||||
Vector pos;
|
Ogre::Vector3 pos;
|
||||||
Matrix rotation;
|
Ogre::Matrix3 rotation;
|
||||||
float scale;
|
float scale;
|
||||||
Vector velocity;
|
Ogre::Vector3 velocity;
|
||||||
|
|
||||||
static const Transformation* getIdentity()
|
static const Transformation& getIdentity()
|
||||||
{
|
{
|
||||||
static Transformation identity;
|
static Transformation identity;
|
||||||
static bool iset = false;
|
static bool iset = false;
|
||||||
if (!iset)
|
if (!iset)
|
||||||
{
|
{
|
||||||
identity.scale = 1.0f;
|
identity.scale = 1.0f;
|
||||||
identity.rotation.v[0].array[0] = 1.0f;
|
identity.rotation[0][0] = 1.0f;
|
||||||
identity.rotation.v[1].array[1] = 1.0f;
|
identity.rotation[1][1] = 1.0f;
|
||||||
identity.rotation.v[2].array[2] = 1.0f;
|
identity.rotation[2][2] = 1.0f;
|
||||||
iset = true;
|
iset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &identity;
|
return identity;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,10 +26,13 @@
|
||||||
|
|
||||||
#include "controlled.hpp"
|
#include "controlled.hpp"
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "property.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class NiNode;
|
||||||
|
|
||||||
/** A Node is an object that's part of the main NIF tree. It has
|
/** A Node is an object that's part of the main NIF tree. It has
|
||||||
parent node (unless it's the root), and transformation (location
|
parent node (unless it's the root), and transformation (location
|
||||||
and rotation) relative to it's parent.
|
and rotation) relative to it's parent.
|
||||||
|
@ -39,20 +42,20 @@ class Node : public Named
|
||||||
public:
|
public:
|
||||||
// Node flags. Interpretation depends somewhat on the type of node.
|
// Node flags. Interpretation depends somewhat on the type of node.
|
||||||
int flags;
|
int flags;
|
||||||
const Transformation *trafo;
|
Transformation trafo;
|
||||||
PropertyList props;
|
PropertyList props;
|
||||||
|
|
||||||
// Bounding box info
|
// Bounding box info
|
||||||
bool hasBounds;
|
bool hasBounds;
|
||||||
const Vector *boundPos;
|
Ogre::Vector3 boundPos;
|
||||||
const Matrix *boundRot;
|
Ogre::Matrix3 boundRot;
|
||||||
const Vector *boundXYZ; // Box size
|
Ogre::Vector3 boundXYZ; // Box size
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
Named::read(nif);
|
Named::read(nif);
|
||||||
|
|
||||||
flags = nif->getShort();
|
flags = nif->getUShort();
|
||||||
trafo = nif->getTrafo();
|
trafo = nif->getTrafo();
|
||||||
props.read(nif);
|
props.read(nif);
|
||||||
|
|
||||||
|
@ -60,15 +63,27 @@ public:
|
||||||
if(hasBounds)
|
if(hasBounds)
|
||||||
{
|
{
|
||||||
nif->getInt(); // always 1
|
nif->getInt(); // always 1
|
||||||
boundPos = nif->getVector();
|
boundPos = nif->getVector3();
|
||||||
boundRot = nif->getMatrix();
|
boundRot = nif->getMatrix3();
|
||||||
boundXYZ = nif->getVector();
|
boundXYZ = nif->getVector3();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent = NULL;
|
||||||
|
|
||||||
boneTrafo = NULL;
|
boneTrafo = NULL;
|
||||||
boneIndex = -1;
|
boneIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Named::post(nif);
|
||||||
|
props.post(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent node, or NULL for the root node. As far as I'm aware, only
|
||||||
|
// NiNodes (or types derived from NiNodes) can be parents.
|
||||||
|
NiNode *parent;
|
||||||
|
|
||||||
// Bone transformation. If set, node is a part of a skeleton.
|
// Bone transformation. If set, node is a part of a skeleton.
|
||||||
const NiSkinData::BoneTrafo *boneTrafo;
|
const NiSkinData::BoneTrafo *boneTrafo;
|
||||||
|
|
||||||
|
@ -88,7 +103,7 @@ public:
|
||||||
void makeBone(short ind, const NiSkinData::BoneInfo &bi)
|
void makeBone(short ind, const NiSkinData::BoneInfo &bi)
|
||||||
{
|
{
|
||||||
boneInfo = &bi;
|
boneInfo = &bi;
|
||||||
boneTrafo = bi.trafo;
|
boneTrafo = &bi.trafo;
|
||||||
boneIndex = ind;
|
boneIndex = ind;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -113,7 +128,6 @@ struct NiNode : Node
|
||||||
NodeList effects;
|
NodeList effects;
|
||||||
|
|
||||||
/* Known NiNode flags:
|
/* Known NiNode flags:
|
||||||
|
|
||||||
0x01 hidden
|
0x01 hidden
|
||||||
0x02 use mesh for collision
|
0x02 use mesh for collision
|
||||||
0x04 use bounding box for collision (?)
|
0x04 use bounding box for collision (?)
|
||||||
|
@ -127,6 +141,20 @@ struct NiNode : Node
|
||||||
children.read(nif);
|
children.read(nif);
|
||||||
effects.read(nif);
|
effects.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
children.post(nif);
|
||||||
|
effects.post(nif);
|
||||||
|
|
||||||
|
for(size_t i = 0;i < children.length();i++)
|
||||||
|
{
|
||||||
|
// Why would a unique list of children contain empty refs?
|
||||||
|
if(children.has(i))
|
||||||
|
children[i].parent = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiTriShape : Node
|
struct NiTriShape : Node
|
||||||
|
@ -148,24 +176,32 @@ struct NiTriShape : Node
|
||||||
skin.read(nif);
|
skin.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
NiTriShapeCopy clone(){
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
skin.post(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
NiTriShapeCopy clone()
|
||||||
|
{
|
||||||
NiTriShapeCopy copy;
|
NiTriShapeCopy copy;
|
||||||
copy.sname = name.toString();
|
copy.sname = name;
|
||||||
float *ptr = (float*)data->vertices.ptr;
|
float *ptr = (float*)&data->vertices[0];
|
||||||
float *ptrNormals = (float*)data->normals.ptr;
|
float *ptrNormals = (float*)&data->normals[0];
|
||||||
int numVerts = data->vertices.length / 3;
|
int numVerts = data->vertices.size() / 3;
|
||||||
for(int i = 0; i < numVerts; i++)
|
for(int i = 0; i < numVerts; i++)
|
||||||
{
|
{
|
||||||
float *current = (float*) (ptr + i * 3);
|
float *current = (float*) (ptr + i * 3);
|
||||||
copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2)));
|
copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2)));
|
||||||
|
|
||||||
if(ptrNormals){
|
if(ptrNormals)
|
||||||
|
{
|
||||||
float *currentNormals = (float*) (ptrNormals + i * 3);
|
float *currentNormals = (float*) (ptrNormals + i * 3);
|
||||||
copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2)));
|
copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -182,15 +218,31 @@ struct NiCamera : Node
|
||||||
|
|
||||||
// Level of detail modifier
|
// Level of detail modifier
|
||||||
float LOD;
|
float LOD;
|
||||||
};
|
|
||||||
|
|
||||||
const Camera *cam;
|
void read(NIFFile *nif)
|
||||||
|
{
|
||||||
|
left = nif->getFloat();
|
||||||
|
right = nif->getFloat();
|
||||||
|
top = nif->getFloat();
|
||||||
|
bottom = nif->getFloat();
|
||||||
|
nearDist = nif->getFloat();
|
||||||
|
farDist = nif->getFloat();
|
||||||
|
|
||||||
|
vleft = nif->getFloat();
|
||||||
|
vright = nif->getFloat();
|
||||||
|
vtop = nif->getFloat();
|
||||||
|
vbottom = nif->getFloat();
|
||||||
|
|
||||||
|
LOD = nif->getFloat();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
Node::read(nif);
|
Node::read(nif);
|
||||||
|
|
||||||
nif->getPtr<Camera>();
|
cam.read(nif);
|
||||||
|
|
||||||
nif->getInt(); // -1
|
nif->getInt(); // -1
|
||||||
nif->getInt(); // 0
|
nif->getInt(); // 0
|
||||||
|
@ -207,6 +259,12 @@ struct NiAutoNormalParticles : Node
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
nif->getInt(); // -1
|
nif->getInt(); // -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiRotatingParticles : Node
|
struct NiRotatingParticles : Node
|
||||||
|
@ -219,9 +277,13 @@ struct NiRotatingParticles : Node
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
nif->getInt(); // -1
|
nif->getInt(); // -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
Named::read(nif);
|
Named::read(nif);
|
||||||
flags = nif->getShort();
|
flags = nif->getUShort();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,6 +82,11 @@ public:
|
||||||
// short.
|
// short.
|
||||||
nif->skip(6);
|
nif->skip(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
texture.post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Apply mode:
|
/* Apply mode:
|
||||||
|
@ -130,6 +135,13 @@ public:
|
||||||
}
|
}
|
||||||
textures[6].read(nif); // Decal
|
textures[6].read(nif); // Decal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Property::post(nif);
|
||||||
|
for(int i = 0;i < 7;i++)
|
||||||
|
textures[i].post(nif);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// These contain no other data than the 'flags' field in Property
|
// These contain no other data than the 'flags' field in Property
|
||||||
|
@ -140,23 +152,33 @@ typedef Property NiSpecularProperty;
|
||||||
typedef Property NiWireframeProperty;
|
typedef Property NiWireframeProperty;
|
||||||
|
|
||||||
// The rest are all struct-based
|
// The rest are all struct-based
|
||||||
template <typename Struct>
|
template <typename T>
|
||||||
struct StructPropT : Property
|
struct StructPropT : Property
|
||||||
{
|
{
|
||||||
const Struct* data;
|
T data;
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
Property::read(nif);
|
Property::read(nif);
|
||||||
data = nif->getPtr<Struct>();
|
data.read(nif);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct S_MaterialProperty
|
struct S_MaterialProperty
|
||||||
{
|
{
|
||||||
// The vector components are R,G,B
|
// The vector components are R,G,B
|
||||||
Vector ambient, diffuse, specular, emissive;
|
Ogre::Vector3 ambient, diffuse, specular, emissive;
|
||||||
float glossiness, alpha;
|
float glossiness, alpha;
|
||||||
|
|
||||||
|
void read(NIFFile *nif)
|
||||||
|
{
|
||||||
|
ambient = nif->getVector3();
|
||||||
|
diffuse = nif->getVector3();
|
||||||
|
specular = nif->getVector3();
|
||||||
|
emissive = nif->getVector3();
|
||||||
|
glossiness = nif->getFloat();
|
||||||
|
alpha = nif->getFloat();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct S_VertexColorProperty
|
struct S_VertexColorProperty
|
||||||
|
@ -171,6 +193,12 @@ struct S_VertexColorProperty
|
||||||
1 - lighting emmisive ambient/diffuse
|
1 - lighting emmisive ambient/diffuse
|
||||||
*/
|
*/
|
||||||
int vertmode, lightmode;
|
int vertmode, lightmode;
|
||||||
|
|
||||||
|
void read(NIFFile *nif)
|
||||||
|
{
|
||||||
|
vertmode = nif->getInt();
|
||||||
|
lightmode = nif->getInt();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct S_AlphaProperty
|
struct S_AlphaProperty
|
||||||
|
@ -222,6 +250,11 @@ struct S_AlphaProperty
|
||||||
|
|
||||||
// Tested against when certain flags are set (see above.)
|
// Tested against when certain flags are set (see above.)
|
||||||
unsigned char threshold;
|
unsigned char threshold;
|
||||||
|
|
||||||
|
void read(NIFFile *nif)
|
||||||
|
{
|
||||||
|
threshold = nif->getChar();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef StructPropT<S_AlphaProperty> NiAlphaProperty;
|
typedef StructPropT<S_AlphaProperty> NiAlphaProperty;
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct Record
|
||||||
{
|
{
|
||||||
// Record type and type name
|
// Record type and type name
|
||||||
int recType;
|
int recType;
|
||||||
Misc::SString recName;
|
std::string recName;
|
||||||
|
|
||||||
Record() : recType(RC_MISSING) {}
|
Record() : recType(RC_MISSING) {}
|
||||||
|
|
||||||
|
@ -104,7 +104,6 @@ struct Record
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use these later if you want custom allocation of all NIF objects
|
Use these later if you want custom allocation of all NIF objects
|
||||||
|
|
||||||
static void* operator new(size_t size);
|
static void* operator new(size_t size);
|
||||||
static void operator delete(void *p);
|
static void operator delete(void *p);
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,61 +37,52 @@ namespace Nif
|
||||||
template <class X>
|
template <class X>
|
||||||
class RecordPtrT
|
class RecordPtrT
|
||||||
{
|
{
|
||||||
int index;
|
union {
|
||||||
|
intptr_t index;
|
||||||
X* ptr;
|
X* ptr;
|
||||||
NIFFile *nif;
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
RecordPtrT() : index(-2) {}
|
||||||
RecordPtrT() : index(-2), ptr(NULL) {}
|
|
||||||
|
|
||||||
/// Read the index from the nif
|
/// Read the index from the nif
|
||||||
void read(NIFFile *_nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
// Can only read the index once
|
// Can only read the index once
|
||||||
assert(index == -2);
|
assert(index == -2);
|
||||||
|
|
||||||
// Store the NIFFile pointer for later
|
// Store the index for later
|
||||||
nif = _nif;
|
|
||||||
|
|
||||||
// And the index, of course
|
|
||||||
index = nif->getInt();
|
index = nif->getInt();
|
||||||
|
assert(index >= -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the pointer explicitly. May be used when you are pointing to
|
/// Resolve index to pointer
|
||||||
records in another file, eg. when you have a .nif / .kf pair.
|
void post(NIFFile *nif)
|
||||||
*/
|
|
||||||
void set(X *p)
|
|
||||||
{
|
{
|
||||||
ptr = p;
|
if(index < 0)
|
||||||
index = -1;
|
ptr = NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Record *r = nif->getRecord(index);
|
||||||
|
// And cast it
|
||||||
|
ptr = dynamic_cast<X*>(r);
|
||||||
|
assert(ptr != NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the actual object from the index
|
/// Look up the actual object from the index
|
||||||
X* getPtr()
|
X* getPtr()
|
||||||
{
|
{
|
||||||
// Have we found the pointer already?
|
|
||||||
if(ptr == NULL)
|
|
||||||
{
|
|
||||||
// Get the record
|
|
||||||
assert(index >= 0);
|
|
||||||
Record *r = nif->getRecord(index);
|
|
||||||
|
|
||||||
// And cast it
|
|
||||||
ptr = dynamic_cast<X*>(r);
|
|
||||||
assert(ptr != NULL);
|
assert(ptr != NULL);
|
||||||
}
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
X& get() { return *getPtr(); }
|
||||||
|
|
||||||
/// Syntactic sugar
|
/// Syntactic sugar
|
||||||
X* operator->() { return getPtr(); }
|
X* operator->() { return getPtr(); }
|
||||||
X& get() { return *getPtr(); }
|
|
||||||
|
|
||||||
/// Pointers are allowed to be empty
|
/// Pointers are allowed to be empty
|
||||||
bool empty() { return index == -1 && ptr == NULL; }
|
bool empty() { return ptr == NULL; }
|
||||||
|
|
||||||
int getIndex() { return index; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A list of references to other records. These are read as a list,
|
/** A list of references to other records. These are read as a list,
|
||||||
|
@ -105,36 +96,33 @@ class RecordListT
|
||||||
std::vector<Ptr> list;
|
std::vector<Ptr> list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int len = nif->getInt();
|
int len = nif->getInt();
|
||||||
list.resize(len);
|
list.resize(len);
|
||||||
|
|
||||||
assert(len >= 0 && len < 1000);
|
for(size_t i=0;i < list.size();i++)
|
||||||
for(int i=0;i<len;i++)
|
|
||||||
list[i].read(nif);
|
list[i].read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
X& operator[](int index)
|
void post(NIFFile *nif)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index < static_cast<int> (list.size()));
|
for(size_t i=0;i < list.size();i++)
|
||||||
return list[index].get();
|
list[i].post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(int index)
|
X& operator[](size_t index)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index < static_cast<int> (list.size()));
|
return list.at(index).get();
|
||||||
return !list[index].empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getIndex(int index)
|
bool has(size_t index)
|
||||||
{
|
{
|
||||||
if(has(index)) return list[index].getIndex();
|
return !list.at(index).empty();
|
||||||
else return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int length() { return list.size(); }
|
size_t length()
|
||||||
|
{ return list.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ http://www.gnu.org/licenses/ .
|
||||||
#include <Ogre.h>
|
#include <Ogre.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
|
||||||
#include "../nif/nif_file.hpp"
|
#include "../nif/nif_file.hpp"
|
||||||
#include "../nif/node.hpp"
|
#include "../nif/node.hpp"
|
||||||
#include "../nif/data.hpp"
|
#include "../nif/data.hpp"
|
||||||
|
@ -44,32 +43,15 @@ http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
typedef unsigned char ubyte;
|
typedef unsigned char ubyte;
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Ogre;
|
|
||||||
using namespace Nif;
|
|
||||||
using namespace Mangle::VFS;
|
|
||||||
|
|
||||||
using namespace NifBullet;
|
using namespace NifBullet;
|
||||||
|
|
||||||
|
|
||||||
ManualBulletShapeLoader::~ManualBulletShapeLoader()
|
ManualBulletShapeLoader::~ManualBulletShapeLoader()
|
||||||
{
|
{
|
||||||
delete vfs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(Nif::Transformation* tr)
|
|
||||||
{
|
|
||||||
Ogre::Matrix3 rot(tr->rotation.v[0].array[0],tr->rotation.v[0].array[1],tr->rotation.v[0].array[2],
|
|
||||||
tr->rotation.v[1].array[0],tr->rotation.v[1].array[1],tr->rotation.v[1].array[2],
|
|
||||||
tr->rotation.v[2].array[0],tr->rotation.v[2].array[1],tr->rotation.v[2].array[2]);
|
|
||||||
return rot;
|
|
||||||
}
|
|
||||||
Ogre::Vector3 ManualBulletShapeLoader::getVector(Nif::Transformation* tr)
|
|
||||||
{
|
|
||||||
Ogre::Vector3 vect3(tr->pos.array[0],tr->pos.array[1],tr->pos.array[2]);
|
|
||||||
return vect3;
|
|
||||||
}
|
|
||||||
|
|
||||||
btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 m)
|
btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 &m)
|
||||||
{
|
{
|
||||||
Ogre::Quaternion oquat(m);
|
Ogre::Quaternion oquat(m);
|
||||||
btQuaternion quat;
|
btQuaternion quat;
|
||||||
|
@ -80,10 +62,9 @@ btQuaternion ManualBulletShapeLoader::getbtQuat(Ogre::Matrix3 m)
|
||||||
return quat;
|
return quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
btVector3 ManualBulletShapeLoader::getbtVector(Nif::Vector v)
|
btVector3 ManualBulletShapeLoader::getbtVector(Ogre::Vector3 &v)
|
||||||
{
|
{
|
||||||
btVector3 a(v.array[0],v.array[1],v.array[2]);
|
return btVector3(v[0], v[1], v[2]);
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
||||||
|
@ -94,20 +75,11 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
||||||
|
|
||||||
mTriMesh = new btTriangleMesh();
|
mTriMesh = new btTriangleMesh();
|
||||||
|
|
||||||
if (!vfs) vfs = new OgreVFS(resourceGroup);
|
|
||||||
|
|
||||||
if (!vfs->isFile(resourceName))
|
|
||||||
{
|
|
||||||
warn("File not found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the NIF. TODO: Wrap this in a try-catch block once we're out
|
// Load the NIF. TODO: Wrap this in a try-catch block once we're out
|
||||||
// of the early stages of development. Right now we WANT to catch
|
// of the early stages of development. Right now we WANT to catch
|
||||||
// every error as early and intrusively as possible, as it's most
|
// every error as early and intrusively as possible, as it's most
|
||||||
// likely a sign of incomplete code rather than faulty input.
|
// likely a sign of incomplete code rather than faulty input.
|
||||||
Nif::NIFFile nif(vfs->open(resourceName), resourceName);
|
Nif::NIFFile nif(resourceName);
|
||||||
|
|
||||||
if (nif.numRecords() < 1)
|
if (nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
warn("Found no records in NIF.");
|
warn("Found no records in NIF.");
|
||||||
|
@ -120,26 +92,25 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
||||||
assert(r != NULL);
|
assert(r != NULL);
|
||||||
|
|
||||||
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
|
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
warn("First record in file was not a node, but a " +
|
warn("First record in file was not a node, but a " +
|
||||||
r->recName.toString() + ". Skipping file.");
|
r->recName + ". Skipping file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasCollisionNode = hasRootCollisionNode(node);
|
bool hasCollisionNode = hasRootCollisionNode(node);
|
||||||
|
|
||||||
//do a first pass
|
//do a first pass
|
||||||
handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,false);
|
handleNode(node,0,NULL,hasCollisionNode,false,false);
|
||||||
|
|
||||||
//if collide = false, then it does a second pass which create a shape for raycasting.
|
//if collide = false, then it does a second pass which create a shape for raycasting.
|
||||||
if(cShape->collide == false)
|
if(cShape->collide == false)
|
||||||
{
|
{
|
||||||
handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,true);
|
handleNode(node,0,NULL,hasCollisionNode,false,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cShape->collide = hasCollisionNode&&cShape->collide;
|
//cShape->collide = hasCollisionNode&&cShape->collide;
|
||||||
|
|
||||||
struct TriangleMeshShape : public btBvhTriangleMeshShape
|
struct TriangleMeshShape : public btBvhTriangleMeshShape
|
||||||
{
|
{
|
||||||
|
@ -186,8 +157,9 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
|
const Nif::Transformation *trafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// Accumulate the flags from all the child nodes. This works for all
|
||||||
// the flags we currently use, at least.
|
// the flags we currently use, at least.
|
||||||
flags |= node->flags;
|
flags |= node->flags;
|
||||||
|
@ -221,18 +193,26 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//transfo of parents node + curent node
|
|
||||||
Ogre::Matrix3 finalRot;
|
|
||||||
Ogre::Vector3 finalPos;
|
|
||||||
float finalScale;
|
|
||||||
|
|
||||||
Nif::Transformation &final = *((Nif::Transformation*)node->trafo);
|
if (trafo)
|
||||||
Ogre::Vector3 nodePos = getVector(&final);
|
{
|
||||||
Ogre::Matrix3 nodeRot = getMatrix(&final);
|
|
||||||
|
|
||||||
finalPos = nodePos + parentPos;
|
// Get a non-const reference to the node's data, since we're
|
||||||
finalRot = parentRot*nodeRot;
|
// overwriting it. TODO: Is this necessary?
|
||||||
finalScale = final.scale*parentScale;
|
Nif::Transformation &final = node->trafo;
|
||||||
|
|
||||||
|
// For both position and rotation we have that:
|
||||||
|
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
||||||
|
final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale;
|
||||||
|
final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale;
|
||||||
|
|
||||||
|
// Merge the rotations together
|
||||||
|
final.rotation = trafo->rotation * final.rotation;
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
final.scale *= trafo->scale;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// For NiNodes, loop through children
|
// For NiNodes, loop through children
|
||||||
|
@ -244,14 +224,14 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
{
|
{
|
||||||
if (list.has(i))
|
if (list.has(i))
|
||||||
{
|
{
|
||||||
handleNode(&list[i], flags,finalRot,finalPos,finalScale,hasCollisionNode,isCollisionNode,raycastingOnly);
|
handleNode(&list[i], flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode))
|
else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode))
|
||||||
{
|
{
|
||||||
cShape->collide = true;
|
cShape->collide = true;
|
||||||
handleNiTriShape(dynamic_cast<Nif::NiTriShape*>(node), flags,finalRot,finalPos,parentScale,raycastingOnly);
|
handleNiTriShape(dynamic_cast<Nif::NiTriShape*>(node), flags,node->trafo.rotation,node->trafo.pos,node->trafo.scale,raycastingOnly);
|
||||||
}
|
}
|
||||||
else if(node->recType == Nif::RC_RootCollisionNode)
|
else if(node->recType == Nif::RC_RootCollisionNode)
|
||||||
{
|
{
|
||||||
|
@ -260,7 +240,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
||||||
for (int i=0; i<n; i++)
|
for (int i=0; i<n; i++)
|
||||||
{
|
{
|
||||||
if (list.has(i))
|
if (list.has(i))
|
||||||
handleNode(&list[i], flags,finalRot,finalPos,finalScale,hasCollisionNode,true,raycastingOnly);
|
handleNode(&list[i], flags,&node->trafo, hasCollisionNode,true,raycastingOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,17 +272,19 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags
|
||||||
|
|
||||||
Nif::NiTriShapeData *data = shape->data.getPtr();
|
Nif::NiTriShapeData *data = shape->data.getPtr();
|
||||||
|
|
||||||
float* vertices = (float*)data->vertices.ptr;
|
float* vertices = &data->vertices[0];
|
||||||
unsigned short* triangles = (unsigned short*)data->triangles.ptr;
|
short* triangles = &data->triangles[0];
|
||||||
|
const Ogre::Matrix3 &rot = shape->trafo.rotation;
|
||||||
for(unsigned int i=0; i < data->triangles.length; i = i+3)
|
const Ogre::Vector3 &pos = shape->trafo.pos;
|
||||||
|
float scale = shape->trafo.scale;
|
||||||
|
for(unsigned int i=0; i < data->triangles.size(); i = i+3)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale);
|
Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale);
|
||||||
Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale);
|
Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale);
|
||||||
Ogre::Vector3 b3(vertices[triangles[i+2]*3]*parentScale,vertices[triangles[i+2]*3+1]*parentScale,vertices[triangles[i+2]*3+2]*parentScale);
|
Ogre::Vector3 b3(vertices[triangles[i+2]*3]*parentScale,vertices[triangles[i+2]*3+1]*parentScale,vertices[triangles[i+2]*3+2]*parentScale);
|
||||||
b1 = parentRot * b1 + parentPos;
|
b1 = pos + rot*b1*scale;
|
||||||
b2 = parentRot * b2 + parentPos;
|
b2 = pos + rot*b2*scale;
|
||||||
b3 = parentRot * b3 + parentPos;
|
b3 = pos + rot*b3*scale;
|
||||||
mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
|
mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,16 +46,6 @@ namespace Nif
|
||||||
class Node;
|
class Node;
|
||||||
class Transformation;
|
class Transformation;
|
||||||
class NiTriShape;
|
class NiTriShape;
|
||||||
class Vector;
|
|
||||||
class Matrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Mangle
|
|
||||||
{
|
|
||||||
namespace VFS
|
|
||||||
{
|
|
||||||
class OgreVFS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NifBullet
|
namespace NifBullet
|
||||||
|
@ -68,7 +58,7 @@ class ManualBulletShapeLoader : public BulletShapeLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ManualBulletShapeLoader():resourceGroup("General"){vfs = 0;}
|
ManualBulletShapeLoader():resourceGroup("General"){}
|
||||||
virtual ~ManualBulletShapeLoader();
|
virtual ~ManualBulletShapeLoader();
|
||||||
|
|
||||||
void warn(std::string msg)
|
void warn(std::string msg)
|
||||||
|
@ -95,22 +85,18 @@ public:
|
||||||
void load(const std::string &name,const std::string &group);
|
void load(const std::string &name,const std::string &group);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ogre::Matrix3 getMatrix(Nif::Transformation* tr);
|
btQuaternion getbtQuat(Ogre::Matrix3 &m);
|
||||||
|
|
||||||
Ogre::Vector3 getVector(Nif::Transformation* tr);
|
btVector3 getbtVector(Ogre::Vector3 &v);
|
||||||
|
|
||||||
btQuaternion getbtQuat(Ogre::Matrix3 m);
|
|
||||||
|
|
||||||
btVector3 getbtVector(Nif::Vector v);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Parse a node.
|
*Parse a node.
|
||||||
*/
|
*/
|
||||||
void handleNode(Nif::Node *node, int flags,
|
void handleNode(Nif::Node *node, int flags,
|
||||||
Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly);
|
const Nif::Transformation *trafo, bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Helpler function
|
*Helper function
|
||||||
*/
|
*/
|
||||||
bool hasRootCollisionNode(Nif::Node* node);
|
bool hasRootCollisionNode(Nif::Node* node);
|
||||||
|
|
||||||
|
@ -119,8 +105,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly);
|
void handleNiTriShape(Nif::NiTriShape *shape, int flags,Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScales,bool raycastingOnly);
|
||||||
|
|
||||||
Mangle::VFS::OgreVFS *vfs;
|
|
||||||
|
|
||||||
std::string resourceName;
|
std::string resourceName;
|
||||||
std::string resourceGroup;
|
std::string resourceGroup;
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,7 @@
|
||||||
typedef unsigned char ubyte;
|
typedef unsigned char ubyte;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Ogre;
|
|
||||||
using namespace Nif;
|
using namespace Nif;
|
||||||
using namespace Mangle::VFS;
|
|
||||||
using namespace Misc;
|
using namespace Misc;
|
||||||
using namespace NifOgre;
|
using namespace NifOgre;
|
||||||
|
|
||||||
|
@ -72,21 +70,6 @@ void NIFLoader::fail(string msg)
|
||||||
assert(1);
|
assert(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 NIFLoader::convertVector3(const Nif::Vector& vec)
|
|
||||||
{
|
|
||||||
return Ogre::Vector3(vec.array);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion NIFLoader::convertRotation(const Nif::Matrix& rot)
|
|
||||||
{
|
|
||||||
Real matrix[3][3];
|
|
||||||
|
|
||||||
for (int i=0; i<3; i++)
|
|
||||||
for (int j=0; j<3; j++)
|
|
||||||
matrix[i][j] = rot.v[i].array[j];
|
|
||||||
|
|
||||||
return Quaternion(Matrix3(matrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper class that computes the bounding box and of a mesh
|
// Helper class that computes the bounding box and of a mesh
|
||||||
class BoundsFinder
|
class BoundsFinder
|
||||||
|
@ -222,11 +205,11 @@ void NIFLoader::setOutputAnimFiles(bool output){
|
||||||
void NIFLoader::setVerbosePath(std::string path){
|
void NIFLoader::setVerbosePath(std::string path){
|
||||||
verbosePath = path;
|
verbosePath = path;
|
||||||
}
|
}
|
||||||
void NIFLoader::createMaterial(const String &name,
|
void NIFLoader::createMaterial(const Ogre::String &name,
|
||||||
const Vector &ambient,
|
const Ogre::Vector3 &ambient,
|
||||||
const Vector &diffuse,
|
const Ogre::Vector3 &diffuse,
|
||||||
const Vector &specular,
|
const Ogre::Vector3 &specular,
|
||||||
const Vector &emissive,
|
const Ogre::Vector3 &emissive,
|
||||||
float glossiness, float alpha,
|
float glossiness, float alpha,
|
||||||
int alphaFlags, float alphaTest,
|
int alphaFlags, float alphaTest,
|
||||||
const String &texName, bool vertexColor)
|
const String &texName, bool vertexColor)
|
||||||
|
@ -309,7 +292,7 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
|
|
||||||
// Takes a name and adds a unique part to it. This is just used to
|
// Takes a name and adds a unique part to it. This is just used to
|
||||||
// make sure that all materials are given unique names.
|
// make sure that all materials are given unique names.
|
||||||
String NIFLoader::getUniqueName(const String &input)
|
Ogre::String NIFLoader::getUniqueName(const Ogre::String &input)
|
||||||
{
|
{
|
||||||
static int addon = 0;
|
static int addon = 0;
|
||||||
static char buf[8];
|
static char buf[8];
|
||||||
|
@ -325,29 +308,25 @@ String NIFLoader::getUniqueName(const String &input)
|
||||||
// does not, change the string IN PLACE to say .dds instead and try
|
// does not, change the string IN PLACE to say .dds instead and try
|
||||||
// that. The texture may still not exist, but no information of value
|
// that. The texture may still not exist, but no information of value
|
||||||
// is lost in that case.
|
// is lost in that case.
|
||||||
void NIFLoader::findRealTexture(String &texName)
|
void NIFLoader::findRealTexture(Ogre::String &texName)
|
||||||
{
|
{
|
||||||
assert(vfs);
|
if(Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName))
|
||||||
if (vfs->isFile(texName)) return;
|
return;
|
||||||
|
|
||||||
int len = texName.size();
|
|
||||||
if (len < 4) return;
|
|
||||||
|
|
||||||
// Change texture extension to .dds
|
// Change texture extension to .dds
|
||||||
texName[len-3] = 'd';
|
Ogre::String::size_type pos = texName.rfind('.');
|
||||||
texName[len-2] = 'd';
|
texName.replace(pos, texName.length(), ".dds");
|
||||||
texName[len-1] = 's';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle node at top
|
//Handle node at top
|
||||||
|
|
||||||
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given
|
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given
|
||||||
// mesh.
|
// mesh.
|
||||||
void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std::list<VertexBoneAssignment> &vertexBoneAssignments)
|
void NIFLoader::createOgreSubMesh(NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &vertexBoneAssignments)
|
||||||
{
|
{
|
||||||
// cout << "s:" << shape << "\n";
|
// cout << "s:" << shape << "\n";
|
||||||
NiTriShapeData *data = shape->data.getPtr();
|
NiTriShapeData *data = shape->data.getPtr();
|
||||||
SubMesh *sub = mesh->createSubMesh(shape->name.toString());
|
Ogre::SubMesh *sub = mesh->createSubMesh(shape->name);
|
||||||
|
|
||||||
int nextBuf = 0;
|
int nextBuf = 0;
|
||||||
|
|
||||||
|
@ -355,27 +334,27 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
// great.
|
// great.
|
||||||
|
|
||||||
// Add vertices
|
// Add vertices
|
||||||
int numVerts = data->vertices.length / 3;
|
int numVerts = data->vertices.size() / 3;
|
||||||
sub->vertexData = new VertexData();
|
sub->vertexData = new Ogre::VertexData();
|
||||||
sub->vertexData->vertexCount = numVerts;
|
sub->vertexData->vertexCount = numVerts;
|
||||||
sub->useSharedVertices = false;
|
sub->useSharedVertices = false;
|
||||||
|
|
||||||
VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
|
Ogre::VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
|
||||||
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION);
|
decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
|
||||||
|
|
||||||
HardwareVertexBufferSharedPtr vbuf =
|
Ogre::HardwareVertexBufferSharedPtr vbuf =
|
||||||
HardwareBufferManager::getSingleton().createVertexBuffer(
|
Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT3),
|
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
|
||||||
numVerts, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
|
numVerts, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
|
||||||
|
|
||||||
if(flip)
|
if(flip)
|
||||||
{
|
{
|
||||||
float *datamod = new float[data->vertices.length];
|
float *datamod = new float[data->vertices.size()];
|
||||||
//std::cout << "Shape" << shape->name.toString() << "\n";
|
//std::cout << "Shape" << shape->name.toString() << "\n";
|
||||||
for(int i = 0; i < numVerts; i++)
|
for(int i = 0; i < numVerts; i++)
|
||||||
{
|
{
|
||||||
int index = i * 3;
|
int index = i * 3;
|
||||||
const float *pos = data->vertices.ptr + index;
|
const float *pos = &data->vertices[index];
|
||||||
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
|
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
|
||||||
original = mTransform * original;
|
original = mTransform * original;
|
||||||
mBoundingBox.merge(original);
|
mBoundingBox.merge(original);
|
||||||
|
@ -388,30 +367,30 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false);
|
vbuf->writeData(0, vbuf->getSizeInBytes(), &data->vertices[0], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
|
Ogre::VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
|
||||||
if (data->normals.length)
|
if (data->normals.size())
|
||||||
{
|
{
|
||||||
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
|
decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
|
||||||
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT3),
|
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
|
||||||
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
|
numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
|
||||||
|
|
||||||
if(flip)
|
if(flip)
|
||||||
{
|
{
|
||||||
Quaternion rotation = mTransform.extractQuaternion();
|
Ogre::Quaternion rotation = mTransform.extractQuaternion();
|
||||||
rotation.normalise();
|
rotation.normalise();
|
||||||
|
|
||||||
float *datamod = new float[data->normals.length];
|
float *datamod = new float[data->normals.size()];
|
||||||
for(int i = 0; i < numVerts; i++)
|
for(int i = 0; i < numVerts; i++)
|
||||||
{
|
{
|
||||||
int index = i * 3;
|
int index = i * 3;
|
||||||
const float *pos = data->normals.ptr + index;
|
const float *pos = &data->normals[index];
|
||||||
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
|
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
|
||||||
original = rotation * original;
|
original = rotation * original;
|
||||||
if (mNormaliseNormals)
|
if (mNormaliseNormals)
|
||||||
|
@ -429,49 +408,49 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false);
|
vbuf->writeData(0, vbuf->getSizeInBytes(), &data->normals[0], false);
|
||||||
}
|
}
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vertex colors
|
// Vertex colors
|
||||||
if (data->colors.length)
|
if (data->colors.size())
|
||||||
{
|
{
|
||||||
const float *colors = data->colors.ptr;
|
const float *colors = &data->colors[0];
|
||||||
RenderSystem* rs = Root::getSingleton().getRenderSystem();
|
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
|
||||||
std::vector<RGBA> colorsRGB(numVerts);
|
std::vector<Ogre::RGBA> colorsRGB(numVerts);
|
||||||
RGBA *pColour = &colorsRGB.front();
|
Ogre::RGBA *pColour = &colorsRGB.front();
|
||||||
for (int i=0; i<numVerts; i++)
|
for (int i=0; i<numVerts; i++)
|
||||||
{
|
{
|
||||||
rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2],
|
rs->convertColourValue(Ogre::ColourValue(colors[0],colors[1],colors[2],
|
||||||
colors[3]),pColour++);
|
colors[3]),pColour++);
|
||||||
colors += 4;
|
colors += 4;
|
||||||
}
|
}
|
||||||
decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE);
|
decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
|
||||||
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_COLOUR),
|
Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR),
|
||||||
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true);
|
vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true);
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->uvlist.length)
|
if (data->uvlist.size())
|
||||||
{
|
{
|
||||||
|
|
||||||
decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
|
decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
|
||||||
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT2),
|
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2),
|
||||||
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY,false);
|
numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,false);
|
||||||
|
|
||||||
if(flip)
|
if(flip)
|
||||||
{
|
{
|
||||||
float *datamod = new float[data->uvlist.length];
|
float *datamod = new float[data->uvlist.size()];
|
||||||
|
|
||||||
for(unsigned int i = 0; i < data->uvlist.length; i+=2){
|
for(unsigned int i = 0; i < data->uvlist.size(); i+=2){
|
||||||
float x = *(data->uvlist.ptr + i);
|
float x = data->uvlist[i];
|
||||||
|
|
||||||
float y = *(data->uvlist.ptr + i + 1);
|
float y = data->uvlist[i + 1];
|
||||||
|
|
||||||
datamod[i] =x;
|
datamod[i] =x;
|
||||||
datamod[i + 1] =y;
|
datamod[i + 1] =y;
|
||||||
|
@ -480,36 +459,34 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
delete [] datamod;
|
delete [] datamod;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false);
|
vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[0], false);
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triangle faces - The total number of triangle points
|
// Triangle faces - The total number of triangle points
|
||||||
int numFaces = data->triangles.length;
|
int numFaces = data->triangles.size();
|
||||||
|
|
||||||
if (numFaces)
|
if (numFaces)
|
||||||
{
|
{
|
||||||
|
|
||||||
sub->indexData->indexCount = numFaces;
|
sub->indexData->indexCount = numFaces;
|
||||||
sub->indexData->indexStart = 0;
|
sub->indexData->indexStart = 0;
|
||||||
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
|
Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
|
||||||
createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
|
createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, numFaces,
|
||||||
numFaces,
|
Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true);
|
||||||
HardwareBuffer::HBU_STATIC_WRITE_ONLY, true);
|
|
||||||
|
|
||||||
if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){
|
if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){
|
||||||
|
|
||||||
sub->indexData->indexBuffer = ibuf;
|
sub->indexData->indexBuffer = ibuf;
|
||||||
|
|
||||||
uint16 *datamod = new uint16[numFaces];
|
uint16_t *datamod = new uint16_t[numFaces];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (size_t i = 0; i < sub->indexData->indexCount; i+=3)
|
for (size_t i = 0; i < sub->indexData->indexCount; i+=3)
|
||||||
{
|
{
|
||||||
|
|
||||||
const short *pos = data->triangles.ptr + index;
|
const short *pos = &data->triangles[index];
|
||||||
uint16 i0 = (uint16) *(pos+0);
|
uint16_t i0 = (uint16_t) *(pos+0);
|
||||||
uint16 i1 = (uint16) *(pos+1);
|
uint16_t i1 = (uint16_t) *(pos+1);
|
||||||
uint16 i2 = (uint16) *(pos+2);
|
uint16_t i2 = (uint16_t) *(pos+2);
|
||||||
|
|
||||||
//std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n";
|
//std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n";
|
||||||
|
|
||||||
|
@ -526,7 +503,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false);
|
ibuf->writeData(0, ibuf->getSizeInBytes(), &data->triangles[0], false);
|
||||||
sub->indexData->indexBuffer = ibuf;
|
sub->indexData->indexBuffer = ibuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,7 +512,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
|
|
||||||
//add vertex bone assignments
|
//add vertex bone assignments
|
||||||
|
|
||||||
for (std::list<VertexBoneAssignment>::iterator it = vertexBoneAssignments.begin();
|
for (std::list<Ogre::VertexBoneAssignment>::iterator it = vertexBoneAssignments.begin();
|
||||||
it != vertexBoneAssignments.end(); it++)
|
it != vertexBoneAssignments.end(); it++)
|
||||||
{
|
{
|
||||||
sub->addBoneAssignment(*it);
|
sub->addBoneAssignment(*it);
|
||||||
|
@ -546,23 +523,8 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
|
|
||||||
// Helper math functions. Reinventing linear algebra for the win!
|
// Helper math functions. Reinventing linear algebra for the win!
|
||||||
|
|
||||||
// Computes B = AxB (matrix*matrix)
|
|
||||||
static void matrixMul(const Matrix &A, Matrix &B)
|
|
||||||
{
|
|
||||||
for (int i=0;i<3;i++)
|
|
||||||
{
|
|
||||||
float a = B.v[0].array[i];
|
|
||||||
float b = B.v[1].array[i];
|
|
||||||
float c = B.v[2].array[i];
|
|
||||||
|
|
||||||
B.v[0].array[i] = a*A.v[0].array[0] + b*A.v[0].array[1] + c*A.v[0].array[2];
|
|
||||||
B.v[1].array[i] = a*A.v[1].array[0] + b*A.v[1].array[1] + c*A.v[1].array[2];
|
|
||||||
B.v[2].array[i] = a*A.v[2].array[0] + b*A.v[2].array[1] + c*A.v[2].array[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Computes C = B + AxC*scale
|
// Computes C = B + AxC*scale
|
||||||
static void vectorMulAdd(const Matrix &A, const Vector &B, float *C, float scale)
|
static void vectorMulAdd(const Ogre::Matrix3 &A, const Ogre::Vector3 &B, float *C, float scale)
|
||||||
{
|
{
|
||||||
// Keep the original values
|
// Keep the original values
|
||||||
float a = C[0];
|
float a = C[0];
|
||||||
|
@ -571,11 +533,11 @@ static void vectorMulAdd(const Matrix &A, const Vector &B, float *C, float scale
|
||||||
|
|
||||||
// Perform matrix multiplication, scaling and addition
|
// Perform matrix multiplication, scaling and addition
|
||||||
for (int i=0;i<3;i++)
|
for (int i=0;i<3;i++)
|
||||||
C[i] = B.array[i] + (a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2])*scale;
|
C[i] = B[i] + (a*A[i][0] + b*A[i][1] + c*A[i][2])*scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes B = AxB (matrix*vector)
|
// Computes B = AxB (matrix*vector)
|
||||||
static void vectorMul(const Matrix &A, float *C)
|
static void vectorMul(const Ogre::Matrix3 &A, float *C)
|
||||||
{
|
{
|
||||||
// Keep the original values
|
// Keep the original values
|
||||||
float a = C[0];
|
float a = C[0];
|
||||||
|
@ -584,7 +546,7 @@ static void vectorMul(const Matrix &A, float *C)
|
||||||
|
|
||||||
// Perform matrix multiplication, scaling and addition
|
// Perform matrix multiplication, scaling and addition
|
||||||
for (int i=0;i<3;i++)
|
for (int i=0;i<3;i++)
|
||||||
C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2];
|
C[i] = a*A[i][0] + b*A[i][1] + c*A[i][2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -619,7 +581,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Material name for this submesh, if any
|
// Material name for this submesh, if any
|
||||||
String material;
|
Ogre::String material;
|
||||||
|
|
||||||
// Skip the entire material phase for hidden nodes
|
// Skip the entire material phase for hidden nodes
|
||||||
if (!hidden)
|
if (!hidden)
|
||||||
|
@ -652,14 +614,12 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture
|
// Texture
|
||||||
String texName;
|
Ogre::String texName;
|
||||||
if (t && t->textures[0].inUse)
|
if (t && t->textures[0].inUse)
|
||||||
{
|
{
|
||||||
NiSourceTexture *st = t->textures[0].texture.getPtr();
|
NiSourceTexture *st = t->textures[0].texture.getPtr();
|
||||||
if (st->external)
|
if (st->external)
|
||||||
{
|
{
|
||||||
SString tname = st->filename;
|
|
||||||
|
|
||||||
/* findRealTexture checks if the file actually
|
/* findRealTexture checks if the file actually
|
||||||
exists. If it doesn't, and the name ends in .tga, it
|
exists. If it doesn't, and the name ends in .tga, it
|
||||||
will try replacing the extension with .dds instead
|
will try replacing the extension with .dds instead
|
||||||
|
@ -673,7 +633,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
problem since all the nif data is stored in a local
|
problem since all the nif data is stored in a local
|
||||||
throwaway buffer.
|
throwaway buffer.
|
||||||
*/
|
*/
|
||||||
texName = "textures\\" + tname.toString();
|
texName = "textures\\" + st->filename;
|
||||||
findRealTexture(texName);
|
findRealTexture(texName);
|
||||||
}
|
}
|
||||||
else warn("Found internal texture, ignoring.");
|
else warn("Found internal texture, ignoring.");
|
||||||
|
@ -685,7 +645,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
alphaFlags = a->flags;
|
alphaFlags = a->flags;
|
||||||
alphaTest = a->data->threshold;
|
alphaTest = a->data.threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Material
|
// Material
|
||||||
|
@ -700,7 +660,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
if (m)
|
if (m)
|
||||||
{
|
{
|
||||||
// Use NiMaterialProperty data to create the data
|
// Use NiMaterialProperty data to create the data
|
||||||
const S_MaterialProperty *d = m->data;
|
const S_MaterialProperty *d = &m->data;
|
||||||
|
|
||||||
std::multimap<std::string,std::string>::iterator itr = MaterialMap.find(texName);
|
std::multimap<std::string,std::string>::iterator itr = MaterialMap.find(texName);
|
||||||
std::multimap<std::string,std::string>::iterator lastElement;
|
std::multimap<std::string,std::string>::iterator lastElement;
|
||||||
|
@ -727,14 +687,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
{
|
{
|
||||||
// We only have a texture name. Create a default
|
// We only have a texture name. Create a default
|
||||||
// material for it.
|
// material for it.
|
||||||
Vector zero, one;
|
const Ogre::Vector3 zero(0.0f), one(1.0f);
|
||||||
for (int i=0; i<3;i++)
|
createMaterial(material, one, one, zero, zero, 0.0f, 1.0f,
|
||||||
{
|
|
||||||
zero.array[i] = 0.0;
|
|
||||||
one.array[i] = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
createMaterial(material, one, one, zero, zero, 0.0, 1.0,
|
|
||||||
alphaFlags, alphaTest, texName, shape->data->colors.length != 0);
|
alphaFlags, alphaTest, texName, shape->data->colors.length != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,12 +701,12 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
level.
|
level.
|
||||||
*/
|
*/
|
||||||
NiTriShapeData *data = shape->data.getPtr();
|
NiTriShapeData *data = shape->data.getPtr();
|
||||||
int numVerts = data->vertices.length / 3;
|
int numVerts = data->vertices.size() / 3;
|
||||||
|
|
||||||
float *ptr = (float*)data->vertices.ptr;
|
float *ptr = (float*)&data->vertices[0];
|
||||||
float *optr = ptr;
|
float *optr = ptr;
|
||||||
|
|
||||||
std::list<VertexBoneAssignment> vertexBoneAssignments;
|
std::list<Ogre::VertexBoneAssignment> vertexBoneAssignments;
|
||||||
|
|
||||||
Nif::NiTriShapeCopy copy = shape->clone();
|
Nif::NiTriShapeCopy copy = shape->clone();
|
||||||
|
|
||||||
|
@ -780,14 +734,14 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
std::vector<Ogre::Vector3> vertexPosOriginal(numVerts, Ogre::Vector3::ZERO);
|
std::vector<Ogre::Vector3> vertexPosOriginal(numVerts, Ogre::Vector3::ZERO);
|
||||||
std::vector<Ogre::Vector3> vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO);
|
std::vector<Ogre::Vector3> vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO);
|
||||||
|
|
||||||
float *ptrNormals = (float*)data->normals.ptr;
|
float *ptrNormals = (float*)&data->normals[0];
|
||||||
//the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex]
|
//the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex]
|
||||||
//the first one contains a link to the bone, the second vertex transformation
|
//the first one contains a link to the bone, the second vertex transformation
|
||||||
//relative to the bone
|
//relative to the bone
|
||||||
int boneIndex = 0;
|
int boneIndex = 0;
|
||||||
Bone *bonePtr;
|
Ogre::Bone *bonePtr;
|
||||||
Vector3 vecPos;
|
Ogre::Vector3 vecPos;
|
||||||
Quaternion vecRot;
|
Ogre::Quaternion vecRot;
|
||||||
|
|
||||||
std::vector<NiSkinData::BoneInfo> boneList = shape->skin->data->bones;
|
std::vector<NiSkinData::BoneInfo> boneList = shape->skin->data->bones;
|
||||||
|
|
||||||
|
@ -801,33 +755,33 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
{
|
{
|
||||||
if(mSkel.isNull())
|
if(mSkel.isNull())
|
||||||
{
|
{
|
||||||
std::cout << "No skeleton for :" << shape->skin->bones[boneIndex].name.toString() << std::endl;
|
std::cout << "No skeleton for :" << shape->skin->bones[boneIndex].name << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//get the bone from bones array of skindata
|
//get the bone from bones array of skindata
|
||||||
if(!mSkel->hasBone(shape->skin->bones[boneIndex].name.toString()))
|
if(!mSkel->hasBone(shape->skin->bones[boneIndex].name))
|
||||||
std::cout << "We don't have this bone";
|
std::cout << "We don't have this bone";
|
||||||
bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString());
|
bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name);
|
||||||
|
|
||||||
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
||||||
|
|
||||||
|
|
||||||
Nif::NiSkinData::BoneInfoCopy boneinfocopy;
|
Nif::NiSkinData::BoneInfoCopy boneinfocopy;
|
||||||
boneinfocopy.trafo.rotation = convertRotation(it->trafo->rotation);
|
boneinfocopy.trafo.rotation = it->trafo.rotation;
|
||||||
boneinfocopy.trafo.trans = convertVector3(it->trafo->trans);
|
boneinfocopy.trafo.trans = it->trafo.trans;
|
||||||
boneinfocopy.bonename = shape->skin->bones[boneIndex].name.toString();
|
boneinfocopy.bonename = shape->skin->bones[boneIndex].name;
|
||||||
boneinfocopy.bonehandle = bonePtr->getHandle();
|
boneinfocopy.bonehandle = bonePtr->getHandle();
|
||||||
copy.boneinfo.push_back(boneinfocopy);
|
copy.boneinfo.push_back(boneinfocopy);
|
||||||
for (unsigned int i=0; i<it->weights.length; i++)
|
for (unsigned int i=0; i<it->weights.size(); i++)
|
||||||
{
|
{
|
||||||
vecPos = bonePtr->_getDerivedPosition() +
|
vecPos = bonePtr->_getDerivedPosition() +
|
||||||
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
|
bonePtr->_getDerivedOrientation() * it->trafo.trans;
|
||||||
|
|
||||||
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
|
vecRot = bonePtr->_getDerivedOrientation() * it->trafo.rotation;
|
||||||
unsigned int verIndex = (it->weights.ptr + i)->vertex;
|
unsigned int verIndex = it->weights[i].vertex;
|
||||||
//boneinfo.weights.push_back(*(it->weights.ptr + i));
|
//boneinfo.weights.push_back(*(it->weights.ptr + i));
|
||||||
Nif::NiSkinData::IndividualWeight ind;
|
Nif::NiSkinData::IndividualWeight ind;
|
||||||
ind.weight = (it->weights.ptr + i)->weight;
|
ind.weight = it->weights[i].weight;
|
||||||
ind.boneinfocopyindex = copy.boneinfo.size() - 1;
|
ind.boneinfocopyindex = copy.boneinfo.size() - 1;
|
||||||
if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end())
|
if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end())
|
||||||
{
|
{
|
||||||
|
@ -844,9 +798,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
if (vertexPosAbsolut[verIndex] == false)
|
if (vertexPosAbsolut[verIndex] == false)
|
||||||
{
|
{
|
||||||
//apply transformation to the vertices
|
//apply transformation to the vertices
|
||||||
Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3);
|
Ogre::Vector3 absVertPos = vecPos + vecRot * Ogre::Vector3(ptr + verIndex *3);
|
||||||
absVertPos = absVertPos * (it->weights.ptr + i)->weight;
|
absVertPos = absVertPos * it->weights[i].weight;
|
||||||
vertexPosOriginal[verIndex] = Vector3(ptr + verIndex *3);
|
vertexPosOriginal[verIndex] = Ogre::Vector3(ptr + verIndex *3);
|
||||||
|
|
||||||
mBoundingBox.merge(absVertPos);
|
mBoundingBox.merge(absVertPos);
|
||||||
//convert it back to float *
|
//convert it back to float *
|
||||||
|
@ -855,11 +809,11 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
//apply rotation to the normals (not every vertex has a normal)
|
//apply rotation to the normals (not every vertex has a normal)
|
||||||
//FIXME: I guessed that vertex[i] = normal[i], is that true?
|
//FIXME: I guessed that vertex[i] = normal[i], is that true?
|
||||||
if (verIndex < data->normals.length)
|
if (verIndex < data->normals.size())
|
||||||
{
|
{
|
||||||
Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3);
|
Ogre::Vector3 absNormalsPos = vecRot * Ogre::Vector3(ptrNormals + verIndex *3);
|
||||||
absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight;
|
absNormalsPos = absNormalsPos * it->weights[i].weight;
|
||||||
vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3);
|
vertexNormalOriginal[verIndex] = Ogre::Vector3(ptrNormals + verIndex *3);
|
||||||
|
|
||||||
for (int j=0; j<3; j++)
|
for (int j=0; j<3; j++)
|
||||||
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
||||||
|
@ -869,9 +823,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex];
|
Ogre::Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex];
|
||||||
absVertPos = absVertPos * (it->weights.ptr + i)->weight;
|
absVertPos = absVertPos * it->weights[i].weight;
|
||||||
Vector3 old = Vector3(ptr + verIndex *3);
|
Ogre::Vector3 old = Ogre::Vector3(ptr + verIndex *3);
|
||||||
absVertPos = absVertPos + old;
|
absVertPos = absVertPos + old;
|
||||||
|
|
||||||
mBoundingBox.merge(absVertPos);
|
mBoundingBox.merge(absVertPos);
|
||||||
|
@ -881,11 +835,11 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
//apply rotation to the normals (not every vertex has a normal)
|
//apply rotation to the normals (not every vertex has a normal)
|
||||||
//FIXME: I guessed that vertex[i] = normal[i], is that true?
|
//FIXME: I guessed that vertex[i] = normal[i], is that true?
|
||||||
if (verIndex < data->normals.length)
|
if (verIndex < data->normals.size())
|
||||||
{
|
{
|
||||||
Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex];
|
Ogre::Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex];
|
||||||
absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight;
|
absNormalsPos = absNormalsPos * it->weights[i].weight;
|
||||||
Vector3 oldNormal = Vector3(ptrNormals + verIndex *3);
|
Ogre::Vector3 oldNormal = Ogre::Vector3(ptrNormals + verIndex *3);
|
||||||
absNormalsPos = absNormalsPos + oldNormal;
|
absNormalsPos = absNormalsPos + oldNormal;
|
||||||
|
|
||||||
for (int j=0; j<3; j++)
|
for (int j=0; j<3; j++)
|
||||||
|
@ -894,10 +848,10 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VertexBoneAssignment vba;
|
Ogre::VertexBoneAssignment vba;
|
||||||
vba.boneIndex = bonePtr->getHandle();
|
vba.boneIndex = bonePtr->getHandle();
|
||||||
vba.vertexIndex = verIndex;
|
vba.vertexIndex = verIndex;
|
||||||
vba.weight = (it->weights.ptr + i)->weight;
|
vba.weight = it->weights[i].weight;
|
||||||
|
|
||||||
|
|
||||||
vertexBoneAssignments.push_back(vba);
|
vertexBoneAssignments.push_back(vba);
|
||||||
|
@ -914,12 +868,12 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
copy.boneSequence = boneSequence;
|
copy.boneSequence = boneSequence;
|
||||||
// Rotate, scale and translate all the vertices,
|
// Rotate, scale and translate all the vertices,
|
||||||
const Matrix &rot = shape->trafo->rotation;
|
const Ogre::Matrix3 &rot = shape->trafo.rotation;
|
||||||
const Vector &pos = shape->trafo->pos;
|
const Ogre::Vector3 &pos = shape->trafo.pos;
|
||||||
float scale = shape->trafo->scale;
|
float scale = shape->trafo.scale;
|
||||||
|
|
||||||
copy.trafo.trans = convertVector3(original.pos);
|
copy.trafo.trans = original.pos;
|
||||||
copy.trafo.rotation = convertRotation(original.rotation);
|
copy.trafo.rotation = original.rotation;
|
||||||
copy.trafo.scale = original.scale;
|
copy.trafo.scale = original.scale;
|
||||||
//We don't use velocity for anything yet, so it does not need to be saved
|
//We don't use velocity for anything yet, so it does not need to be saved
|
||||||
|
|
||||||
|
@ -927,15 +881,15 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
for (int i=0; i<numVerts; i++)
|
for (int i=0; i<numVerts; i++)
|
||||||
{
|
{
|
||||||
vectorMulAdd(rot, pos, ptr, scale);
|
vectorMulAdd(rot, pos, ptr, scale);
|
||||||
Ogre::Vector3 absVertPos = Ogre::Vector3(*(ptr + 3 * i), *(ptr + 3 * i + 1), *(ptr + 3 * i + 2));
|
Ogre::Vector3 absVertPos = Ogre::Vector3(ptr);
|
||||||
mBoundingBox.merge(absVertPos);
|
mBoundingBox.merge(absVertPos);
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember to rotate all the vertex normals as well
|
// Remember to rotate all the vertex normals as well
|
||||||
if (data->normals.length)
|
if (data->normals.size())
|
||||||
{
|
{
|
||||||
ptr = (float*)data->normals.ptr;
|
ptr = (float*)&data->normals[0];
|
||||||
for (int i=0; i<numVerts; i++)
|
for (int i=0; i<numVerts; i++)
|
||||||
{
|
{
|
||||||
vectorMul(rot, ptr);
|
vectorMul(rot, ptr);
|
||||||
|
@ -947,7 +901,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
boneIndex = mSkel->getNumBones() - 1;
|
boneIndex = mSkel->getNumBones() - 1;
|
||||||
for(int i = 0; i < numVerts; i++){
|
for(int i = 0; i < numVerts; i++){
|
||||||
VertexBoneAssignment vba;
|
Ogre::VertexBoneAssignment vba;
|
||||||
vba.boneIndex = boneIndex;
|
vba.boneIndex = boneIndex;
|
||||||
vba.vertexIndex = i;
|
vba.vertexIndex = i;
|
||||||
vba.weight = 1;
|
vba.weight = 1;
|
||||||
|
@ -971,15 +925,15 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
void NIFLoader::calculateTransform()
|
void NIFLoader::calculateTransform()
|
||||||
{
|
{
|
||||||
// Calculate transform
|
// Calculate transform
|
||||||
Matrix4 transform = Matrix4::IDENTITY;
|
Ogre::Matrix4 transform = Ogre::Matrix4::IDENTITY;
|
||||||
transform = Matrix4::getScale(vector) * transform;
|
transform = Ogre::Matrix4::getScale(vector) * transform;
|
||||||
|
|
||||||
// Check whether we have to flip vertex winding.
|
// Check whether we have to flip vertex winding.
|
||||||
// We do have to, if we changed our right hand base.
|
// We do have to, if we changed our right hand base.
|
||||||
// We can test it by using the cross product from X and Y and see, if it is a non-negative
|
// We can test it by using the cross product from X and Y and see, if it is a non-negative
|
||||||
// projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet,
|
// projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet,
|
||||||
// but the test is cheap either way.
|
// but the test is cheap either way.
|
||||||
Matrix3 m3;
|
Ogre::Matrix3 m3;
|
||||||
transform.extract3x3Matrix(m3);
|
transform.extract3x3Matrix(m3);
|
||||||
|
|
||||||
if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0)
|
if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0)
|
||||||
|
@ -1042,7 +996,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
|
|
||||||
for(std::vector<Nif::NiTextKeyExtraData::TextKey>::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++)
|
for(std::vector<Nif::NiTextKeyExtraData::TextKey>::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++)
|
||||||
{
|
{
|
||||||
std::string text = textiter->text.toString();
|
std::string text = textiter->text;
|
||||||
|
|
||||||
replace(text.begin(), text.end(), '\n', '/');
|
replace(text.begin(), text.end(), '\n', '/');
|
||||||
|
|
||||||
|
@ -1073,7 +1027,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bone *bone = 0;
|
Ogre::Bone *bone = 0;
|
||||||
|
|
||||||
// create skeleton or add bones
|
// create skeleton or add bones
|
||||||
if (node->recType == RC_NiNode)
|
if (node->recType == RC_NiNode)
|
||||||
|
@ -1083,14 +1037,14 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
{
|
{
|
||||||
inTheSkeletonTree = true;
|
inTheSkeletonTree = true;
|
||||||
|
|
||||||
mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
mSkel = Ogre::SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
||||||
}
|
}
|
||||||
else if (!mSkel.isNull() && !parentBone)
|
else if (!mSkel.isNull() && !parentBone)
|
||||||
inTheSkeletonTree = false;
|
inTheSkeletonTree = false;
|
||||||
|
|
||||||
if (!mSkel.isNull()) //if there is a skeleton
|
if (!mSkel.isNull()) //if there is a skeleton
|
||||||
{
|
{
|
||||||
std::string name = node->name.toString();
|
std::string name = node->name;
|
||||||
|
|
||||||
// Quick-n-dirty workaround for the fact that several
|
// Quick-n-dirty workaround for the fact that several
|
||||||
// bones may have the same name.
|
// bones may have the same name.
|
||||||
|
@ -1103,30 +1057,29 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
parentBone->addChild(bone);
|
parentBone->addChild(bone);
|
||||||
|
|
||||||
bone->setInheritOrientation(true);
|
bone->setInheritOrientation(true);
|
||||||
bone->setPosition(convertVector3(node->trafo->pos));
|
bone->setPosition(node->trafo.pos);
|
||||||
bone->setOrientation(convertRotation(node->trafo->rotation));
|
bone->setOrientation(node->trafo.rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Transformation original = *(node->trafo);
|
Transformation original = node->trafo;
|
||||||
// Apply the parent transformation to this node. We overwrite the
|
// Apply the parent transformation to this node. We overwrite the
|
||||||
// existing data with the final transformation.
|
// existing data with the final transformation.
|
||||||
if (trafo)
|
if (trafo)
|
||||||
{
|
{
|
||||||
// Get a non-const reference to the node's data, since we're
|
// Get a non-const reference to the node's data, since we're
|
||||||
// overwriting it. TODO: Is this necessary?
|
// overwriting it. TODO: Is this necessary?
|
||||||
Transformation &final = *((Transformation*)node->trafo);
|
Transformation &final = node->trafo;
|
||||||
|
|
||||||
// For both position and rotation we have that:
|
// For both position and rotation we have that:
|
||||||
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
||||||
vectorMulAdd(trafo->rotation, trafo->pos, final.pos.array, trafo->scale);
|
final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale;
|
||||||
vectorMulAdd(trafo->rotation, trafo->velocity, final.velocity.array, trafo->scale);
|
final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale;
|
||||||
|
|
||||||
// Merge the rotations together
|
// Merge the rotations together
|
||||||
matrixMul(trafo->rotation, final.rotation);
|
final.rotation = trafo->rotation * final.rotation;
|
||||||
|
|
||||||
// Scalar values are so nice to deal with. Why can't everything
|
// Scale
|
||||||
// just be scalar?
|
|
||||||
final.scale *= trafo->scale;
|
final.scale *= trafo->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,12 +1092,12 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
{
|
{
|
||||||
|
|
||||||
if (list.has(i))
|
if (list.has(i))
|
||||||
handleNode(&list[i], flags, node->trafo, bounds, bone, boneSequence);
|
handleNode(&list[i], flags, &node->trafo, bounds, bone, boneSequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->recType == RC_NiTriShape && bNiTri)
|
else if (node->recType == RC_NiTriShape && bNiTri)
|
||||||
{
|
{
|
||||||
std::string nodename = node->name.toString();
|
std::string nodename = node->name;
|
||||||
|
|
||||||
if (triname == "")
|
if (triname == "")
|
||||||
{
|
{
|
||||||
|
@ -1159,7 +1112,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFLoader::loadResource(Resource *resource)
|
void NIFLoader::loadResource(Ogre::Resource *resource)
|
||||||
{
|
{
|
||||||
inTheSkeletonTree = false;
|
inTheSkeletonTree = false;
|
||||||
allanim.clear();
|
allanim.clear();
|
||||||
|
@ -1245,22 +1198,13 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
{
|
{
|
||||||
calculateTransform();
|
calculateTransform();
|
||||||
}
|
}
|
||||||
// Set up the VFS if it hasn't been done already
|
|
||||||
if (!vfs) vfs = new OgreVFS(resourceGroup);
|
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
mesh = dynamic_cast<Mesh*>(resource);
|
mesh = dynamic_cast<Ogre::Mesh*>(resource);
|
||||||
assert(mesh);
|
assert(mesh);
|
||||||
|
|
||||||
// Look it up
|
// Look it up
|
||||||
resourceName = mesh->getName();
|
resourceName = mesh->getName();
|
||||||
//std::cout << resourceName << "\n";
|
|
||||||
|
|
||||||
if (!vfs->isFile(resourceName))
|
|
||||||
{
|
|
||||||
warn("File "+resourceName+" not found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper that computes bounding boxes for us.
|
// Helper that computes bounding boxes for us.
|
||||||
BoundsFinder bounds;
|
BoundsFinder bounds;
|
||||||
|
@ -1269,8 +1213,7 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
// of the early stages of development. Right now we WANT to catch
|
// of the early stages of development. Right now we WANT to catch
|
||||||
// every error as early and intrusively as possible, as it's most
|
// every error as early and intrusively as possible, as it's most
|
||||||
// likely a sign of incomplete code rather than faulty input.
|
// likely a sign of incomplete code rather than faulty input.
|
||||||
NIFFile nif(vfs->open(resourceName), resourceName);
|
NIFFile nif(resourceName);
|
||||||
|
|
||||||
if (nif.numRecords() < 1)
|
if (nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
warn("Found no records in NIF.");
|
warn("Found no records in NIF.");
|
||||||
|
@ -1286,7 +1229,7 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
warn("First record in file was not a node, but a " +
|
warn("First record in file was not a node, but a " +
|
||||||
r->recName.toString() + ". Skipping file.");
|
r->recName + ". Skipping file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,7 +1253,7 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
|
|
||||||
if (f->timeStart >= 10000000000000000.0f)
|
if (f->timeStart >= 10000000000000000.0f)
|
||||||
continue;
|
continue;
|
||||||
data->setBonename(o->name.toString());
|
data->setBonename(o->name);
|
||||||
data->setStartTime(f->timeStart);
|
data->setStartTime(f->timeStart);
|
||||||
data->setStopTime(f->timeStop);
|
data->setStopTime(f->timeStop);
|
||||||
|
|
||||||
|
@ -1321,7 +1264,7 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
// set the bounding value.
|
// set the bounding value.
|
||||||
if (bounds.isValid())
|
if (bounds.isValid())
|
||||||
{
|
{
|
||||||
mesh->_setBounds(AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(),
|
mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(),
|
||||||
bounds.maxX(), bounds.maxY(), bounds.maxZ()));
|
bounds.maxX(), bounds.maxY(), bounds.maxZ()));
|
||||||
mesh->_setBoundingSphereRadius(bounds.getRadius());
|
mesh->_setBoundingSphereRadius(bounds.getRadius());
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1287,7 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
for(std::vector<Ogre::SubMesh*>::iterator iter = needBoneAssignments.begin(); iter != needBoneAssignments.end(); iter++)
|
for(std::vector<Ogre::SubMesh*>::iterator iter = needBoneAssignments.begin(); iter != needBoneAssignments.end(); iter++)
|
||||||
{
|
{
|
||||||
int boneIndex = mSkel->getNumBones() - 1;
|
int boneIndex = mSkel->getNumBones() - 1;
|
||||||
VertexBoneAssignment vba;
|
Ogre::VertexBoneAssignment vba;
|
||||||
vba.boneIndex = boneIndex;
|
vba.boneIndex = boneIndex;
|
||||||
vba.vertexIndex = 0;
|
vba.vertexIndex = 0;
|
||||||
vba.weight = 1;
|
vba.weight = 1;
|
||||||
|
@ -1363,20 +1306,19 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MeshPtr NIFLoader::load(const std::string &name,
|
Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group)
|
||||||
const std::string &group)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
MeshManager *m = MeshManager::getSingletonPtr();
|
Ogre::MeshManager *m = Ogre::MeshManager::getSingletonPtr();
|
||||||
// Check if the resource already exists
|
// Check if the resource already exists
|
||||||
ResourcePtr ptr = m->getByName(name, group);
|
Ogre::ResourcePtr ptr = m->getByName(name, group);
|
||||||
MeshPtr themesh;
|
Ogre::MeshPtr themesh;
|
||||||
if (!ptr.isNull()){
|
if (!ptr.isNull()){
|
||||||
themesh = MeshPtr(ptr);
|
themesh = Ogre::MeshPtr(ptr);
|
||||||
}
|
}
|
||||||
else // Nope, create a new one.
|
else // Nope, create a new one.
|
||||||
{
|
{
|
||||||
themesh = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
|
themesh = Ogre::MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
|
||||||
}
|
}
|
||||||
return themesh;
|
return themesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,17 +62,8 @@ namespace Nif
|
||||||
class Node;
|
class Node;
|
||||||
class Transformation;
|
class Transformation;
|
||||||
class NiTriShape;
|
class NiTriShape;
|
||||||
class Vector;
|
|
||||||
class Matrix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Mangle
|
|
||||||
{
|
|
||||||
namespace VFS
|
|
||||||
{
|
|
||||||
class OgreVFS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace NifOgre
|
namespace NifOgre
|
||||||
{
|
{
|
||||||
|
@ -110,9 +101,6 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
std::map<std::string, float>* getTextIndices(std::string name);
|
std::map<std::string, float>* getTextIndices(std::string name);
|
||||||
|
|
||||||
|
|
||||||
Ogre::Vector3 convertVector3(const Nif::Vector& vec);
|
|
||||||
Ogre::Quaternion convertRotation(const Nif::Matrix& rot);
|
|
||||||
|
|
||||||
void setOutputAnimFiles(bool output);
|
void setOutputAnimFiles(bool output);
|
||||||
void setVerbosePath(std::string path);
|
void setVerbosePath(std::string path);
|
||||||
|
|
||||||
|
@ -136,10 +124,10 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &vertexBoneAssignments);
|
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &vertexBoneAssignments);
|
||||||
|
|
||||||
void createMaterial(const Ogre::String &name,
|
void createMaterial(const Ogre::String &name,
|
||||||
const Nif::Vector &ambient,
|
const Ogre::Vector3 &ambient,
|
||||||
const Nif::Vector &diffuse,
|
const Ogre::Vector3 &diffuse,
|
||||||
const Nif::Vector &specular,
|
const Ogre::Vector3 &specular,
|
||||||
const Nif::Vector &emissive,
|
const Ogre::Vector3 &emissive,
|
||||||
float glossiness, float alpha,
|
float glossiness, float alpha,
|
||||||
int alphaFlags, float alphaTest,
|
int alphaFlags, float alphaTest,
|
||||||
const Ogre::String &texName,
|
const Ogre::String &texName,
|
||||||
|
@ -155,13 +143,6 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
return resourceName + ".skel";
|
return resourceName + ".skel";
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the interface to the Ogre resource system. It allows us to
|
|
||||||
// load NIFs from BSAs, in the file system and in any other place we
|
|
||||||
// tell Ogre to look (eg. in zip or rar files.) It's also used to
|
|
||||||
// check for the existence of texture files, so we can exchange the
|
|
||||||
// extension from .tga to .dds if the texture is missing.
|
|
||||||
Mangle::VFS::OgreVFS *vfs;
|
|
||||||
|
|
||||||
std::string verbosePath;
|
std::string verbosePath;
|
||||||
std::string resourceName;
|
std::string resourceName;
|
||||||
std::string resourceGroup;
|
std::string resourceGroup;
|
||||||
|
|
58
credits.txt
Normal file
58
credits.txt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
CREDITS
|
||||||
|
|
||||||
|
Current Developers:
|
||||||
|
Aleksandar Jovanov
|
||||||
|
Alexander “Ace” Olofsson
|
||||||
|
athile
|
||||||
|
BrotherBrick
|
||||||
|
Cris “Mirceam” Mihalache
|
||||||
|
gugus / gus
|
||||||
|
Jacob “Yacoby” Essex
|
||||||
|
Jannik “scrawl” Heller
|
||||||
|
Jason “jhooks” Hooks
|
||||||
|
Karl-Felix “k1ll” Glatzer
|
||||||
|
Lukasz “lgro” Gromanowski
|
||||||
|
Marc “Zini” Zinnschlag
|
||||||
|
Michael “werdanith” Papageorgiou
|
||||||
|
Nikolay “corristo” Kasyanov
|
||||||
|
Pieter “pvdk” van der Kloet
|
||||||
|
Roman "Kromgart" Melnik
|
||||||
|
Sebastian “swick” Wick
|
||||||
|
Sylvain "Garvek" T.
|
||||||
|
|
||||||
|
Retired Developers:
|
||||||
|
Ardekantur
|
||||||
|
Armin Preiml
|
||||||
|
Diggory Hardy
|
||||||
|
Jan Borsodi
|
||||||
|
Jan-Peter “peppe” Nilsson
|
||||||
|
Josua Grawitter
|
||||||
|
Nicolay Korslund
|
||||||
|
sergoz
|
||||||
|
Star-Demon
|
||||||
|
Yuri Krupenin
|
||||||
|
|
||||||
|
PR team and Translators:
|
||||||
|
Julien (jvoisin/ap0) Voisin
|
||||||
|
sirherrbatka
|
||||||
|
ElderTroll
|
||||||
|
spyboot
|
||||||
|
corristo
|
||||||
|
Okulo
|
||||||
|
penguinroad
|
||||||
|
Kingpix
|
||||||
|
|
||||||
|
Reverser and Research:
|
||||||
|
natirips
|
||||||
|
Sadler
|
||||||
|
fragonard
|
||||||
|
Greendogo
|
||||||
|
Myckel
|
||||||
|
modred11
|
||||||
|
HiPhish
|
||||||
|
|
||||||
|
OpenMW:
|
||||||
|
Thanks to DokterDume for kindly providing us with the Moon and Star logo used as the application icon and project logo.
|
||||||
|
|
||||||
|
Launcher:
|
||||||
|
Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Files tab.
|
|
@ -4,9 +4,8 @@
|
||||||
PluginFolder=${OGRE_PLUGIN_DIR_REL}
|
PluginFolder=${OGRE_PLUGIN_DIR_REL}
|
||||||
|
|
||||||
# Define plugins
|
# Define plugins
|
||||||
Plugin=RenderSystem_GL
|
Plugin=RenderSystem_GL${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_ParticleFX
|
Plugin=Plugin_ParticleFX${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_OctreeSceneManager
|
Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_CgProgramManager
|
Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
PluginFolder=${OGRE_PLUGIN_DIR}
|
PluginFolder=${OGRE_PLUGIN_DIR}
|
||||||
|
|
||||||
# Define plugins
|
# Define plugins
|
||||||
Plugin=RenderSystem_GL.1.8.0
|
Plugin=RenderSystem_GL${DEBUG_SUFFIX}.1.8.0
|
||||||
Plugin=Plugin_ParticleFX.1.8.0
|
Plugin=Plugin_ParticleFX${DEBUG_SUFFIX}.1.8.0
|
||||||
Plugin=Plugin_OctreeSceneManager.1.8.0
|
Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX}.1.8.0
|
||||||
Plugin=Plugin_CgProgramManager.1.8.0
|
Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX}.1.8.0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
PluginFolder=.\
|
PluginFolder=.\
|
||||||
|
|
||||||
# Define plugins
|
# Define plugins
|
||||||
Plugin=RenderSystem_Direct3D9
|
Plugin=RenderSystem_Direct3D9${DEBUG_SUFFIX}
|
||||||
Plugin=RenderSystem_GL
|
Plugin=RenderSystem_GL${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_ParticleFX
|
Plugin=Plugin_ParticleFX${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_OctreeSceneManager
|
Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX}
|
||||||
Plugin=Plugin_CgProgramManager
|
Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -333,11 +333,18 @@ namespace Physic
|
||||||
|
|
||||||
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale)
|
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale)
|
||||||
{
|
{
|
||||||
|
char uniqueID[8];
|
||||||
|
sprintf( uniqueID, "%07.3f", scale );
|
||||||
|
std::string sid = uniqueID;
|
||||||
|
std::string outputstring = mesh + uniqueID + "\"|";
|
||||||
|
//std::cout << "The string" << outputstring << "\n";
|
||||||
|
|
||||||
//get the shape from the .nif
|
//get the shape from the .nif
|
||||||
mShapeLoader->load(mesh,"General");
|
mShapeLoader->load(outputstring,"General");
|
||||||
BulletShapeManager::getSingletonPtr()->load(mesh,"General");
|
BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
|
||||||
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General");
|
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
|
||||||
shape->Shape->setLocalScaling( btVector3(scale,scale,scale));
|
shape->Shape->setLocalScaling( btVector3(scale,scale,scale));
|
||||||
|
//btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(dynamic_cast<btBvhTriangleMeshShape*> (shape->Shape), btVector3(scale,scale,scale));
|
||||||
|
|
||||||
//create the motionState
|
//create the motionState
|
||||||
CMotionState* newMotionState = new CMotionState(this,name);
|
CMotionState* newMotionState = new CMotionState(this,name);
|
||||||
|
@ -400,19 +407,33 @@ namespace Physic
|
||||||
if (it != RigidBodyMap.end() )
|
if (it != RigidBodyMap.end() )
|
||||||
{
|
{
|
||||||
RigidBody* body = it->second;
|
RigidBody* body = it->second;
|
||||||
|
//btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape());
|
||||||
|
|
||||||
if(body != NULL)
|
if(body != NULL)
|
||||||
{
|
{
|
||||||
delete body;
|
delete body;
|
||||||
}
|
}
|
||||||
|
/*if(scaled != NULL)
|
||||||
|
{
|
||||||
|
delete scaled;
|
||||||
|
}*/
|
||||||
RigidBodyMap.erase(it);
|
RigidBodyMap.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidBody* PhysicEngine::getRigidBody(std::string name)
|
RigidBody* PhysicEngine::getRigidBody(std::string name)
|
||||||
|
{
|
||||||
|
RigidBodyContainer::iterator it = RigidBodyMap.find(name);
|
||||||
|
if (it != RigidBodyMap.end() )
|
||||||
{
|
{
|
||||||
RigidBody* body = RigidBodyMap[name];
|
RigidBody* body = RigidBodyMap[name];
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicEngine::stepSimulation(double deltaT)
|
void PhysicEngine::stepSimulation(double deltaT)
|
||||||
{
|
{
|
||||||
|
@ -467,10 +488,18 @@ namespace Physic
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicActor* PhysicEngine::getCharacter(std::string name)
|
PhysicActor* PhysicEngine::getCharacter(std::string name)
|
||||||
|
{
|
||||||
|
PhysicActorContainer::iterator it = PhysicActorMap.find(name);
|
||||||
|
if (it != PhysicActorMap.end() )
|
||||||
{
|
{
|
||||||
PhysicActor* act = PhysicActorMap[name];
|
PhysicActor* act = PhysicActorMap[name];
|
||||||
return act;
|
return act;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicEngine::emptyEventLists(void)
|
void PhysicEngine::emptyEventLists(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "BulletShapeLoader.h"
|
#include "BulletShapeLoader.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
|
||||||
|
|
||||||
class btRigidBody;
|
class btRigidBody;
|
||||||
class btBroadphaseInterface;
|
class btBroadphaseInterface;
|
||||||
|
|
|
@ -229,7 +229,7 @@ bool PM_SlideMove( bool gravity )
|
||||||
end = pm->ps.origin + pm->ps.velocity * time_left;
|
end = pm->ps.origin + pm->ps.velocity * time_left;
|
||||||
|
|
||||||
// see if we can make it there
|
// see if we can make it there
|
||||||
//pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
|
//pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg);
|
||||||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj);
|
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj);
|
||||||
newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ bool PM_SlideMove( bool gravity )
|
||||||
{
|
{
|
||||||
// pm->ps->velocity += (trace.plane.normal + pm->ps->velocity)
|
// pm->ps->velocity += (trace.plane.normal + pm->ps->velocity)
|
||||||
//VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
|
//VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
|
||||||
pm->ps.velocity = (trace.planenormal + pm->ps.velocity);
|
pm->ps.velocity = trace.planenormal + pm->ps.velocity;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +298,12 @@ bool PM_SlideMove( bool gravity )
|
||||||
if ( into >= 0.1 )
|
if ( into >= 0.1 )
|
||||||
continue; // move doesn't interact with the plane
|
continue; // move doesn't interact with the plane
|
||||||
|
|
||||||
|
|
||||||
|
if(planes[i].x >= .70)
|
||||||
|
{
|
||||||
|
pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// see how hard we are hitting things
|
// see how hard we are hitting things
|
||||||
if ( -into > pml.impactSpeed )
|
if ( -into > pml.impactSpeed )
|
||||||
pml.impactSpeed = -into;
|
pml.impactSpeed = -into;
|
||||||
|
@ -319,6 +325,13 @@ bool PM_SlideMove( bool gravity )
|
||||||
//if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 )
|
//if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 )
|
||||||
continue; // move doesn't interact with the plane
|
continue; // move doesn't interact with the plane
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||||||
|
//return true;
|
||||||
|
|
||||||
|
|
||||||
// try clipping the move to the plane
|
// try clipping the move to the plane
|
||||||
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
|
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
|
||||||
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
|
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
|
||||||
|
@ -360,6 +373,7 @@ bool PM_SlideMove( bool gravity )
|
||||||
// see if there is a third plane the the new move enters
|
// see if there is a third plane the the new move enters
|
||||||
for ( k = 0 ; k < numplanes ; k++ )
|
for ( k = 0 ; k < numplanes ; k++ )
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( k == i || k == j )
|
if ( k == i || k == j )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -513,7 +527,7 @@ int PM_StepSlideMove( bool gravity )
|
||||||
delta = pm->ps.origin.z - start_o.z;
|
delta = pm->ps.origin.z - start_o.z;
|
||||||
if ( delta > 2 )
|
if ( delta > 2 )
|
||||||
{
|
{
|
||||||
pm->ps.counter = 10;
|
pm->ps.counter = 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (gravity)
|
if (gravity)
|
||||||
|
@ -845,6 +859,8 @@ static void PM_WalkMove( playerMove* const pmove )
|
||||||
float vel;
|
float vel;
|
||||||
//pm->ps.gravity = 4000;
|
//pm->ps.gravity = 4000;
|
||||||
|
|
||||||
|
//std::cout << "Player is walking\n";
|
||||||
|
|
||||||
if ( pm->ps.waterlevel > 2 && //DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 )
|
if ( pm->ps.waterlevel > 2 && //DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 )
|
||||||
pml.forward.dotProduct(pml.groundTrace.planenormal) > 0.0f)
|
pml.forward.dotProduct(pml.groundTrace.planenormal) > 0.0f)
|
||||||
{
|
{
|
||||||
|
@ -1145,6 +1161,10 @@ void PM_GroundTraceMissed()
|
||||||
{
|
{
|
||||||
traceResults trace;
|
traceResults trace;
|
||||||
Ogre::Vector3 point;
|
Ogre::Vector3 point;
|
||||||
|
//We should not have significant upwards velocity when in the air, unless we jumped.
|
||||||
|
//This code protects against flying into the air when moving at high speeds.
|
||||||
|
//Z velocity is set to 50, instead of 0, to help move up certain steps.
|
||||||
|
|
||||||
//std::cout << "Ground trace missed\n";
|
//std::cout << "Ground trace missed\n";
|
||||||
// we just transitioned into freefall
|
// we just transitioned into freefall
|
||||||
//if ( pm->debugLevel )
|
//if ( pm->debugLevel )
|
||||||
|
@ -1407,12 +1427,15 @@ static void PM_GroundTrace( void )
|
||||||
// if the trace didn't hit anything, we are in free fall
|
// if the trace didn't hit anything, we are in free fall
|
||||||
if ( trace.fraction == 1.0)
|
if ( trace.fraction == 1.0)
|
||||||
{
|
{
|
||||||
|
if(pm->ps.velocity.z > 50.0f && pm->ps.bSnap && pm->ps.speed > 1000.0f)
|
||||||
|
pm->ps.velocity.z = 50.0f;
|
||||||
if(pm->ps.snappingImplemented){
|
if(pm->ps.snappingImplemented){
|
||||||
if(pm->ps.bSnap && pm->ps.counter <= 0)
|
if(pm->ps.bSnap && pm->ps.counter <= 0)
|
||||||
PM_GroundTraceMissed();
|
PM_GroundTraceMissed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1457,6 +1480,7 @@ static void PM_GroundTrace( void )
|
||||||
|
|
||||||
// slopes that are too steep will not be considered onground
|
// slopes that are too steep will not be considered onground
|
||||||
//if ( trace.plane.normal[2] < MIN_WALK_NORMAL )
|
//if ( trace.plane.normal[2] < MIN_WALK_NORMAL )
|
||||||
|
//std::cout << "MinWalkNormal" << trace.planenormal.z;
|
||||||
if (trace.planenormal.z < MIN_WALK_NORMAL)
|
if (trace.planenormal.z < MIN_WALK_NORMAL)
|
||||||
{
|
{
|
||||||
//if ( pm->debugLevel )
|
//if ( pm->debugLevel )
|
||||||
|
@ -1569,8 +1593,11 @@ void PM_AirMove()
|
||||||
else
|
else
|
||||||
PM_SlideMove ( qtrue );
|
PM_SlideMove ( qtrue );
|
||||||
#endif*/
|
#endif*/
|
||||||
|
//std::cout << "Moving in the air" << pm->ps.velocity << "\n";
|
||||||
|
|
||||||
/*bprintf("%i ", */PM_StepSlideMove ( true )/* )*/;
|
/*bprintf("%i ", */PM_StepSlideMove ( true )/* )*/;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PM_NoclipMove( void )
|
static void PM_NoclipMove( void )
|
||||||
|
|
|
@ -28,7 +28,7 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2);
|
||||||
#define MAX_CLIP_PLANES 5
|
#define MAX_CLIP_PLANES 5
|
||||||
#define OVERCLIP 1.001f
|
#define OVERCLIP 1.001f
|
||||||
//#define STEPSIZE 18 // 18 is way too much
|
//#define STEPSIZE 18 // 18 is way too much
|
||||||
#define STEPSIZE (18 / 2)
|
#define STEPSIZE (9)
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.14159265358979323846f
|
#define M_PI 3.14159265358979323846f
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,7 +41,7 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2);
|
||||||
#define MAX_GENTITIES (1 << GENTITYNUM_BITS)
|
#define MAX_GENTITIES (1 << GENTITYNUM_BITS)
|
||||||
#define ENTITYNUM_NONE (MAX_GENTITIES - 1)
|
#define ENTITYNUM_NONE (MAX_GENTITIES - 1)
|
||||||
#define ENTITYNUM_WORLD (MAX_GENTITIES - 2)
|
#define ENTITYNUM_WORLD (MAX_GENTITIES - 2)
|
||||||
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
|
#define MIN_WALK_NORMAL .7f // can't walk on very steep slopes
|
||||||
#define JUMP_VELOCITY (270)
|
#define JUMP_VELOCITY (270)
|
||||||
#define PS_PMOVEFRAMECOUNTBITS 6
|
#define PS_PMOVEFRAMECOUNTBITS 6
|
||||||
#define MINS_Z -24
|
#define MINS_Z -24
|
||||||
|
|
138
readme.txt
138
readme.txt
|
@ -12,8 +12,6 @@ EBGaramond-Regular.ttf: OFL (see OFL.txt for more information)
|
||||||
VeraMono.ttf: custom (see Bitstream Vera License.txt for more information)
|
VeraMono.ttf: custom (see Bitstream Vera License.txt for more information)
|
||||||
|
|
||||||
|
|
||||||
THIS IS A WORK IN PROGRESS
|
|
||||||
|
|
||||||
|
|
||||||
INSTALLATION
|
INSTALLATION
|
||||||
|
|
||||||
|
@ -90,47 +88,6 @@ Allowed options:
|
||||||
--fallback arg fallback values
|
--fallback arg fallback values
|
||||||
|
|
||||||
|
|
||||||
CREDITS
|
|
||||||
|
|
||||||
Current Developers:
|
|
||||||
Aleksandar Jovanov
|
|
||||||
Alexander “Ace” Olofsson
|
|
||||||
athile
|
|
||||||
BrotherBrick
|
|
||||||
Cris “Mirceam” Mihalache
|
|
||||||
gugus / gus
|
|
||||||
Jacob “Yacoby” Essex
|
|
||||||
Jannik “scrawl” Heller
|
|
||||||
Jason “jhooks” Hooks
|
|
||||||
Karl-Felix “k1ll” Glatzer
|
|
||||||
Lukasz “lgro” Gromanowski
|
|
||||||
Marc “Zini” Zinnschlag
|
|
||||||
Michael “werdanith” Papageorgiou
|
|
||||||
Nikolay “corristo” Kasyanov
|
|
||||||
Pieter “pvdk” van der Kloet
|
|
||||||
Roman "Kromgart" Melnik
|
|
||||||
Sebastian “swick” Wick
|
|
||||||
Sylvain "Garvek" T.
|
|
||||||
|
|
||||||
Retired Developers:
|
|
||||||
Ardekantur
|
|
||||||
Armin Preiml
|
|
||||||
Diggory Hardy
|
|
||||||
Jan Borsodi
|
|
||||||
Jan-Peter “peppe” Nilsson
|
|
||||||
Josua Grawitter
|
|
||||||
Nicolay Korslund
|
|
||||||
sergoz
|
|
||||||
Star-Demon
|
|
||||||
Yuri Krupenin
|
|
||||||
|
|
||||||
OpenMW:
|
|
||||||
Thanks to DokterDume for kindly providing us with the Moon and Star logo used as the application icon and project logo.
|
|
||||||
|
|
||||||
Launcher:
|
|
||||||
Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Files tab.
|
|
||||||
|
|
||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
0.16.0
|
0.16.0
|
||||||
|
@ -215,7 +172,6 @@ Task #113: Morrowind.ini Importer
|
||||||
Task #215: Refactor the sound code
|
Task #215: Refactor the sound code
|
||||||
Task #216: Update MyGUI
|
Task #216: Update MyGUI
|
||||||
|
|
||||||
|
|
||||||
0.13.0
|
0.13.0
|
||||||
|
|
||||||
Bug #145: Fixed sound problems after cell change
|
Bug #145: Fixed sound problems after cell change
|
||||||
|
@ -273,7 +229,6 @@ Task #131: NPC Activation doesn't work properly
|
||||||
Task #144: MWRender cleanup
|
Task #144: MWRender cleanup
|
||||||
Task #155: cmake cleanup
|
Task #155: cmake cleanup
|
||||||
|
|
||||||
|
|
||||||
0.11.1
|
0.11.1
|
||||||
|
|
||||||
Bug #2: Resources loading doesn't work outside of bsa files
|
Bug #2: Resources loading doesn't work outside of bsa files
|
||||||
|
@ -300,4 +255,95 @@ Task #14: Replace tabs with 4 spaces
|
||||||
Task #18: Move components from global namespace into their own namespace
|
Task #18: Move components from global namespace into their own namespace
|
||||||
Task #123: refactor header files in components/esm
|
Task #123: refactor header files in components/esm
|
||||||
|
|
||||||
TODO add old changelog (take pre 0.11.1 changelog from wiki)
|
0.10.0
|
||||||
|
|
||||||
|
* NPC dialogue window (not functional yet)
|
||||||
|
* Collisions with objects
|
||||||
|
* Refactor the PlayerPos class
|
||||||
|
* Adjust file locations
|
||||||
|
* CMake files and test linking for Bullet
|
||||||
|
* Replace Ogre raycasting test for activation with something more precise
|
||||||
|
* Adjust player movement according to collision results
|
||||||
|
* FPS display
|
||||||
|
* Various Portability Improvements
|
||||||
|
* Mac OS X support is back!
|
||||||
|
|
||||||
|
0.9.0
|
||||||
|
|
||||||
|
* Exterior cells loading, unloading and management
|
||||||
|
* Character Creation GUI
|
||||||
|
* Character creation
|
||||||
|
* Make cell names case insensitive when doing internal lookups
|
||||||
|
* Music player
|
||||||
|
* NPCs rendering
|
||||||
|
|
||||||
|
0.8.0
|
||||||
|
|
||||||
|
* GUI
|
||||||
|
* Complete and working script engine
|
||||||
|
* In game console
|
||||||
|
* Sky rendering
|
||||||
|
* Sound and music
|
||||||
|
* Tons of smaller stuff
|
||||||
|
|
||||||
|
0.7.0
|
||||||
|
|
||||||
|
* This release is a complete rewrite in C++.
|
||||||
|
* All D code has been culled, and all modules have been rewritten.
|
||||||
|
* The game is now back up to the level of rendering interior cells and moving around, but physics, sound, GUI, and scripting still remain to be ported from the old codebase.
|
||||||
|
|
||||||
|
0.6.0
|
||||||
|
|
||||||
|
* Coded a GUI system using MyGUI
|
||||||
|
* Skinned MyGUI to look like Morrowind (work in progress)
|
||||||
|
* Integrated the Monster script engine
|
||||||
|
* Rewrote some functions into script code
|
||||||
|
* Very early MyGUI < > Monster binding
|
||||||
|
* Fixed Windows sound problems (replaced old openal32.dll)
|
||||||
|
|
||||||
|
0.5.0
|
||||||
|
|
||||||
|
* Collision detection with Bullet
|
||||||
|
* Experimental walk & fall character physics
|
||||||
|
* New key bindings:
|
||||||
|
* t toggle physics mode (walking, flying, ghost),
|
||||||
|
* n night eye, brightens the scene
|
||||||
|
* Fixed incompatability with DMD 1.032 and newer compilers
|
||||||
|
* * (thanks to tomqyp)
|
||||||
|
* Various minor changes and updates
|
||||||
|
|
||||||
|
0.4.0
|
||||||
|
|
||||||
|
* Switched from Audiere to OpenAL
|
||||||
|
* * (BIG thanks to Chris Robinson)
|
||||||
|
* Added complete Makefile (again) as a alternative build tool
|
||||||
|
* More realistic lighting (thanks again to Chris Robinson)
|
||||||
|
* Various localization fixes tested with Russian and French versions
|
||||||
|
* Temporary workaround for the Unicode issue: invalid UTF displayed as '?'
|
||||||
|
* Added ns option to disable sound, for debugging
|
||||||
|
* Various bug fixes
|
||||||
|
* Cosmetic changes to placate gdc Wall
|
||||||
|
|
||||||
|
0.3.0
|
||||||
|
|
||||||
|
* Built and tested on Windows XP
|
||||||
|
* Partial support for FreeBSD (exceptions do not work)
|
||||||
|
* You no longer have to download Monster separately
|
||||||
|
* Made an alternative for building without DSSS (but DSSS still works)
|
||||||
|
* Renamed main program from 'morro' to 'openmw'
|
||||||
|
* Made the config system more robust
|
||||||
|
* Added oc switch for showing Ogre config window on startup
|
||||||
|
* Removed some config files, these are auto generated when missing.
|
||||||
|
* Separated plugins.cfg into linux and windows versions.
|
||||||
|
* Updated Makefile and sources for increased portability
|
||||||
|
* confirmed to work against OIS 1.0.0 (Ubuntu repository package)
|
||||||
|
|
||||||
|
0.2.0
|
||||||
|
|
||||||
|
* Compiles with gdc
|
||||||
|
* Switched to DSSS for building D code
|
||||||
|
* Includes the program esmtool
|
||||||
|
|
||||||
|
0.1.0
|
||||||
|
|
||||||
|
first release
|
||||||
|
|
Loading…
Reference in a new issue