Imported Upstream version 0.26.0

This commit is contained in:
Bret Curtis 2013-10-17 16:37:22 +02:00
commit 9a2b6c69b6
1398 changed files with 212217 additions and 0 deletions

View file

@ -0,0 +1,303 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/
This file (ogre_nif_loader.cpp) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
#include "bulletnifloader.hpp"
#include <cstdio>
#include <components/misc/stringops.hpp>
#include "../nif/niffile.hpp"
#include "../nif/node.hpp"
#include "../nif/data.hpp"
#include "../nif/property.hpp"
#include "../nif/controller.hpp"
#include "../nif/extra.hpp"
#include <libs/platform/strings.h>
#include <vector>
#include <list>
// For warning messages
#include <iostream>
// float infinity
#include <limits>
typedef unsigned char ubyte;
namespace NifBullet
{
struct TriangleMeshShape : public btBvhTriangleMeshShape
{
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
{
}
virtual ~TriangleMeshShape()
{
delete getTriangleInfoMap();
delete m_meshInterface;
}
};
ManualBulletShapeLoader::~ManualBulletShapeLoader()
{
}
btVector3 ManualBulletShapeLoader::getbtVector(Ogre::Vector3 const &v)
{
return btVector3(v[0], v[1], v[2]);
}
void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
{
mShape = static_cast<OEngine::Physic::BulletShape *>(resource);
mResourceName = mShape->getName();
mShape->mCollide = false;
mBoundingBox = NULL;
mShape->mBoxTranslation = Ogre::Vector3(0,0,0);
mShape->mBoxRotation = Ogre::Quaternion::IDENTITY;
mHasShape = false;
btTriangleMesh* mesh1 = new btTriangleMesh();
// 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
// every error as early and intrusively as possible, as it's most
// likely a sign of incomplete code rather than faulty input.
Nif::NIFFile::ptr pnif (Nif::NIFFile::create (mResourceName.substr(0, mResourceName.length()-7)));
Nif::NIFFile & nif = *pnif.get ();
if (nif.numRoots() < 1)
{
warn("Found no root nodes in NIF.");
return;
}
Nif::Record *r = nif.getRoot(0);
assert(r != NULL);
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
if (node == NULL)
{
warn("First root in file was not a node, but a " +
r->recName + ". Skipping file.");
return;
}
mShape->mHasCollisionNode = hasRootCollisionNode(node);
//do a first pass
handleNode(mesh1, node,0,false,false,false);
if(mBoundingBox != NULL)
{
mShape->mCollisionShape = mBoundingBox;
delete mesh1;
}
else if (mHasShape && mShape->mCollide)
{
mShape->mCollisionShape = new TriangleMeshShape(mesh1,true);
}
else
delete mesh1;
//second pass which create a shape for raycasting.
mResourceName = mShape->getName();
mShape->mCollide = false;
mBoundingBox = NULL;
mShape->mBoxTranslation = Ogre::Vector3(0,0,0);
mShape->mBoxRotation = Ogre::Quaternion::IDENTITY;
mHasShape = false;
btTriangleMesh* mesh2 = new btTriangleMesh();
handleNode(mesh2, node,0,true,true,false);
if(mBoundingBox != NULL)
{
mShape->mRaycastingShape = mBoundingBox;
delete mesh2;
}
else if (mHasShape)
{
mShape->mRaycastingShape = new TriangleMeshShape(mesh2,true);
}
else
delete mesh2;
}
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node)
{
if(node->recType == Nif::RC_RootCollisionNode)
return true;
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
{
if(!list[i].empty())
{
if(hasRootCollisionNode(list[i].getPtr()))
return true;
}
}
}
return false;
}
void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node *node, int flags,
bool isCollisionNode,
bool raycasting, bool isMarker)
{
// Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least.
flags |= node->flags;
if (!raycasting)
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
else
isCollisionNode = isCollisionNode && (node->recType != Nif::RC_RootCollisionNode);
// Don't collide with AvoidNode shapes
if(node->recType == Nif::RC_AvoidNode)
flags |= 0x800;
// Marker objects
/// \todo don't do this in the editor
std::string nodename = node->name;
Misc::StringUtils::toLower(nodename);
if (nodename.find("marker") != std::string::npos)
isMarker = true;
// Check for extra data
Nif::Extra const *e = node;
while (!e->extra.empty())
{
// Get the next extra data in the list
e = e->extra.getPtr();
assert(e != NULL);
if (e->recType == Nif::RC_NiStringExtraData)
{
// String markers may contain important information
// affecting the entire subtree of this node
Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e;
// not sure what the difference between NCO and NCC is, or if there even is one
if (sd->string == "NCO" || sd->string == "NCC")
{
// No collision. Use an internal flag setting to mark this.
flags |= 0x800;
}
else if (sd->string == "MRK")
// Marker objects. These are only visible in the
// editor. Until and unless we add an editor component to
// the engine, just skip this entire node.
isMarker = true;
}
}
if ( (isCollisionNode || (!mShape->mHasCollisionNode && !raycasting))
&& (!isMarker || (mShape->mHasCollisionNode && !raycasting)))
{
if(node->hasBounds)
{
mShape->mBoxTranslation = node->boundPos;
mShape->mBoxRotation = node->boundRot;
mBoundingBox = new btBoxShape(getbtVector(node->boundXYZ));
}
else if(node->recType == Nif::RC_NiTriShape)
{
mShape->mCollide = !(flags&0x800);
handleNiTriShape(mesh, static_cast<const Nif::NiTriShape*>(node), flags, node->getWorldTransform(), raycasting);
}
}
// For NiNodes, loop through children
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
{
if(!list[i].empty())
handleNode(mesh, list[i].getPtr(), flags, isCollisionNode, raycasting, isMarker);
}
}
}
void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform,
bool raycasting)
{
assert(shape != NULL);
// Interpret flags
bool hidden = (flags&Nif::NiNode::Flag_Hidden) != 0;
bool collide = (flags&Nif::NiNode::Flag_MeshCollision) != 0;
bool bbcollide = (flags&Nif::NiNode::Flag_BBoxCollision) != 0;
// If the object was marked "NCO" earlier, it shouldn't collide with
// anything. So don't do anything.
if ((flags & 0x800) && !raycasting)
{
collide = false;
bbcollide = false;
return;
}
if (!collide && !bbcollide && hidden && !raycasting)
// This mesh apparently isn't being used for anything, so don't
// bother setting it up.
return;
mHasShape = true;
const Nif::NiTriShapeData *data = shape->data.getPtr();
const std::vector<Ogre::Vector3> &vertices = data->vertices;
const short *triangles = &data->triangles[0];
for(size_t i = 0;i < data->triangles.size();i+=3)
{
Ogre::Vector3 b1 = transform*vertices[triangles[i+0]];
Ogre::Vector3 b2 = transform*vertices[triangles[i+1]];
Ogre::Vector3 b3 = transform*vertices[triangles[i+2]];
mesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
}
}
void ManualBulletShapeLoader::load(const std::string &name,const std::string &group)
{
// Check if the resource already exists
Ogre::ResourcePtr ptr = OEngine::Physic::BulletShapeManager::getSingleton().getByName(name, group);
if (!ptr.isNull())
return;
OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this);
}
} // namespace NifBullet

