forked from mirror/openmw-tes3mp
Merge branch 'master' into exterior
This commit is contained in:
commit
15878b12fd
8 changed files with 270 additions and 48 deletions
|
@ -50,6 +50,14 @@ set(TO_UTF8_HEADER
|
||||||
${COMP_DIR}/to_utf8/to_utf8.hpp)
|
${COMP_DIR}/to_utf8/to_utf8.hpp)
|
||||||
source_group(components\\to_utf8 FILES ${TO_UTF8} ${TO_UTF8_HEADER})
|
source_group(components\\to_utf8 FILES ${TO_UTF8} ${TO_UTF8_HEADER})
|
||||||
|
|
||||||
|
set(FILE_FINDER
|
||||||
|
${COMP_DIR}/file_finder/search.cpp)
|
||||||
|
set(FILE_FINDER_HEADER
|
||||||
|
${COMP_DIR}/file_finder/file_finder.hpp
|
||||||
|
${COMP_DIR}/file_finder/filename_less.hpp
|
||||||
|
${COMP_DIR}/file_finder/search.hpp)
|
||||||
|
source_group(components\\file_finder FILES ${FILE_FINDER} ${FILE_FINDER_HEADER})
|
||||||
|
|
||||||
set(ESM_STORE
|
set(ESM_STORE
|
||||||
${COMP_DIR}/esm_store/store.cpp)
|
${COMP_DIR}/esm_store/store.cpp)
|
||||||
set(ESM_STORE_HEADER
|
set(ESM_STORE_HEADER
|
||||||
|
@ -82,10 +90,10 @@ file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp)
|
||||||
source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER})
|
source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER})
|
||||||
|
|
||||||
set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} ${TO_UTF8}
|
set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} ${TO_UTF8}
|
||||||
${COMPILER} ${INTERPRETER} ${ESM})
|
${COMPILER} ${INTERPRETER} ${ESM} ${FILE_FINDER})
|
||||||
set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER}
|
set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER}
|
||||||
${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${TO_UTF8_HEADER}
|
${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${TO_UTF8_HEADER}
|
||||||
${INTERPRETER_HEADER})
|
${INTERPRETER_HEADER} ${FILE_FINDER_HEADER})
|
||||||
|
|
||||||
# source directory: libs
|
# source directory: libs
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "soundmanager.hpp"
|
#include "soundmanager.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -8,6 +7,7 @@ using namespace std;
|
||||||
#include <mangle/sound/clients/ogre_listener_mover.hpp>
|
#include <mangle/sound/clients/ogre_listener_mover.hpp>
|
||||||
#include <mangle/sound/clients/ogre_output_updater.hpp>
|
#include <mangle/sound/clients/ogre_output_updater.hpp>
|
||||||
|
|
||||||
|
#include <components/file_finder/file_finder.hpp>
|
||||||
#include <components/esm_store/store.hpp>
|
#include <components/esm_store/store.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -74,12 +74,17 @@ namespace MWSound
|
||||||
Mangle::Sound::OgreListenerMover cameraTracker;
|
Mangle::Sound::OgreListenerMover cameraTracker;
|
||||||
|
|
||||||
const ESMS::ESMStore &store;
|
const ESMS::ESMStore &store;
|
||||||
std::string dir;
|
|
||||||
|
|
||||||
typedef std::map<std::string,Mangle::Sound::WSoundPtr> IDMap;
|
typedef std::map<std::string,Mangle::Sound::WSoundPtr> IDMap;
|
||||||
typedef std::map<MWWorld::Ptr,IDMap> PtrMap;
|
typedef std::map<MWWorld::Ptr,IDMap> PtrMap;
|
||||||
PtrMap sounds;
|
PtrMap sounds;
|
||||||
|
|
||||||
|
// This is used for case insensitive and slash-type agnostic file
|
||||||
|
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
|
||||||
|
// relative to the sound dir, and translates them into full paths
|
||||||
|
// of existing files in the filesystem, if they exist.
|
||||||
|
FileFinder::FileFinder files;
|
||||||
|
|
||||||
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
|
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
|
||||||
const ESMS::ESMStore &str,
|
const ESMS::ESMStore &str,
|
||||||
const std::string &soundDir)
|
const std::string &soundDir)
|
||||||
|
@ -87,6 +92,7 @@ namespace MWSound
|
||||||
, updater(mgr)
|
, updater(mgr)
|
||||||
, cameraTracker(mgr)
|
, cameraTracker(mgr)
|
||||||
, store(str)
|
, store(str)
|
||||||
|
, files(soundDir)
|
||||||
{
|
{
|
||||||
cout << "Sound output: " << SOUND_OUT << endl;
|
cout << "Sound output: " << SOUND_OUT << endl;
|
||||||
cout << "Sound decoder: " << SOUND_IN << endl;
|
cout << "Sound decoder: " << SOUND_IN << endl;
|
||||||
|
@ -96,21 +102,40 @@ namespace MWSound
|
||||||
|
|
||||||
// Tell Ogre to update the sound system each frame
|
// Tell Ogre to update the sound system each frame
|
||||||
root->addFrameListener(&updater);
|
root->addFrameListener(&updater);
|
||||||
|
}
|
||||||
|
|
||||||
dir = soundDir + "/";
|
std::string toMp3(const std::string &str)
|
||||||
|
{
|
||||||
|
std::string wav = str;
|
||||||
|
int i = str.size()-3;
|
||||||
|
wav[i++] = 'm';
|
||||||
|
wav[i++] = 'p';
|
||||||
|
wav[i++] = '3';
|
||||||
|
return wav;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasFile(const std::string &str)
|
||||||
|
{
|
||||||
|
if(files.has(str)) return true;
|
||||||
|
// Not found? Try exchanging .wav with .mp3
|
||||||
|
return files.has(toMp3(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
|
// Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
|
||||||
// with proper slash conversion (eg. datadir/Sound/Fx/funny.wav)
|
// with proper slash conversion (eg. datadir/Sound/Fx/funny.wav)
|
||||||
std::string convertPath(const std::string &str)
|
std::string convertPath(const std::string &str)
|
||||||
{
|
{
|
||||||
std::string file = dir + str;
|
// Search and return
|
||||||
#ifndef WIN32
|
if(files.has(str))
|
||||||
// Actually / path separators should work in Windows too, they
|
return files.lookup(str);
|
||||||
// just aren't necessary.
|
|
||||||
std::replace(file.begin(), file.end(), '\\', '/');
|
// Try mp3 if the wav wasn't found
|
||||||
#endif
|
std::string mp3 = toMp3(str);
|
||||||
return file;
|
if(files.has(mp3))
|
||||||
|
return files.lookup(mp3);
|
||||||
|
|
||||||
|
// Give up
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a soundId to file name, and modify the volume
|
// Convert a soundId to file name, and modify the volume
|
||||||
|
@ -232,7 +257,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
// Make sure to increase the iterator before we erase it.
|
// Make sure to increase the iterator before we erase it.
|
||||||
it2 = it++;
|
it2 = it++;
|
||||||
if(it->first.getCell() == cell)
|
if(it2->first.getCell() == cell)
|
||||||
clearAll(it2);
|
clearAll(it2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +302,10 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
// The range values are not tested
|
// The range values are not tested
|
||||||
if(!mData) return;
|
if(!mData) return;
|
||||||
mData->add(mData->convertPath(filename), ptr, "_say_sound", 1, 1, 100, 10000, false);
|
if(mData->hasFile(filename))
|
||||||
|
mData->add(mData->convertPath(filename), ptr, "_say_sound", 1, 1, 100, 10000, false);
|
||||||
|
else
|
||||||
|
cout << "Sound file " << filename << " not found, skipping.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoundManager::sayDone (MWWorld::Ptr ptr) const
|
bool SoundManager::sayDone (MWWorld::Ptr ptr) const
|
||||||
|
|
66
components/file_finder/file_finder.hpp
Normal file
66
components/file_finder/file_finder.hpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef FILE_FINDER_MAIN_H
|
||||||
|
#define FILE_FINDER_MAIN_H
|
||||||
|
|
||||||
|
#include "search.hpp"
|
||||||
|
#include "filename_less.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace FileFinder
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename LESS>
|
||||||
|
class FileFinderT
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string, LESS> table;
|
||||||
|
|
||||||
|
struct Inserter : ReturnPath
|
||||||
|
{
|
||||||
|
FileFinderT<LESS> *owner;
|
||||||
|
int cut;
|
||||||
|
|
||||||
|
void add(const boost::filesystem::path &pth)
|
||||||
|
{
|
||||||
|
std::string file = pth.file_string();
|
||||||
|
std::string key = file.substr(cut);
|
||||||
|
owner->table[key] = file;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Inserter inserter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileFinderT(const boost::filesystem::path &path, bool recurse=true)
|
||||||
|
{
|
||||||
|
inserter.owner = this;
|
||||||
|
|
||||||
|
// Remember the original path length, so we can cut it away from
|
||||||
|
// the relative paths used as keys
|
||||||
|
std::string pstring = path.file_string();
|
||||||
|
inserter.cut = pstring.size();
|
||||||
|
|
||||||
|
// If the path does not end in a slash, then boost will add one
|
||||||
|
// later, which means one more character we have to remove.
|
||||||
|
char last = pstring[pstring.size()-1];
|
||||||
|
if(last != '\\' && last != '/')
|
||||||
|
inserter.cut++;
|
||||||
|
|
||||||
|
// Fill the map
|
||||||
|
find(path, inserter, recurse);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has(const std::string& file) const
|
||||||
|
{
|
||||||
|
return table.find(file) != table.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the full path from a relative path.
|
||||||
|
const std::string &lookup(const std::string& file) const
|
||||||
|
{
|
||||||
|
return table.find(file)->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The default is to use path_less for equality checks
|
||||||
|
typedef FileFinderT<path_less> FileFinder;
|
||||||
|
}
|
||||||
|
#endif
|
49
components/file_finder/filename_less.hpp
Normal file
49
components/file_finder/filename_less.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef FILE_FINDER_LESS_H
|
||||||
|
#define FILE_FINDER_LESS_H
|
||||||
|
|
||||||
|
#include <libs/platform/strings.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace FileFinder{
|
||||||
|
|
||||||
|
// Used for maps of file paths. Compares file paths, but ignores case
|
||||||
|
// AND treats \ and / as the same character.
|
||||||
|
struct path_less
|
||||||
|
{
|
||||||
|
int compareChar(char a, char b) const
|
||||||
|
{
|
||||||
|
if(a>b) return 1;
|
||||||
|
else if(a<b) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comparePathChar(char a, char b) const
|
||||||
|
{
|
||||||
|
if(a >= 'a' && a <= 'z') a += 'A'-'a';
|
||||||
|
else if(a == '\\') a = '/';
|
||||||
|
if(b >= 'a' && b <= 'z') b += 'A'-'a';
|
||||||
|
else if(b == '\\') b = '/';
|
||||||
|
return compareChar(a,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareString(const char *a, const char *b) const
|
||||||
|
{
|
||||||
|
while(*a && *b)
|
||||||
|
{
|
||||||
|
int i = comparePathChar(*a,*b);
|
||||||
|
if(i != 0) return i;
|
||||||
|
a++; b++;
|
||||||
|
}
|
||||||
|
// At this point, one or both of the chars is a null terminator.
|
||||||
|
// Normal char comparison will get the correct final result here.
|
||||||
|
return compareChar(*a,*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator() (const std::string& a, const std::string& b) const
|
||||||
|
{
|
||||||
|
return compareString(a.c_str(), b.c_str()) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
28
components/file_finder/search.cpp
Normal file
28
components/file_finder/search.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include "search.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace boost::filesystem;
|
||||||
|
|
||||||
|
void FileFinder::find(const path & dir_path, ReturnPath &ret, bool recurse)
|
||||||
|
{
|
||||||
|
if ( !exists( dir_path ) )
|
||||||
|
{
|
||||||
|
cout << "Path " << dir_path << " not found\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
directory_iterator end_itr; // default construction yields past-the-end
|
||||||
|
for ( directory_iterator itr(dir_path);
|
||||||
|
itr != end_itr;
|
||||||
|
++itr )
|
||||||
|
{
|
||||||
|
if ( is_directory( *itr ) )
|
||||||
|
{
|
||||||
|
if(recurse) find(*itr, ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret.add(*itr);
|
||||||
|
}
|
||||||
|
}
|
20
components/file_finder/search.hpp
Normal file
20
components/file_finder/search.hpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef FILE_FINDER_SEARCH_H
|
||||||
|
#define FILE_FINDER_SEARCH_H
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace FileFinder
|
||||||
|
{
|
||||||
|
struct ReturnPath
|
||||||
|
{
|
||||||
|
virtual void add(const boost::filesystem::path &pth) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Search the given path and return all file paths through 'ret'. If
|
||||||
|
recurse==true, all files in subdirectories are returned as well.
|
||||||
|
*/
|
||||||
|
void find(const boost::filesystem::path & dir_path, ReturnPath &ret, bool recurse=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -30,9 +30,12 @@
|
||||||
#include "../nif/node.hpp"
|
#include "../nif/node.hpp"
|
||||||
#include "../nif/data.hpp"
|
#include "../nif/data.hpp"
|
||||||
#include "../nif/property.hpp"
|
#include "../nif/property.hpp"
|
||||||
|
#include "../nif/controller.hpp"
|
||||||
|
#include "../nif/extra.hpp"
|
||||||
#include <libs/platform/strings.h>
|
#include <libs/platform/strings.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
// For warning messages
|
// For warning messages
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -170,7 +173,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Conversion of blend / test mode from NIF -> OGRE.
|
// Conversion of blend / test mode from NIF -> OGRE.
|
||||||
/* Not in use yet, so let's comment it out.
|
// Not in use yet, so let's comment it out.
|
||||||
|
/*
|
||||||
static SceneBlendFactor getBlendFactor(int mode)
|
static SceneBlendFactor getBlendFactor(int mode)
|
||||||
{
|
{
|
||||||
switch(mode)
|
switch(mode)
|
||||||
|
@ -191,9 +195,9 @@ static SceneBlendFactor getBlendFactor(int mode)
|
||||||
return SBF_SOURCE_ALPHA;
|
return SBF_SOURCE_ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is also unused
|
|
||||||
|
// This is also unused
|
||||||
static CompareFunction getTestMode(int mode)
|
static CompareFunction getTestMode(int mode)
|
||||||
{
|
{
|
||||||
switch(mode)
|
switch(mode)
|
||||||
|
@ -218,7 +222,7 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
const Vector &specular,
|
const Vector &specular,
|
||||||
const Vector &emissive,
|
const Vector &emissive,
|
||||||
float glossiness, float alpha,
|
float glossiness, float alpha,
|
||||||
float alphaFlags, float alphaTest,
|
int alphaFlags, float alphaTest,
|
||||||
const String &texName)
|
const String &texName)
|
||||||
{
|
{
|
||||||
MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup);
|
MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup);
|
||||||
|
@ -234,32 +238,33 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
/*TextureUnitState *txt =*/
|
/*TextureUnitState *txt =*/
|
||||||
pass->createTextureUnitState(texName);
|
pass->createTextureUnitState(texName);
|
||||||
|
|
||||||
/* As of yet UNTESTED code from Chris:
|
// As of yet UNTESTED code from Chris:
|
||||||
pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
|
/*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
|
||||||
pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
|
pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
|
||||||
pass->setDepthCheckEnabled(true);
|
pass->setDepthCheckEnabled(true);
|
||||||
|
|
||||||
// Add transparency if NiAlphaProperty was present
|
// Add transparency if NiAlphaProperty was present
|
||||||
if(alphaFlags != -1)
|
if (alphaFlags != -1)
|
||||||
{
|
{
|
||||||
if((alphaFlags&1))
|
std::cout << "Alpha flags set!" << endl;
|
||||||
{
|
if ((alphaFlags&1))
|
||||||
|
{
|
||||||
pass->setDepthWriteEnabled(false);
|
pass->setDepthWriteEnabled(false);
|
||||||
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf),
|
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf),
|
||||||
getBlendFactor((alphaFlags>>5)&0xf));
|
getBlendFactor((alphaFlags>>5)&0xf));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pass->setDepthWriteEnabled(true);
|
pass->setDepthWriteEnabled(true);
|
||||||
|
|
||||||
if((alphaFlags>>9)&1)
|
if ((alphaFlags>>9)&1)
|
||||||
pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7),
|
pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7),
|
||||||
alphaTest);
|
alphaTest);
|
||||||
|
|
||||||
pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1));
|
pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pass->setDepthWriteEnabled(true);
|
pass->setDepthWriteEnabled(true); */
|
||||||
*/
|
|
||||||
|
|
||||||
// Add transparency if NiAlphaProperty was present
|
// Add transparency if NiAlphaProperty was present
|
||||||
if (alphaFlags != -1)
|
if (alphaFlags != -1)
|
||||||
|
@ -322,7 +327,7 @@ void NIFLoader::findRealTexture(String &texName)
|
||||||
|
|
||||||
// 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)
|
void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std::list<VertexBoneAssignment> &vertexBoneAssignments)
|
||||||
{
|
{
|
||||||
NiTriShapeData *data = shape->data.getPtr();
|
NiTriShapeData *data = shape->data.getPtr();
|
||||||
SubMesh *sub = mesh->createSubMesh(shape->name.toString());
|
SubMesh *sub = mesh->createSubMesh(shape->name.toString());
|
||||||
|
@ -410,6 +415,14 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material)
|
||||||
|
|
||||||
// Set material if one was given
|
// Set material if one was given
|
||||||
if (!material.empty()) sub->setMaterialName(material);
|
if (!material.empty()) sub->setMaterialName(material);
|
||||||
|
|
||||||
|
//add vertex bone assignments
|
||||||
|
|
||||||
|
for (std::list<VertexBoneAssignment>::iterator it = vertexBoneAssignments.begin();
|
||||||
|
it != vertexBoneAssignments.end(); it++)
|
||||||
|
{
|
||||||
|
sub->addBoneAssignment(*it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper math functions. Reinventing linear algebra for the win!
|
// Helper math functions. Reinventing linear algebra for the win!
|
||||||
|
@ -595,12 +608,13 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
float *ptr = (float*)data->vertices.ptr;
|
float *ptr = (float*)data->vertices.ptr;
|
||||||
float *optr = ptr;
|
float *optr = ptr;
|
||||||
|
|
||||||
|
std::list<VertexBoneAssignment> vertexBoneAssignments;
|
||||||
|
|
||||||
//use niskindata for the position of vertices.
|
//use niskindata for the position of vertices.
|
||||||
if (!shape->skin.empty())
|
if (!shape->skin.empty())
|
||||||
{
|
{
|
||||||
// vector that stores if the position if a vertex is absolute
|
// vector that stores if the position if a vertex is absolute
|
||||||
std::vector<bool> vertexPosAbsolut(numVerts,false);
|
std::vector<bool> vertexPosAbsolut(numVerts,false);
|
||||||
|
|
||||||
|
|
||||||
float *ptrNormals = (float*)data->normals.ptr;
|
float *ptrNormals = (float*)data->normals.ptr;
|
||||||
//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]
|
||||||
|
@ -654,16 +668,18 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO: create vbas, and give them to createOgreSubMesh
|
|
||||||
|
|
||||||
vertexPosAbsolut[verIndex] = true;
|
vertexPosAbsolut[verIndex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexBoneAssignment vba;
|
||||||
|
vba.boneIndex = bonePtr->getHandle();
|
||||||
|
vba.vertexIndex = verIndex;
|
||||||
|
vba.weight = (it->weights.ptr + i)->weight;
|
||||||
|
|
||||||
|
vertexBoneAssignments.push_back(vba);
|
||||||
}
|
}
|
||||||
|
|
||||||
boneIndex++;
|
boneIndex++;
|
||||||
//it->trafo (pos, rot, scale) of the vertex
|
|
||||||
//it->weights array containt the vertices linked to the bone and the weight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -696,7 +712,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
bounds.add(optr, numVerts);
|
bounds.add(optr, numVerts);
|
||||||
|
|
||||||
// Create the submesh
|
// Create the submesh
|
||||||
createOgreSubMesh(shape, material);
|
createOgreSubMesh(shape, material, vertexBoneAssignments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,9 +753,16 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
// create skeleton or add bones
|
// create skeleton or add bones
|
||||||
if (node->recType == RC_NiNode)
|
if (node->recType == RC_NiNode)
|
||||||
{
|
{
|
||||||
if (node->name == "Bip01") //root node, create a skeleton
|
//FIXME: "Bip01" isn't every time the root bone
|
||||||
|
if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton
|
||||||
{
|
{
|
||||||
skel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
skel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
||||||
|
|
||||||
|
/*if (node->extra->recType == RC_NiTextKeyExtraData )
|
||||||
|
{
|
||||||
|
//TODO: Get animation names
|
||||||
|
std::cout << node->name.toString() << " is root bone and has textkeyextradata!\n";
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skel.isNull()) //if there is a skeleton
|
if (!skel.isNull()) //if there is a skeleton
|
||||||
|
@ -845,17 +868,17 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
// Handle the node
|
// Handle the node
|
||||||
handleNode(node, 0, NULL, bounds, 0);
|
handleNode(node, 0, NULL, bounds, 0);
|
||||||
|
|
||||||
//set skeleton
|
// set the bounding value.
|
||||||
// if (!skel.isNull())
|
|
||||||
// mesh->setSkeletonName(getSkeletonName());
|
|
||||||
|
|
||||||
// Finally, set the bounding value.
|
|
||||||
if (bounds.isValid())
|
if (bounds.isValid())
|
||||||
{
|
{
|
||||||
mesh->_setBounds(AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(),
|
mesh->_setBounds(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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set skeleton
|
||||||
|
// if (!skel.isNull())
|
||||||
|
// mesh->setSkeletonName(getSkeletonName());
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshPtr NIFLoader::load(const std::string &name,
|
MeshPtr NIFLoader::load(const std::string &name,
|
||||||
|
|
|
@ -90,7 +90,7 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
|
|
||||||
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
|
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
|
||||||
|
|
||||||
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material);
|
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 Nif::Vector &ambient,
|
||||||
|
@ -98,7 +98,7 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
const Nif::Vector &specular,
|
const Nif::Vector &specular,
|
||||||
const Nif::Vector &emissive,
|
const Nif::Vector &emissive,
|
||||||
float glossiness, float alpha,
|
float glossiness, float alpha,
|
||||||
float alphaFlags, float alphaTest,
|
int alphaFlags, float alphaTest,
|
||||||
const Ogre::String &texName);
|
const Ogre::String &texName);
|
||||||
|
|
||||||
void findRealTexture(Ogre::String &texName);
|
void findRealTexture(Ogre::String &texName);
|
||||||
|
|
Loading…
Reference in a new issue