View file

@ -0,0 +1,113 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/
This file (ogre_nif_loader.h) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
#ifndef OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP
#define OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP
#include <cassert>
#include <string>
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
#include <btBulletDynamicsCommon.h>
#include <openengine/bullet/BulletShapeLoader.h>
// For warning messages
#include <iostream>
namespace Nif
{
class Node;
class Transformation;
class NiTriShape;
}
namespace NifBullet
{
/**
*Load bulletShape from NIF files.
*/
class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader
{
public:
ManualBulletShapeLoader()
: mShape(NULL)
, mBoundingBox(NULL)
, mHasShape(false)
{
}
virtual ~ManualBulletShapeLoader();
void warn(const std::string &msg)
{
std::cerr << "NIFLoader: Warn:" << msg << "\n";
}
void fail(const std::string &msg)
{
std::cerr << "NIFLoader: Fail: "<< msg << std::endl;
abort();
}
/**
*This function should not be called manualy. Use load instead. (this is called by the BulletShapeManager when you use load).
*/
void loadResource(Ogre::Resource *resource);
/**
*This function load a new bulletShape from a NIF file into the BulletShapeManager.
*When the file is loaded, you can then use BulletShapeManager::getByName() to retrive the bulletShape.
*Warning: this function will just crash if the resourceGroup doesn't exist!
*/
void load(const std::string &name,const std::string &group);
private:
btVector3 getbtVector(Ogre::Vector3 const &v);
/**
*Parse a node.
*/
void handleNode(btTriangleMesh* mesh, Nif::Node const *node, int flags, bool isCollisionNode, bool raycasting, bool isMarker);
/**
*Helper function
*/
bool hasRootCollisionNode(const Nif::Node *node);
/**
*convert a NiTriShape to a bullet trishape.
*/
void handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, bool raycasting);
std::string mResourceName;
OEngine::Physic::BulletShape* mShape;//current shape
btBoxShape *mBoundingBox;
bool mHasShape;
};
}
#endif

View file

@ -0,0 +1,209 @@
#include "bullet_nif_loader.hpp"
#include "..\nifogre\ogre_nif_loader.hpp"
#include "..\bsa\bsa_archive.hpp"
#include "..\nifogre\ogre_nif_loader.hpp"
#include <Ogre.h>
#include <OIS.h>
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include "BtOgrePG.h"
#include "BtOgreGP.h"
#include "BtOgreExtras.h"
const char* mesh = "meshes\\x\\ex_hlaalu_b_24.nif";
class MyMotionState : public btMotionState {
public:
MyMotionState(const btTransform &initialpos, Ogre::SceneNode *node) {
mVisibleobj = node;
mPos1 = initialpos;
node->setPosition(initialpos.getOrigin().x(),initialpos.getOrigin().y(),initialpos.getOrigin().z());
}
virtual ~MyMotionState() {
}
void setNode(Ogre::SceneNode *node) {
mVisibleobj = node;
}
virtual void getWorldTransform(btTransform &worldTrans) const {
worldTrans = mPos1;
}
virtual void setWorldTransform(const btTransform &worldTrans) {
if(NULL == mVisibleobj) return; // silently return before we set a node
btQuaternion rot = worldTrans.getRotation();
mVisibleobj->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
btVector3 pos = worldTrans.getOrigin();
mVisibleobj->setPosition(pos.x(), pos.y(), pos.z());
}
protected:
Ogre::SceneNode *mVisibleobj;
btTransform mPos1;
};
int main()
{
try
{
//Ogre stuff
Ogre::Root* pRoot = new Ogre::Root();
pRoot->showConfigDialog();
BulletShapeManager* manag = new BulletShapeManager();
Ogre::RenderWindow* win = pRoot->initialise(true,"test");
Ogre::SceneManager* scmg = pRoot->createSceneManager(Ogre::ST_GENERIC,"MonGestionnaireDeScene");
Ogre::Camera* pCamera = scmg->createCamera("test");
Ogre::Viewport* pViewport = win->addViewport(pCamera);
pCamera->setPosition(-50,0,0);
pCamera->setFarClipDistance(10000);
pCamera->setNearClipDistance(1.);
pCamera->lookAt(0,0,0);
//Ogre::ResourceGroupManager::getSingleton().addResourceLocation("C++/OgreSK/media/models","FileSystem","General");
Ogre::ResourceGroupManager::getSingleton().addResourceLocation("","FileSystem","General");
/*Ogre::ResourceGroupManager::getSingleton().addResourceLocation("C++/OgreSK/media/materials/scripts","FileSystem","General");
Ogre::ResourceGroupManager::getSingleton().addResourceLocation("C++/OgreSK/media/materials/textures","FileSystem","General");
Ogre::ResourceGroupManager::getSingleton().addResourceLocation("C++/OgreSK/media/materials/programs","FileSystem","General");*/
//OIS stuff
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
win->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
OIS::InputManager *pInputManager = OIS::InputManager::createInputSystem( pl );
OIS::Mouse *pMouse = static_cast<OIS::Mouse*>(pInputManager->createInputObject(OIS::OISMouse, false));
OIS::Keyboard* pKeyboard = static_cast<OIS::Keyboard*>(pInputManager->createInputObject(OIS::OISKeyboard, false));
unsigned int width, height, depth;
int top, left;
win->getMetrics(width, height, depth, left, top);
const OIS::MouseState &ms = pMouse->getMouseState();
ms.width = width;
ms.height = height;
//Ressources stuff
Bsa::addBSA("Morrowind.bsa");
//Ogre::ResourceGroupManager::getSingleton().createResourceGroup("general");
Ogre::ResourcePtr ptr = BulletShapeManager::getSingleton().getByName(mesh,"General");
NifBullet::ManualBulletShapeLoader* ShapeLoader = new NifBullet::ManualBulletShapeLoader();
ShapeLoader->load(mesh,"General");
//BulletShapeManager::getSingleton().unload(mesh);
//ShapeLoader->load(mesh,"General");
NIFLoader::load(mesh);
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
//BulletShapeManager::getSingleton().
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General");
BulletShapeManager::getSingleton().load(mesh,"General");
BulletShapeManager::getSingleton().unload(mesh);
BulletShapeManager::getSingleton().load(mesh,"General");
BulletShapeManager::getSingleton().load(mesh,"General");
//shape->load();
//shape->unload();
//shape->load();
//Bullet init
btBroadphaseInterface* broadphase = new btDbvtBroadphase();
// Set up the collision configuration and dispatcher
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
// The actual physics solver
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
// The world.
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
//le sol?
Ogre::SceneNode *node = scmg->getRootSceneNode()->createChildSceneNode("node");
Ogre::Entity *ent = scmg->createEntity("Mesh1",mesh);
node->attachObject(ent);
MyMotionState* mst = new MyMotionState(btTransform::getIdentity(),node);
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,mst,shape->Shape,btVector3(0,0,0));
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
dynamicsWorld->addRigidBody(groundRigidBody);
//une balle:
Ogre::SceneNode *node2 = scmg->getRootSceneNode()->createChildSceneNode("node2");
Ogre::Entity *ent2 = scmg->createEntity("Mesh2","ogrehead.mesh");
node2->attachObject(ent2);
node2->setPosition(0,500,0);
btTransform iT;
iT.setIdentity();
iT.setOrigin(btVector3(0,5000,0));
MyMotionState* mst2 = new MyMotionState(btTransform::getIdentity(),node2);
btSphereShape* sphereshape = new btSphereShape(10);
btRigidBody::btRigidBodyConstructionInfo sphereCI(10,mst2,sphereshape,btVector3(0,0,0));
btRigidBody* sphere = new btRigidBody(sphereCI);
dynamicsWorld->addRigidBody(sphere);
//btOgre!
BtOgre::DebugDrawer* mDebugDrawer = new BtOgre::DebugDrawer(scmg->getRootSceneNode(), dynamicsWorld);
dynamicsWorld->setDebugDrawer(mDebugDrawer);
Ogre::Timer timer;
timer.reset();
bool cont = true;
while(cont)
{
if(timer.getMilliseconds()>30)
{
pMouse->capture();
pKeyboard->capture();
Ogre::Vector3 a(0,0,0);
if(pKeyboard->isKeyDown(OIS::KC_UP))
{
a = a + Ogre::Vector3(0,0,-20);
}
if(pKeyboard->isKeyDown(OIS::KC_DOWN))
{
a = a + Ogre::Vector3(0,0,20);
}
if(pKeyboard->isKeyDown(OIS::KC_ESCAPE))
{
cont = false;
}
OIS::MouseState MS = pMouse->getMouseState();
pCamera->yaw(-Ogre::Degree(MS.X.rel));
pCamera->pitch(-Ogre::Degree(MS.Y.rel));
pCamera->moveRelative(a);
pRoot->renderOneFrame();
mDebugDrawer->step();
timer.reset();
dynamicsWorld->stepSimulation(0.03);
}
}
std::cout << "cool";
delete manag;
delete pRoot;
char a;
std::cin >> a;
}
catch(Ogre::Exception& e)
{
std::cout << e.getFullDescription();
char a;
std::cin >> a;
}
}