forked from mirror/openmw-tes3mp
Merge branch 'animation2'
commit
0c2de2c00c
@ -0,0 +1,130 @@
|
||||
#include "actors.hpp"
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
using namespace NifOgre;
|
||||
|
||||
void Actors::setMwRoot(Ogre::SceneNode* root){
|
||||
mMwRoot = root;
|
||||
}
|
||||
void Actors::insertNPC(const MWWorld::Ptr& ptr){
|
||||
|
||||
insertBegin(ptr, true, true);
|
||||
NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend);
|
||||
|
||||
//
|
||||
|
||||
mAllActors[ptr] = anim;
|
||||
|
||||
|
||||
}
|
||||
void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
|
||||
Ogre::SceneNode* cellnode;
|
||||
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end())
|
||||
{
|
||||
//Create the scenenode and put it in the map
|
||||
cellnode = mMwRoot->createChildSceneNode();
|
||||
mCellSceneNodes[ptr.getCell()] = cellnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellnode = mCellSceneNodes[ptr.getCell()];
|
||||
}
|
||||
|
||||
Ogre::SceneNode* insert = cellnode->createChildSceneNode();
|
||||
const float *f = ptr.getRefData().getPosition().pos;
|
||||
insert->setPosition(f[0], f[1], f[2]);
|
||||
insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale);
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ptr.getCellRef().pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
insert->setOrientation(xr*yr*zr);
|
||||
if (!enabled)
|
||||
insert->setVisible (false);
|
||||
ptr.getRefData().setBaseNode(insert);
|
||||
|
||||
|
||||
}
|
||||
void Actors::insertCreature (const MWWorld::Ptr& ptr){
|
||||
|
||||
insertBegin(ptr, true, true);
|
||||
CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend);
|
||||
//mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim));
|
||||
mAllActors[ptr] = anim;
|
||||
//mAllActors.push_back(&anim);*/
|
||||
}
|
||||
|
||||
bool Actors::deleteObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
delete mAllActors[ptr];
|
||||
mAllActors.erase(ptr);
|
||||
if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode())
|
||||
{
|
||||
|
||||
Ogre::SceneNode *parent = base->getParentSceneNode();
|
||||
|
||||
for (std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::const_iterator iter (
|
||||
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
|
||||
if (iter->second==parent)
|
||||
{
|
||||
base->removeAndDestroyAllChildren();
|
||||
mRend.getScene()->destroySceneNode (base);
|
||||
ptr.getRefData().setBaseNode (0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Actors::removeCell(MWWorld::Ptr::CellStore* store){
|
||||
if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
|
||||
{
|
||||
Ogre::SceneNode* base = mCellSceneNodes[store];
|
||||
base->removeAndDestroyAllChildren();
|
||||
mCellSceneNodes.erase(store);
|
||||
mRend.getScene()->destroySceneNode(base);
|
||||
base = 0;
|
||||
}
|
||||
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||
{
|
||||
if(iter->first.getCell() == store){
|
||||
delete iter->second;
|
||||
mAllActors.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->startScript(groupName, mode, number);
|
||||
}
|
||||
void Actors::skipAnimation (const MWWorld::Ptr& ptr){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->stopScript();
|
||||
}
|
||||
void Actors::addTime(){
|
||||
//std::cout << "Adding time in actors\n";
|
||||
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||
{
|
||||
(iter->second)->runAnimation(mEnvironment.mFrameDuration);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
#ifndef _GAME_RENDER_ACTORS_H
|
||||
#define _GAME_RENDER_ACTORS_H
|
||||
|
||||
#include "components/esm_store/cell_store.hpp"
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "npcanimation.hpp"
|
||||
#include "creatureanimation.hpp"
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
namespace MWRender{
|
||||
class Actors{
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||
Ogre::SceneNode* mMwRoot;
|
||||
MWWorld::Environment& mEnvironment;
|
||||
std::map<MWWorld::Ptr, Animation*> mAllActors;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){}
|
||||
~Actors(){}
|
||||
void setMwRoot(Ogre::SceneNode* root);
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertCreature (const MWWorld::Ptr& ptr);
|
||||
void insertNPC(const MWWorld::Ptr& ptr);
|
||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||
///< \return found?
|
||||
|
||||
void removeCell(MWWorld::Ptr::CellStore* store);
|
||||
|
||||
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
|
||||
int number = 1);
|
||||
///< Run animation for a MW-reference. Calls to this function for references that are currently not
|
||||
/// in the rendered scene should be ignored.
|
||||
///
|
||||
/// \param mode: 0 normal, 1 immediate start, 2 immediate loop
|
||||
/// \param number How offen the animation should be run
|
||||
|
||||
void skipAnimation (const MWWorld::Ptr& ptr);
|
||||
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
|
||||
/// references that are currently not in the rendered scene should be ignored.
|
||||
|
||||
void addTime();
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,568 @@
|
||||
#include "animation.hpp"
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
std::map<std::string, int> Animation::mUniqueIDs;
|
||||
|
||||
Animation::~Animation(){
|
||||
}
|
||||
|
||||
std::string Animation::getUniqueID(std::string mesh){
|
||||
int counter;
|
||||
std::string copy = mesh;
|
||||
std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
|
||||
if(mUniqueIDs.find(copy) == mUniqueIDs.end()){
|
||||
counter = mUniqueIDs[copy] = 0;
|
||||
}
|
||||
else{
|
||||
mUniqueIDs[copy] = mUniqueIDs[copy] + 1;
|
||||
counter = mUniqueIDs[copy];
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
if(counter > 99 && counter < 1000)
|
||||
out << "0";
|
||||
else if(counter > 9)
|
||||
out << "00";
|
||||
else
|
||||
out << "000";
|
||||
out << counter;
|
||||
return out.str();
|
||||
}
|
||||
void Animation::startScript(std::string groupname, int mode, int loops){
|
||||
//If groupname is recognized set animate to true
|
||||
//Set the start time and stop time
|
||||
//How many times to loop
|
||||
if(groupname == "all"){
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
}
|
||||
else if(textmappings){
|
||||
|
||||
std::string startName = groupname + ": loop start";
|
||||
std::string stopName = groupname + ": loop stop";
|
||||
|
||||
bool first = false;
|
||||
|
||||
if(loops > 1){
|
||||
startName = groupname + ": loop start";
|
||||
stopName = groupname + ": loop stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName){
|
||||
startTime = iter->second;
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName){
|
||||
stopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!first){
|
||||
startName = groupname + ": start";
|
||||
stopName = groupname + ": stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName){
|
||||
startTime = iter->second;
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName){
|
||||
stopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void Animation::stopScript(){
|
||||
animate = 0;
|
||||
}
|
||||
|
||||
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
|
||||
bool useHandles = skel == creaturemodel->getSkeleton();
|
||||
shapeNumber = 0;
|
||||
|
||||
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
||||
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
||||
|
||||
{
|
||||
//std::map<unsigned short, PosAndRot> vecPosRot;
|
||||
|
||||
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
||||
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
||||
|
||||
//std::set<unsigned int> vertices;
|
||||
//std::set<unsigned int> normals;
|
||||
//std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfovector = copy.boneinfo;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >* verticesToChange = ©.vertsToWeights;
|
||||
|
||||
//std::cout << "Name " << copy.sname << "\n";
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0);
|
||||
Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||
//Ogre::HardwareVertexBufferSharedPtr vbufNormal = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(1);
|
||||
// Ogre::Real* pRealNormal = static_cast<Ogre::Real*>(vbufNormal->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||
|
||||
std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices();
|
||||
//Each shape has multiple indices
|
||||
if(initialVertices.size() )
|
||||
{
|
||||
|
||||
if(copy.vertices.size() == initialVertices.size())
|
||||
{
|
||||
//Create if it doesn't already exist
|
||||
if(shapeIndexI.size() == static_cast<std::size_t> (shapeNumber))
|
||||
{
|
||||
std::vector<int> vec;
|
||||
shapeIndexI.push_back(vec);
|
||||
}
|
||||
if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){
|
||||
float x;
|
||||
for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){
|
||||
int j = 0;
|
||||
if(shapeIndexI[shapeNumber].size() <= i)
|
||||
shapeIndexI[shapeNumber].push_back(0);
|
||||
|
||||
|
||||
if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){
|
||||
int indexI = (shapeIndexI[shapeNumber])[i];
|
||||
std::vector<Ogre::Vector3> relevantData = (copy.morph.getRelevantData()[i]);
|
||||
float v1 = relevantData[indexI].x;
|
||||
float v2 = relevantData[j].x;
|
||||
float t = v1 + (v2 - v1) * x;
|
||||
if ( t < 0 ) t = 0;
|
||||
if ( t > 1 ) t = 1;
|
||||
if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size())
|
||||
{
|
||||
for (unsigned int v = 0; v < initialVertices.size(); v++){
|
||||
initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
allvertices = &initialVertices;
|
||||
}
|
||||
shapeNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(verticesToChange->size() > 0){
|
||||
|
||||
for(std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >::iterator iter = verticesToChange->begin();
|
||||
iter != verticesToChange->end(); iter++)
|
||||
{
|
||||
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
|
||||
int verIndex = iter->first;
|
||||
Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
|
||||
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
|
||||
Ogre::Bone *bonePtr = 0;
|
||||
if(useHandles)
|
||||
{
|
||||
bonePtr = skel->getBone(boneinfocopy->bonehandle);
|
||||
}
|
||||
else
|
||||
bonePtr = skel->getBone(boneinfocopy->bonename);
|
||||
|
||||
Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
|
||||
/*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){
|
||||
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
if(useHandles){
|
||||
PosAndRot both;
|
||||
both.vecPos = vecPos;
|
||||
both.vecRot = vecRot;
|
||||
vecPosRot[boneinfocopy->bonehandle] = both;
|
||||
}
|
||||
}
|
||||
else{
|
||||
PosAndRot both = vecPosRot[boneinfocopy->bonehandle];
|
||||
vecPos = both.vecPos;
|
||||
vecRot = both.vecRot;
|
||||
}*/
|
||||
|
||||
Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight;
|
||||
|
||||
|
||||
for(std::size_t i = 1; i < inds.size(); i++){
|
||||
boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]);
|
||||
if(useHandles)
|
||||
bonePtr = skel->getBone(boneinfocopy->bonehandle);
|
||||
else
|
||||
bonePtr = skel->getBone(boneinfocopy->bonename);
|
||||
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
/*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){
|
||||
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
if(useHandles){
|
||||
PosAndRot both;
|
||||
both.vecPos = vecPos;
|
||||
both.vecRot = vecRot;
|
||||
vecPosRot[boneinfocopy->bonehandle] = both;
|
||||
}
|
||||
}
|
||||
else{
|
||||
PosAndRot both = vecPosRot[boneinfocopy->bonehandle];
|
||||
vecPos = both.vecPos;
|
||||
vecRot = both.vecRot;
|
||||
}*/
|
||||
|
||||
|
||||
absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight;
|
||||
|
||||
}
|
||||
Ogre::Real* addr = (pReal + 3 * verIndex);
|
||||
*addr = absVertPos.x;
|
||||
*(addr+1) = absVertPos.y;
|
||||
*(addr+2) = absVertPos.z;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (unsigned int i = 0; i < boneinfovector.size(); i++)
|
||||
{
|
||||
Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[i];
|
||||
if(skel->hasBone(boneinfo.bonename)){
|
||||
Ogre::Bone *bonePtr = skel->getBone(boneinfo.bonename);
|
||||
Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans;
|
||||
Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation;
|
||||
|
||||
for (unsigned int j=0; j < boneinfo.weights.size(); j++)
|
||||
{
|
||||
unsigned int verIndex = boneinfo.weights[j].vertex;
|
||||
if(vertices.find(verIndex) == vertices.end())
|
||||
{
|
||||
Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex];
|
||||
absVertPos = absVertPos * boneinfo.weights[j].weight;
|
||||
vertices.insert(verIndex);
|
||||
Ogre::Real* addr = (pReal + 3 * verIndex);
|
||||
*addr = absVertPos.x;
|
||||
*(addr+1) = absVertPos.y;
|
||||
*(addr+2) = absVertPos.z;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex];
|
||||
absVertPos = absVertPos * boneinfo.weights[j].weight;
|
||||
Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex);
|
||||
absVertPos = absVertPos + old;
|
||||
Ogre::Real* addr = (pReal + 3 * verIndex);
|
||||
*addr = absVertPos.x;
|
||||
*(addr+1) = absVertPos.y;
|
||||
*(addr+2) = absVertPos.z;
|
||||
|
||||
//std::cout << "Vertex" << verIndex << "Weight: " << boneinfo.weights[i].weight << "was seen twice\n";
|
||||
|
||||
}
|
||||
|
||||
if(normals.find(verIndex) == normals.end())
|
||||
{
|
||||
Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex];
|
||||
absNormalsPos = absNormalsPos * boneinfo.weights[j].weight;
|
||||
normals.insert(verIndex);
|
||||
Ogre::Real* addr = (pRealNormal + 3 * verIndex);
|
||||
*addr = absNormalsPos.x;
|
||||
*(addr+1) = absNormalsPos.y;
|
||||
*(addr+2) = absNormalsPos.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex];
|
||||
absNormalsPos = absNormalsPos * boneinfo.weights[j].weight;
|
||||
Ogre::Vector3 old = Ogre::Vector3(pRealNormal + 3 * verIndex);
|
||||
absNormalsPos = absNormalsPos + old;
|
||||
|
||||
Ogre::Real* addr = (pRealNormal + 3 * verIndex);
|
||||
*addr = absNormalsPos.x;
|
||||
*(addr+1) = absNormalsPos.y;
|
||||
*(addr+2) = absNormalsPos.z;
|
||||
|
||||
}
|
||||
#endif
|
||||
//}
|
||||
//}
|
||||
|
||||
|
||||
//} //Comment out
|
||||
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename);
|
||||
Ogre::Quaternion shaperot = copy.trafo.rotation;
|
||||
Ogre::Vector3 shapetrans = copy.trafo.trans;
|
||||
float shapescale = copy.trafo.scale;
|
||||
std::vector<std::string> boneSequence = copy.boneSequence;
|
||||
std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin();
|
||||
Ogre::Vector3 transmult;
|
||||
Ogre::Quaternion rotmult;
|
||||
float scale;
|
||||
if(skel->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter);
|
||||
|
||||
|
||||
|
||||
|
||||
transmult = bonePtr->getPosition();
|
||||
rotmult = bonePtr->getOrientation();
|
||||
scale = bonePtr->getScale().x;
|
||||
boneSequenceIter++;
|
||||
for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++)
|
||||
{
|
||||
if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(*boneSequenceIter);
|
||||
// Computes C = B + AxC*scale
|
||||
transmult = transmult + rotmult * bonePtr->getPosition();
|
||||
rotmult = rotmult * bonePtr->getOrientation();
|
||||
scale = scale * bonePtr->getScale().x;
|
||||
}
|
||||
//std::cout << "Bone:" << *boneSequenceIter << " ";
|
||||
}
|
||||
transmult = transmult + rotmult * shapetrans;
|
||||
rotmult = rotmult * shaperot;
|
||||
scale = shapescale * scale;
|
||||
|
||||
//std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
transmult = shapetrans;
|
||||
rotmult = shaperot;
|
||||
scale = shapescale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Computes C = B + AxC*scale
|
||||
// final_vector = old_vector + old_rotation*new_vector*old_scale/
|
||||
|
||||
for(unsigned int i = 0; i < allvertices->size(); i++){
|
||||
Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i];
|
||||
Ogre::Real* addr = pReal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}/*
|
||||
for(int i = 0; i < allnormals.size(); i++){
|
||||
Ogre::Vector3 current =rotmult * allnormals[i];
|
||||
Ogre::Real* addr = pRealNormal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}*/
|
||||
|
||||
}
|
||||
vbuf->unlock();
|
||||
//vbufNormal->unlock();
|
||||
}
|
||||
|
||||
}
|
||||
bool Animation::timeIndex( float time, std::vector<float> times, int & i, int & j, float & x ){
|
||||
int count;
|
||||
if ( (count = times.size()) > 0 )
|
||||
{
|
||||
if ( time <= times[0] )
|
||||
{
|
||||
i = j = 0;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
if ( time >= times[count - 1] )
|
||||
{
|
||||
i = j = count - 1;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( i < 0 || i >= count )
|
||||
i = 0;
|
||||
|
||||
float tI = times[i];
|
||||
if ( time > tI )
|
||||
{
|
||||
j = i + 1;
|
||||
float tJ;
|
||||
while ( time >= ( tJ = times[j]) )
|
||||
{
|
||||
i = j++;
|
||||
tI = tJ;
|
||||
}
|
||||
x = ( time - tI ) / ( tJ - tI );
|
||||
return true;
|
||||
}
|
||||
else if ( time < tI )
|
||||
{
|
||||
j = i - 1;
|
||||
float tJ;
|
||||
while ( time <= ( tJ = times[j] ) )
|
||||
{
|
||||
i = j--;
|
||||
tI = tJ;
|
||||
}
|
||||
x = ( time - tI ) / ( tJ - tI );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = i;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void Animation::handleAnimationTransforms(){
|
||||
Ogre::SkeletonInstance* skel = base->getSkeleton();
|
||||
|
||||
|
||||
Ogre::Bone* b = skel->getRootBone();
|
||||
b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick
|
||||
|
||||
skel->_updateTransforms();
|
||||
//skel->_notifyManualBonesDirty();
|
||||
|
||||
base->getAllAnimationStates()->_notifyDirty();
|
||||
//base->_updateAnimation();
|
||||
base->_notifyMoved();
|
||||
|
||||
for(unsigned int i = 0; i < entityparts.size(); i++){
|
||||
Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton();
|
||||
|
||||
Ogre::Bone* b = skel->getRootBone();
|
||||
b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick
|
||||
|
||||
skel->_updateTransforms();
|
||||
// skel->_notifyManualBonesDirty();
|
||||
|
||||
entityparts[i]->getAllAnimationStates()->_notifyDirty();
|
||||
//entityparts[i]->_updateAnimation();
|
||||
entityparts[i]->_notifyMoved();
|
||||
}
|
||||
|
||||
std::vector<Nif::NiKeyframeData>::iterator iter;
|
||||
int slot = 0;
|
||||
if(transformations){
|
||||
for(iter = transformations->begin(); iter != transformations->end(); iter++){
|
||||
if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime())
|
||||
{
|
||||
slot++;
|
||||
//iter++;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
float x;
|
||||
float x2;
|
||||
|
||||
std::vector<Ogre::Quaternion> quats = iter->getQuat();
|
||||
|
||||
std::vector<float> ttime = iter->gettTime();
|
||||
std::vector<float>::iterator ttimeiter = ttime.begin();
|
||||
|
||||
std::vector<float> rtime = iter->getrTime();
|
||||
int rindexJ = 0;
|
||||
timeIndex(time, rtime, rindexI[slot], rindexJ, x2);
|
||||
int tindexJ = 0;
|
||||
|
||||
|
||||
std::vector<Ogre::Vector3> translist1 = iter->getTranslist1();
|
||||
|
||||
timeIndex(time, ttime, tindexI[slot], tindexJ, x);
|
||||
|
||||
//std::cout << "X: " << x << " X2: " << x2 << "\n";
|
||||
Ogre::Vector3 t;
|
||||
Ogre::Quaternion r;
|
||||
|
||||
bool bTrans = translist1.size() > 0;
|
||||
if(bTrans){
|
||||
Ogre::Vector3 v1 = translist1[tindexI[slot]];
|
||||
Ogre::Vector3 v2 = translist1[tindexJ];
|
||||
t = (v1 + (v2 - v1) * x);
|
||||
|
||||
}
|
||||
|
||||
bool bQuats = quats.size() > 0;
|
||||
if(bQuats){
|
||||
r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true);
|
||||
//bone->setOrientation(r);
|
||||
}
|
||||
skel = base->getSkeleton();
|
||||
if(skel->hasBone(iter->getBonename())){
|
||||
Ogre::Bone* bone = skel->getBone(iter->getBonename());
|
||||
if(bTrans)
|
||||
bone->setPosition(t);
|
||||
if(bQuats)
|
||||
bone->setOrientation(r);
|
||||
|
||||
|
||||
|
||||
skel->_updateTransforms();
|
||||
//skel->_notifyManualBonesDirty();
|
||||
base->getAllAnimationStates()->_notifyDirty();
|
||||
//base->_updateAnimation();
|
||||
base->_notifyMoved();
|
||||
}
|
||||
for(std::size_t i = 0; i < entityparts.size(); i++){
|
||||
skel = entityparts[i]->getSkeleton();
|
||||
if(skel->hasBone(iter->getBonename())){
|
||||
Ogre::Bone* bone = skel->getBone(iter->getBonename());
|
||||
if(bTrans)
|
||||
bone->setPosition(t);
|
||||
if(bQuats)
|
||||
bone->setOrientation(r);
|
||||
|
||||
skel->_updateTransforms();
|
||||
//skel->_notifyManualBonesDirty();
|
||||
entityparts[i]->getAllAnimationStates()->_notifyDirty();
|
||||
// entityparts[i]->_updateAnimation();
|
||||
entityparts[i]->_notifyMoved();
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
#ifndef _GAME_RENDER_ANIMATION_H
|
||||
#define _GAME_RENDER_ANIMATION_H
|
||||
#include <components/nif/data.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
#include <map>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
struct PosAndRot{
|
||||
Ogre::Quaternion vecRot;
|
||||
Ogre::Vector3 vecPos;
|
||||
};
|
||||
|
||||
class Animation{
|
||||
|
||||
protected:
|
||||
Ogre::SceneNode* insert;
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
MWWorld::Environment& mEnvironment;
|
||||
static std::map<std::string, int> mUniqueIDs;
|
||||
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>* > shapeparts; //All the NiTriShape data that we need for animating an npc
|
||||
|
||||
float time;
|
||||
float startTime;
|
||||
float stopTime;
|
||||
int animate;
|
||||
//Represents a rotation index for each bone
|
||||
std::vector<int>rindexI;
|
||||
//Represents a translation index for each bone
|
||||
std::vector<int>tindexI;
|
||||
|
||||
//Only shapes with morphing data will use a shape number
|
||||
int shapeNumber;
|
||||
std::vector<std::vector<int> > shapeIndexI;
|
||||
|
||||
//Ogre::SkeletonInstance* skel;
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes; //All the NiTriShapeData for a creature
|
||||
std::vector<Ogre::Entity*> entityparts;
|
||||
|
||||
|
||||
std::vector<Nif::NiKeyframeData>* transformations;
|
||||
std::map<std::string,float>* textmappings;
|
||||
Ogre::Entity* base;
|
||||
void handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel);
|
||||
void handleAnimationTransforms();
|
||||
bool timeIndex( float time, std::vector<float> times, int & i, int & j, float & x );
|
||||
std::string getUniqueID(std::string mesh);
|
||||
|
||||
public:
|
||||
Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend): mRend(_rend), mEnvironment(_env), animate(0){};
|
||||
virtual void runAnimation(float timepassed) = 0;
|
||||
void startScript(std::string groupname, int mode, int loops);
|
||||
void stopScript();
|
||||
|
||||
|
||||
~Animation();
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
@ -1,67 +0,0 @@
|
||||
#include "cellimp.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
|
||||
template<typename T>
|
||||
void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment,
|
||||
T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
|
||||
{
|
||||
if (!cellRefList.list.empty())
|
||||
{
|
||||
const MWWorld::Class& class_ =
|
||||
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell));
|
||||
|
||||
for (typename T::List::iterator it = cellRefList.list.begin();
|
||||
it != cellRefList.list.end(); it++)
|
||||
{
|
||||
if (it->mData.getCount() || it->mData.isEnabled())
|
||||
{
|
||||
MWWorld::Ptr ptr (&*it, &cell);
|
||||
|
||||
try
|
||||
{
|
||||
class_.insertObj (ptr, cellRender, environment);
|
||||
class_.enable (ptr, environment);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::string error ("error during rendering: ");
|
||||
std::cerr << error + e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CellRenderImp::insertCell(ESMS::CellStore<MWWorld::RefData> &cell,
|
||||
MWWorld::Environment& environment)
|
||||
{
|
||||
// Loop through all references in the cell
|
||||
insertCellRefList (*this, environment, cell.activators, cell);
|
||||
insertCellRefList (*this, environment, cell.potions, cell);
|
||||
insertCellRefList (*this, environment, cell.appas, cell);
|
||||
insertCellRefList (*this, environment, cell.armors, cell);
|
||||
insertCellRefList (*this, environment, cell.books, cell);
|
||||
insertCellRefList (*this, environment, cell.clothes, cell);
|
||||
insertCellRefList (*this, environment, cell.containers, cell);
|
||||
insertCellRefList (*this, environment, cell.creatures, cell);
|
||||
insertCellRefList (*this, environment, cell.doors, cell);
|
||||
insertCellRefList (*this, environment, cell.ingreds, cell);
|
||||
insertCellRefList (*this, environment, cell.creatureLists, cell);
|
||||
insertCellRefList (*this, environment, cell.itemLists, cell);
|
||||
insertCellRefList (*this, environment, cell.lights, cell);
|
||||
insertCellRefList (*this, environment, cell.lockpicks, cell);
|
||||
insertCellRefList (*this, environment, cell.miscItems, cell);
|
||||
insertCellRefList (*this, environment, cell.npcs, cell);
|
||||
insertCellRefList (*this, environment, cell.probes, cell);
|
||||
insertCellRefList (*this, environment, cell.repairs, cell);
|
||||
insertCellRefList (*this, environment, cell.statics, cell);
|
||||
insertCellRefList (*this, environment, cell.weapons, cell);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
#ifndef _GAME_RENDER_CELLIMP_H
|
||||
#define _GAME_RENDER_CELLIMP_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "components/esm_store/cell_store.hpp"
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include <OgreMath.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneNode;
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class CellRef;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
namespace MWRender
|
||||
{
|
||||
/// Base class for cell render, that implements inserting references into a cell in a
|
||||
/// cell type- and render-engine-independent way.
|
||||
|
||||
class CellRenderImp
|
||||
{
|
||||
public:
|
||||
CellRenderImp() {}
|
||||
virtual ~CellRenderImp() {}
|
||||
|
||||
/// start inserting a new reference.
|
||||
virtual void insertBegin (ESM::CellRef& ref, MWWorld::RefData& refData, bool static_ = false) = 0;
|
||||
|
||||
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) = 0;
|
||||
/// insert a mesh related to the most recent insertBegin call.
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst) = 0;
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) = 0;
|
||||
virtual void insertMesh(const std::string &mesh) = 0;
|
||||
|
||||
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) = 0;
|
||||
|
||||
virtual void insertObjectPhysics() = 0;
|
||||
|
||||
virtual void insertActorPhysics() = 0;
|
||||
|
||||
/// insert a light related to the most recent insertBegin call.
|
||||
virtual void insertLight(float r, float g, float b, float radius) = 0;
|
||||
|
||||
/// finish inserting a new reference and return a handle to it.
|
||||
virtual std::string insertEnd (bool Enable) = 0;
|
||||
|
||||
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
|
||||
|
||||
};
|
||||
|
||||
/// Exception-safe rendering
|
||||
class Rendering
|
||||
{
|
||||
CellRenderImp& mCellRender;
|
||||
bool mEnd;
|
||||
|
||||
// not implemented
|
||||
Rendering (const Rendering&);
|
||||
Rendering& operator= (const Rendering&);
|
||||
|
||||
public:
|
||||
|
||||
Rendering (CellRenderImp& cellRender, ESM::CellRef& ref, MWWorld::RefData& refData, bool static_ = false)
|
||||
: mCellRender (cellRender), mEnd (false)
|
||||
{
|
||||
mCellRender.insertBegin (ref, refData, static_);
|
||||
}
|
||||
|
||||
~Rendering()
|
||||
{
|
||||
if (!mEnd)
|
||||
mCellRender.insertEnd (false);
|
||||
}
|
||||
|
||||
std::string end (bool enable)
|
||||
{
|
||||
assert (!mEnd);
|
||||
mEnd = true;
|
||||
return mCellRender.insertEnd (enable);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,62 @@
|
||||
#include "creatureanimation.hpp"
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace NifOgre;
|
||||
namespace MWRender{
|
||||
|
||||
CreatureAnimation::~CreatureAnimation(){
|
||||
|
||||
}
|
||||
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){
|
||||
insert = ptr.getRefData().getBaseNode();
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
assert (ref->base != NULL);
|
||||
if(!ref->base->model.empty()){
|
||||
const std::string &mesh = "meshes\\" + ref->base->model;
|
||||
std::string meshNumbered = mesh + getUniqueID(mesh) + ">|";
|
||||
NifOgre::NIFLoader::load(meshNumbered);
|
||||
base = mRend.getScene()->createEntity(meshNumbered);
|
||||
std::string meshZero = mesh + "0000>|";
|
||||
|
||||
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){
|
||||
|
||||
for(std::size_t init = 0; init < transformations->size(); init++){
|
||||
rindexI.push_back(0);
|
||||
tindexI.push_back(0);
|
||||
}
|
||||
stopTime = transformations->begin()->getStopTime();
|
||||
startTime = transformations->begin()->getStartTime();
|
||||
shapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero);
|
||||
}
|
||||
textmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero);
|
||||
insert->attachObject(base);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureAnimation::runAnimation(float timepassed){
|
||||
if(animate > 0){
|
||||
//Add the amount of time passed to time
|
||||
|
||||
//Handle the animation transforms dependent on time
|
||||
|
||||
//Handle the shapes dependent on animation transforms
|
||||
time += timepassed;
|
||||
if(time >= stopTime){
|
||||
animate--;
|
||||
//std::cout << "Stopping the animation\n";
|
||||
if(animate == 0)
|
||||
time = stopTime;
|
||||
else
|
||||
time = startTime + (time - stopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
handleShapes(shapes, base, base->getSkeleton());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#ifndef _GAME_RENDER_CREATUREANIMATION_H
|
||||
#define _GAME_RENDER_CREATUREANIMATION_H
|
||||
|
||||
#include "animation.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class CreatureAnimation: public Animation{
|
||||
|
||||
public:
|
||||
~CreatureAnimation();
|
||||
CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||
virtual void runAnimation(float timepassed);
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,38 @@
|
||||
#include "debugging.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "OgreRoot.h"
|
||||
#include "OgreRenderWindow.h"
|
||||
#include "OgreSceneManager.h"
|
||||
#include "OgreViewport.h"
|
||||
#include "OgreCamera.h"
|
||||
#include "OgreTextureManager.h"
|
||||
|
||||
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <components/esm/loadstat.hpp>
|
||||
|
||||
#include "player.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
||||
Debugging::Debugging(OEngine::Physic::PhysicEngine* engine){
|
||||
eng = engine;
|
||||
}
|
||||
|
||||
|
||||
bool Debugging::toggleRenderMode (int mode){
|
||||
switch (mode)
|
||||
{
|
||||
case MWWorld::World::Render_CollisionDebug:
|
||||
|
||||
// TODO use a proper function instead of accessing the member variable
|
||||
// directly.
|
||||
eng->setDebugRenderingMode (!eng->isDebugCreated);
|
||||
return eng->isDebugCreated;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
#ifndef _GAME_RENDER_MWSCENE_H
|
||||
#define _GAME_RENDER_MWSCENE_H
|
||||
|
||||
#include <utility>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Camera;
|
||||
class Viewport;
|
||||
class SceneManager;
|
||||
class SceneNode;
|
||||
class RaySceneQuery;
|
||||
class Quaternion;
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class Player;
|
||||
|
||||
class Debugging{
|
||||
OEngine::Physic::PhysicEngine* eng;
|
||||
|
||||
|
||||
public:
|
||||
Debugging(OEngine::Physic::PhysicEngine* engine);
|
||||
bool toggleRenderMode (int mode);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,454 +0,0 @@
|
||||
#include "exterior.hpp"
|
||||
|
||||
#include <OgreEntity.h>
|
||||
#include <OgreLight.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreSceneManager.h>
|
||||
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
#include "mwscene.hpp"
|
||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
||||
#include "mwscene.hpp"
|
||||
#include <Ogre.h>
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
using namespace ESMS;
|
||||
|
||||
bool ExteriorCellRender::lightConst = false;
|
||||
float ExteriorCellRender::lightConstValue = 0.0f;
|
||||
|
||||
bool ExteriorCellRender::lightLinear = true;
|
||||
int ExteriorCellRender::lightLinearMethod = 1;
|
||||
float ExteriorCellRender::lightLinearValue = 3;
|
||||
float ExteriorCellRender::lightLinearRadiusMult = 1;
|
||||
|
||||
bool ExteriorCellRender::lightQuadratic = false;
|
||||
int ExteriorCellRender::lightQuadraticMethod = 2;
|
||||
float ExteriorCellRender::lightQuadraticValue = 16;
|
||||
float ExteriorCellRender::lightQuadraticRadiusMult = 1;
|
||||
|
||||
bool ExteriorCellRender::lightOutQuadInLin = false;
|
||||
|
||||
int ExteriorCellRender::uniqueID = 0;
|
||||
|
||||
ExteriorCellRender::ExteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, MWWorld::Environment& environment,
|
||||
MWScene &_scene, MWWorld::PhysicsSystem *physics)
|
||||
: mCell(_cell), mEnvironment (environment), mScene(_scene), mPhysics(physics), mBase(NULL), mInsert(NULL), mAmbientMode (0)
|
||||
{
|
||||
uniqueID = uniqueID +1;
|
||||
sg = mScene.getMgr()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ExteriorCellRender::insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_)
|
||||
{
|
||||
assert (!mInsert);
|
||||
|
||||
isStatic = static_;
|
||||
|
||||
// Create and place scene node for this object
|
||||
mInsert = mBase->createChildSceneNode();
|
||||
|
||||
const float *f = ref.pos.pos;
|
||||
mInsert->setPosition(f[0], f[1], f[2]);
|
||||
mInsert->setScale(ref.scale, ref.scale, ref.scale);
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ref.pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
mInsert->setOrientation(xr*yr*zr);
|
||||
|
||||
mInsertMesh.clear();
|
||||
}
|
||||
|
||||
|
||||
void ExteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements)
|
||||
{
|
||||
assert(mInsert);
|
||||
Ogre::SceneNode *parent = mInsert;
|
||||
//std::cout << "ELEMENTS:" << elements;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneNodeName[i]));
|
||||
}
|
||||
parent->rotate(axis, angle);
|
||||
}
|
||||
/*
|
||||
void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements){
|
||||
assert (mInsert);
|
||||
//mInsert->
|
||||
Ogre::SceneNode *parent = mInsert;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
|
||||
}
|
||||
|
||||
mNpcPart = parent->createChildSceneNode(sceneNodeName);
|
||||
NIFLoader::load(mesh);
|
||||
MovableObject *ent = mScene.getMgr()->createEntity(mesh);
|
||||
|
||||
mNpcPart->translate(vec);
|
||||
mNpcPart->rotate(axis, angle);
|
||||
// mNpcPart->translate(vec);
|
||||
//mNpcPart->rotate(axis, angle);
|
||||
mNpcPart->attachObject(ent);
|
||||
//mNpcPart->
|
||||
|
||||
}
|
||||
*/
|
||||
void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements)
|
||||
{
|
||||
insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true);
|
||||
}
|
||||
void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){
|
||||
|
||||
assert (mInsert);
|
||||
//mInsert->
|
||||
Ogre::SceneNode *parent = mInsert;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
|
||||
}
|
||||
|
||||
mNpcPart = parent->createChildSceneNode(sceneNodeName);
|
||||
MeshPtr good2 = NifOgre::NIFLoader::load(mesh);
|
||||
|
||||
MovableObject *ent = mScene.getMgr()->createEntity(mesh);
|
||||
|
||||
|
||||
if(translateFirst){
|
||||
mNpcPart->translate(vec);
|
||||
mNpcPart->rotate(axis, angle);
|
||||
}
|
||||
else{
|
||||
|
||||
mNpcPart->rotate(axis, angle);
|
||||
mNpcPart->translate(vec);
|
||||
}
|
||||
mNpcPart->attachObject(ent);
|
||||
|
||||
Ogre::MeshManager *m = MeshManager::getSingletonPtr();
|
||||
const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif";
|
||||
|
||||
const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif";
|
||||
|
||||
const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif";
|
||||
if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGKHAJIITF\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail1);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot1);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGKHAJIITM\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail2);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot2);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGARGONIANF\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail3);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot3);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGARGONIANM\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail4);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot4);
|
||||
good2->reload();
|
||||
}
|
||||
}
|
||||
// insert a mesh related to the most recent insertBegin call.
|
||||
|
||||
void ExteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements)
|
||||
{
|
||||
assert(mInsert);
|
||||
Ogre::SceneNode *parent = mInsert;
|
||||
//std::cout << "ELEMENTS:" << elements;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneNodeName[i]));
|
||||
}
|
||||
parent->scale(axis);
|
||||
}
|
||||
|
||||
// insert a mesh related to the most recent insertBegin call.
|
||||
|
||||
|
||||
void ExteriorCellRender::insertMesh(const std::string &mesh)
|
||||
{
|
||||
assert (mInsert);
|
||||
|
||||
NifOgre::NIFLoader::load(mesh);
|
||||
Entity *ent = mScene.getMgr()->createEntity(mesh);
|
||||
|
||||
if(!isStatic)
|
||||
{
|
||||
mInsert->attachObject(ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
sg->addEntity(ent,mInsert->_getDerivedPosition(),mInsert->_getDerivedOrientation(),mInsert->_getDerivedScale());
|
||||
sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000));
|
||||
mScene.getMgr()->destroyEntity(ent);
|
||||
}
|
||||
if (mInsertMesh.empty())
|
||||
mInsertMesh = mesh;
|
||||
}
|
||||
|
||||
void ExteriorCellRender::insertObjectPhysics()
|
||||
{
|
||||
if (!mInsertMesh.empty())
|
||||
{
|
||||
mPhysics->addObject (mInsert->getName(), mInsertMesh, mInsert->getOrientation(),
|
||||
mInsert->getScale().x, mInsert->getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
void ExteriorCellRender::insertActorPhysics()
|
||||
{
|
||||
mPhysics->addActor (mInsert->getName(), mInsertMesh, mInsert->getPosition());
|
||||
}
|
||||
|
||||
// insert a light related to the most recent insertBegin call.
|
||||
void ExteriorCellRender::insertLight(float r, float g, float b, float radius)
|
||||
{
|
||||
assert (mInsert);
|
||||
|
||||
Ogre::Light *light = mScene.getMgr()->createLight();
|
||||
light->setDiffuseColour (r, g, b);
|
||||
|
||||
float cval=0.0f, lval=0.0f, qval=0.0f;
|
||||
|
||||
if(lightConst)
|
||||
cval = lightConstValue;
|
||||
if(!lightOutQuadInLin)
|
||||
{
|
||||
if(lightLinear)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
}
|
||||
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
|
||||
mInsert->attachObject(light);
|
||||
}
|
||||
|
||||
// finish inserting a new reference and return a handle to it.
|
||||
|
||||
std::string ExteriorCellRender::insertEnd (bool enable)
|
||||
{
|
||||
assert (mInsert);
|
||||
|
||||
std::string handle = mInsert->getName();
|
||||
|
||||
if (!enable)
|
||||
mInsert->setVisible (false);
|
||||
|
||||
mInsert = 0;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// configure lighting according to cell
|
||||
|
||||
void ExteriorCellRender::configureAmbient()
|
||||
{
|
||||
mAmbientColor.setAsABGR (mCell.cell->ambi.ambient);
|
||||
setAmbientMode();
|
||||
|
||||
// Create a "sun" that shines light downwards. It doesn't look
|
||||
// completely right, but leave it for now.
|
||||
Ogre::Light *light = mScene.getMgr()->createLight();
|
||||
Ogre::ColourValue colour;
|
||||
colour.setAsABGR (mCell.cell->ambi.sunlight);
|
||||
light->setDiffuseColour (colour);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDirection(0,-1,0);
|
||||
}
|
||||
|
||||
// configure fog according to cell
|
||||
void ExteriorCellRender::configureFog()
|
||||
{
|
||||
Ogre::ColourValue color;
|
||||
color.setAsABGR (mCell.cell->ambi.fog);
|
||||
|
||||
float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity);
|
||||
float low = 200;
|
||||
|
||||
mScene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high);
|
||||
mScene.getCamera()->setFarClipDistance (high + 10);
|
||||
mScene.getViewport()->setBackgroundColour (color);
|
||||
}
|
||||
|
||||
void ExteriorCellRender::setAmbientMode()
|
||||
{
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0:
|
||||
|
||||
mScene.getMgr()->setAmbientLight(mAmbientColor);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
mScene.getMgr()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
mScene.getMgr()->setAmbientLight(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ExteriorCellRender::show()
|
||||
{
|
||||
// FIXME: this one may be the bug
|
||||
mBase = mScene.getRoot()->createChildSceneNode();
|
||||
|
||||
configureAmbient();
|
||||
configureFog();
|
||||
|
||||
insertCell(mCell, mEnvironment);
|
||||
|
||||
sg->build();
|
||||
}
|
||||
|
||||
void ExteriorCellRender::hide()
|
||||
{
|
||||
if(mBase)
|
||||
mBase->setVisible(false);
|
||||
}
|
||||
|
||||
void ExteriorCellRender::destroyAllAttachedMovableObjects(Ogre::SceneNode* i_pSceneNode)
|
||||
{
|
||||
if ( !i_pSceneNode )
|
||||
{
|
||||
assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy all the attached objects
|
||||
SceneNode::ObjectIterator itObject = i_pSceneNode->getAttachedObjectIterator();
|
||||
|
||||
while ( itObject.hasMoreElements() )
|
||||
{
|
||||
MovableObject* pObject = static_cast<MovableObject*>(itObject.getNext());
|
||||
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
||||
}
|
||||
|
||||
// Recurse to child SceneNodes
|
||||
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
||||
|
||||
while ( itChild.hasMoreElements() )
|
||||
{
|
||||
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
||||
destroyAllAttachedMovableObjects( pChildNode );
|
||||
}
|
||||
}
|
||||
|
||||
void ExteriorCellRender::destroy()
|
||||
{
|
||||
if(mBase)
|
||||
{
|
||||
destroyAllAttachedMovableObjects(mBase);
|
||||
mBase->removeAndDestroyAllChildren();
|
||||
mScene.getMgr()->destroySceneNode(mBase);
|
||||
}
|
||||
|
||||
mBase = 0;
|
||||
|
||||
if (sg)
|
||||
{
|
||||
mScene.getMgr()->destroyStaticGeometry (sg);
|
||||
sg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Switch through lighting modes.
|
||||
|
||||
void ExteriorCellRender::toggleLight()
|
||||
{
|
||||
if (mAmbientMode==2)
|
||||
mAmbientMode = 0;
|
||||
else
|
||||
++mAmbientMode;
|
||||
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0: std::cout << "Setting lights to normal\n"; break;
|
||||
case 1: std::cout << "Turning the lights up\n"; break;
|
||||
case 2: std::cout << "Turning the lights to full\n"; break;
|
||||
}
|
||||
|
||||
setAmbientMode();
|
||||
}
|
||||
|
||||
void ExteriorCellRender::enable (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
mScene.getMgr()->getSceneNode (handle)->setVisible (true);
|
||||
}
|
||||
|
||||
void ExteriorCellRender::disable (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
mScene.getMgr()->getSceneNode (handle)->setVisible (false);
|
||||
}
|
||||
|
||||
void ExteriorCellRender::deleteObject (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
{
|
||||
Ogre::SceneNode *node = mScene.getMgr()->getSceneNode (handle);
|
||||
node->removeAndDestroyAllChildren();
|
||||
mScene.getMgr()->destroySceneNode (node);
|
||||
}
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
#ifndef _GAME_RENDER_EXTERIOR_H
|
||||
#define _GAME_RENDER_EXTERIOR_H
|
||||
|
||||
#include "cell.hpp"
|
||||
#include "cellimp.hpp"
|
||||
#include "../mwworld/physicssystem.hpp"
|
||||
|
||||
#include "OgreColourValue.h"
|
||||
#include <OgreMath.h>
|
||||
#include <Ogre.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneNode;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class MWScene;
|
||||
|
||||
/**
|
||||
This class is responsible for inserting meshes and other
|
||||
rendering objects from the given cell into the given rendering
|
||||
scene.
|
||||
*/
|
||||
|
||||
class ExteriorCellRender : public CellRender, private CellRenderImp
|
||||
{
|
||||
|
||||
static bool lightConst;
|
||||
static float lightConstValue;
|
||||
|
||||
static bool lightLinear;
|
||||
static int lightLinearMethod;
|
||||
static float lightLinearValue;
|
||||
static float lightLinearRadiusMult;
|
||||
|
||||
static bool lightQuadratic;
|
||||
static int lightQuadraticMethod;
|
||||
static float lightQuadraticValue;
|
||||
static float lightQuadraticRadiusMult;
|
||||
|
||||
static bool lightOutQuadInLin;
|
||||
|
||||
ESMS::CellStore<MWWorld::RefData> &mCell;
|
||||
MWWorld::Environment &mEnvironment;
|
||||
MWScene &mScene;
|
||||
MWWorld::PhysicsSystem *mPhysics;
|
||||
|
||||
/// The scene node that contains all objects belonging to this
|
||||
/// cell.
|
||||
Ogre::SceneNode *mBase;
|
||||
|
||||
Ogre::SceneNode *mInsert;
|
||||
std::string mInsertMesh;
|
||||
Ogre::SceneNode *mNpcPart;
|
||||
|
||||
//the static geometry
|
||||
Ogre::StaticGeometry *sg;
|
||||
bool isStatic;
|
||||
|
||||
// 0 normal, 1 more bright, 2 max
|
||||
int mAmbientMode;
|
||||
|
||||
Ogre::ColourValue mAmbientColor;
|
||||
|
||||
/// start inserting a new reference.
|
||||
virtual void insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_ = false);
|
||||
|
||||
/// insert a mesh related to the most recent insertBegin call.
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements);
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
|
||||
|
||||
virtual void insertMesh(const std::string &mesh);
|
||||
|
||||
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
|
||||
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
|
||||
|
||||
virtual void insertObjectPhysics();
|
||||
|
||||
virtual void insertActorPhysics();
|
||||
|
||||
/// insert a light related to the most recent insertBegin call.
|
||||
virtual void insertLight(float r, float g, float b, float radius);
|
||||
|
||||
/// finish inserting a new reference and return a handle to it.
|
||||
virtual std::string insertEnd (bool Enable);
|
||||
|
||||
/// configure lighting according to cell
|
||||
void configureAmbient();
|
||||
|
||||
/// configure fog according to cell
|
||||
void configureFog();
|
||||
|
||||
void setAmbientMode();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ExteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, MWWorld::Environment& environment,
|
||||
MWScene &_scene, MWWorld::PhysicsSystem *physics);
|
||||
|
||||
virtual ~ExteriorCellRender() { destroy(); }
|
||||
|
||||
/// Make the cell visible. Load the cell if necessary.
|
||||
virtual void show();
|
||||
|
||||
/// Remove the cell from rendering, but don't remove it from
|
||||
/// memory.
|
||||
virtual void hide();
|
||||
|
||||
/// Destroy all rendering objects connected with this cell.
|
||||
virtual void destroy(); // comment by Zini: shouldn't this go into the destructor?
|
||||
|
||||
/// Switch through lighting modes.
|
||||
void toggleLight();
|
||||
|
||||
/// Make the reference with the given handle visible.
|
||||
virtual void enable (const std::string& handle);
|
||||
|
||||
/// Make the reference with the given handle invisible.
|
||||
virtual void disable (const std::string& handle);
|
||||
|
||||
/// Remove the reference with the given handle permanently from the scene.
|
||||
virtual void deleteObject (const std::string& handle);
|
||||
|
||||
void destroyAllAttachedMovableObjects(Ogre::SceneNode* i_pSceneNode);
|
||||
|
||||
static int uniqueID;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,409 +0,0 @@
|
||||
#include "interior.hpp"
|
||||
|
||||
#include <OgreEntity.h>
|
||||
#include <OgreLight.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreMath.h>
|
||||
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
#include "mwscene.hpp"
|
||||
#include <Ogre.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
using namespace ESMS;
|
||||
|
||||
bool InteriorCellRender::lightConst = false;
|
||||
float InteriorCellRender::lightConstValue = 0.0f;
|
||||
|
||||
bool InteriorCellRender::lightLinear = true;
|
||||
int InteriorCellRender::lightLinearMethod = 1;
|
||||
float InteriorCellRender::lightLinearValue = 3;
|
||||
float InteriorCellRender::lightLinearRadiusMult = 1;
|
||||
|
||||
bool InteriorCellRender::lightQuadratic = false;
|
||||
int InteriorCellRender::lightQuadraticMethod = 2;
|
||||
float InteriorCellRender::lightQuadraticValue = 16;
|
||||
float InteriorCellRender::lightQuadraticRadiusMult = 1;
|
||||
|
||||
bool InteriorCellRender::lightOutQuadInLin = false;
|
||||
|
||||
// start inserting a new reference.
|
||||
|
||||
void InteriorCellRender::insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_)
|
||||
{
|
||||
assert (!insert);
|
||||
|
||||
// Create and place scene node for this object
|
||||
insert = base->createChildSceneNode();
|
||||
|
||||
const float *f = refData.getPosition().pos;
|
||||
insert->setPosition(f[0], f[1], f[2]);
|
||||
insert->setScale(ref.scale, ref.scale, ref.scale);
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ref.pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
insert->setOrientation(xr*yr*zr);
|
||||
|
||||
mInsertMesh.clear();
|
||||
}
|
||||
|
||||
// insert a mesh related to the most recent insertBegin call.
|
||||
void InteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements)
|
||||
{
|
||||
assert(insert);
|
||||
Ogre::SceneNode *parent = insert;
|
||||
//std::cout << "ELEMENTS:" << elements;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneNodeName[i]));
|
||||
}
|
||||
parent->rotate(axis, angle);
|
||||
}
|
||||
// insert a mesh related to the most recent insertBegin call.
|
||||
|
||||
void InteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements)
|
||||
{
|
||||
assert(insert);
|
||||
Ogre::SceneNode *parent = insert;
|
||||
//std::cout << "ELEMENTS:" << elements;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneNodeName[i]));
|
||||
}
|
||||
parent->scale(axis);
|
||||
}
|
||||
void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements)
|
||||
{
|
||||
insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true);
|
||||
}
|
||||
void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){
|
||||
|
||||
assert (insert);
|
||||
//insert->
|
||||
Ogre::SceneNode *parent = insert;
|
||||
for (int i = 0; i < elements; i++){
|
||||
if(sceneParent[i] != "" && parent->getChild(sceneParent[i]))
|
||||
parent = dynamic_cast<Ogre::SceneNode*> (parent->getChild(sceneParent[i]));
|
||||
}
|
||||
|
||||
npcPart = parent->createChildSceneNode(sceneNodeName);
|
||||
//npcPart->showBoundingBox(true);
|
||||
|
||||
MeshPtr good2 = NifOgre::NIFLoader::load(mesh);
|
||||
|
||||
MovableObject *ent = scene.getMgr()->createEntity(mesh);
|
||||
//ent->extr
|
||||
|
||||
// MovableObject *ent2 = scene.getMgr()->createEntity(bounds
|
||||
// );
|
||||
//ent->
|
||||
//std::cout << mesh << bounds << "\n";
|
||||
|
||||
if(translateFirst){
|
||||
npcPart->translate(vec);
|
||||
npcPart->rotate(axis, angle);
|
||||
}
|
||||
else{
|
||||
|
||||
npcPart->rotate(axis, angle);
|
||||
npcPart->translate(vec);
|
||||
}
|
||||
|
||||
npcPart->attachObject(ent);
|
||||
Ogre::MeshManager *m = MeshManager::getSingletonPtr();
|
||||
const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif";
|
||||
|
||||
const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif";
|
||||
|
||||
const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif";
|
||||
const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif";
|
||||
const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif";
|
||||
const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif";
|
||||
if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGKHAJIITF\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail1);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot1);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGKHAJIITM\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail2);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot2);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGARGONIANF\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail3);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot3);
|
||||
good2->reload();
|
||||
}
|
||||
else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull())
|
||||
{
|
||||
//std::cout << "CLONINGARGONIANM\n";
|
||||
good2->reload();
|
||||
MeshPtr tail = good2->clone(beasttail4);
|
||||
good2->reload();
|
||||
MeshPtr foot = good2->clone(beastfoot4);
|
||||
good2->reload();
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorCellRender::insertMesh(const std::string &mesh)
|
||||
{
|
||||
assert (insert);
|
||||
|
||||
NifOgre::NIFLoader::load(mesh);
|
||||
MovableObject *ent = scene.getMgr()->createEntity(mesh);
|
||||
insert->attachObject(ent);
|
||||
|
||||
if (mInsertMesh.empty())
|
||||
mInsertMesh = mesh;
|
||||
}
|
||||
|
||||
void InteriorCellRender::insertObjectPhysics()
|
||||
{
|
||||
if (!mInsertMesh.empty())
|
||||
{
|
||||
mPhysics->addObject (insert->getName(), mInsertMesh, insert->getOrientation(),
|
||||
insert->getScale().x, insert->getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorCellRender::insertActorPhysics()
|
||||
{
|
||||
mPhysics->addActor (insert->getName(), mInsertMesh, insert->getPosition());
|
||||
}
|
||||
|
||||
// insert a light related to the most recent insertBegin call.
|
||||
void InteriorCellRender::insertLight(float r, float g, float b, float radius)
|
||||
{
|
||||
assert (insert);
|
||||
|
||||
Ogre::Light *light = scene.getMgr()->createLight();
|
||||
light->setDiffuseColour (r, g, b);
|
||||
|
||||
float cval=0.0f, lval=0.0f, qval=0.0f;
|
||||
|
||||
if(lightConst)
|
||||
cval = lightConstValue;
|
||||
if(!lightOutQuadInLin)
|
||||
{
|
||||
if(lightLinear)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
}
|
||||
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
|
||||
insert->attachObject(light);
|
||||
}
|
||||
|
||||
// finish inserting a new reference and return a handle to it.
|
||||
|
||||
std::string InteriorCellRender::insertEnd (bool enable)
|
||||
{
|
||||
assert (insert);
|
||||
|
||||
std::string handle = insert->getName();
|
||||
|
||||
if (!enable)
|
||||
insert->setVisible (false);
|
||||
|
||||
insert = 0;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// configure lighting according to cell
|
||||
|
||||
void InteriorCellRender::configureAmbient()
|
||||
{
|
||||
ambientColor.setAsABGR (cell.cell->ambi.ambient);
|
||||
setAmbientMode();
|
||||
|
||||
// Create a "sun" that shines light downwards. It doesn't look
|
||||
// completely right, but leave it for now.
|
||||
Ogre::Light *light = scene.getMgr()->createLight();
|
||||
Ogre::ColourValue colour;
|
||||
colour.setAsABGR (cell.cell->ambi.sunlight);
|
||||
light->setDiffuseColour (colour);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDirection(0,-1,0);
|
||||
}
|
||||
|
||||
// configure fog according to cell
|
||||
void InteriorCellRender::configureFog()
|
||||
{
|
||||
Ogre::ColourValue color;
|
||||
color.setAsABGR (cell.cell->ambi.fog);
|
||||
|
||||
float high = 4500 + 9000 * (1-cell.cell->ambi.fogDensity);
|
||||
float low = 200;
|
||||
|
||||
scene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high);
|
||||
scene.getCamera()->setFarClipDistance (high + 10);
|
||||
scene.getViewport()->setBackgroundColour (color);
|
||||
}
|
||||
|
||||
void InteriorCellRender::setAmbientMode()
|
||||
{
|
||||
switch (ambientMode)
|
||||
{
|
||||
case 0:
|
||||
|
||||
scene.getMgr()->setAmbientLight(ambientColor);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
scene.getMgr()->setAmbientLight(0.7f*ambientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
scene.getMgr()->setAmbientLight(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorCellRender::show()
|
||||
{
|
||||
base = scene.getRoot()->createChildSceneNode();
|
||||
|
||||
configureAmbient();
|
||||
configureFog();
|
||||
|
||||
insertCell(cell, mEnvironment);
|
||||
}
|
||||
|
||||
void InteriorCellRender::hide()
|
||||
{
|
||||
if(base)
|
||||
base->setVisible(false);
|
||||
}
|
||||
|
||||
void InteriorCellRender::destroy()
|
||||
{
|
||||
if(base)
|
||||
{
|
||||
base->removeAndDestroyAllChildren();
|
||||
scene.getMgr()->destroySceneNode(base);
|
||||
}
|
||||
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
// Switch through lighting modes.
|
||||
|
||||
void InteriorCellRender::toggleLight()
|
||||
{
|
||||
if (ambientMode==2)
|
||||
ambientMode = 0;
|
||||
else
|
||||
++ambientMode;
|
||||
|
||||
switch (ambientMode)
|
||||
{
|
||||
case 0: std::cout << "Setting lights to normal\n"; break;
|
||||
case 1: std::cout << "Turning the lights up\n"; break;
|
||||
case 2: std::cout << "Turning the lights to full\n"; break;
|
||||
}
|
||||
|
||||
setAmbientMode();
|
||||
}
|
||||
|
||||
void InteriorCellRender::enable (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
scene.getMgr()->getSceneNode (handle)->setVisible (true);
|
||||
}
|
||||
|
||||
void InteriorCellRender::disable (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
scene.getMgr()->getSceneNode (handle)->setVisible (false);
|
||||
}
|
||||
|
||||
void InteriorCellRender::deleteObject (const std::string& handle)
|
||||
{
|
||||
if (!handle.empty())
|
||||
{
|
||||
Ogre::SceneNode *node = scene.getMgr()->getSceneNode (handle);
|
||||
node->removeAndDestroyAllChildren();
|
||||
scene.getMgr()->destroySceneNode (node);
|
||||
}
|
||||
}
|
||||
|
||||
// Magic function from the internets. Might need this later.
|
||||
/*
|
||||
void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode )
|
||||
{
|
||||
if ( !i_pSceneNode )
|
||||
{
|
||||
ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy all the attached objects
|
||||
SceneNode::ObjectIterator itObject = i_pSceneNode->getAttachedObjectIterator();
|
||||
|
||||
while ( itObject.hasMoreElements() )
|
||||
{
|
||||
MovableObject* pObject = static_cast<MovableObject*>(itObject.getNext());
|
||||
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
||||
}
|
||||
|
||||
// Recurse to child SceneNodes
|
||||
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
||||
|
||||
while ( itChild.hasMoreElements() )
|
||||
{
|
||||
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
||||
DestroyAllAttachedMovableObjects( pChildNode );
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,131 +0,0 @@
|
||||
#ifndef _GAME_RENDER_INTERIOR_H
|
||||
#define _GAME_RENDER_INTERIOR_H
|
||||
|
||||
#include "cell.hpp"
|
||||
#include "cellimp.hpp"
|
||||
#include "../mwworld/physicssystem.hpp"
|
||||
|
||||
#include "OgreColourValue.h"
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneNode;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class MWScene;
|
||||
|
||||
/**
|
||||
This class is responsible for inserting meshes and other
|
||||
rendering objects from the given cell into the given rendering
|
||||
scene.
|
||||
*/
|
||||
|
||||
class InteriorCellRender : public CellRender, private CellRenderImp
|
||||
{
|
||||
//static bool isChest;
|
||||
static bool lightConst;
|
||||
static float lightConstValue;
|
||||
|
||||
static bool lightLinear;
|
||||
static int lightLinearMethod;
|
||||
static float lightLinearValue;
|
||||
static float lightLinearRadiusMult;
|
||||
|
||||
static bool lightQuadratic;
|
||||
static int lightQuadraticMethod;
|
||||
static float lightQuadraticValue;
|
||||
static float lightQuadraticRadiusMult;
|
||||
|
||||
static bool lightOutQuadInLin;
|
||||
|
||||
ESMS::CellStore<MWWorld::RefData> &cell;
|
||||
MWWorld::Environment &mEnvironment;
|
||||
MWScene &scene;
|
||||
MWWorld::PhysicsSystem *mPhysics;
|
||||
|
||||
/// The scene node that contains all objects belonging to this
|
||||
/// cell.
|
||||
Ogre::SceneNode *base;
|
||||
|
||||
Ogre::SceneNode *insert;
|
||||
std::string mInsertMesh;
|
||||
Ogre::SceneNode *npcPart;
|
||||
|
||||
// 0 normal, 1 more bright, 2 max
|
||||
int ambientMode;
|
||||
|
||||
Ogre::ColourValue ambientColor;
|
||||
|
||||
/// start inserting a new reference.
|
||||
virtual void insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_ = false);
|
||||
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
|
||||
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
|
||||
/// insert a mesh related to the most recent insertBegin call.
|
||||
virtual void insertMesh(const std::string &mesh);
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements);
|
||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
|
||||
|
||||
virtual void insertObjectPhysics();
|
||||
|
||||
virtual void insertActorPhysics();
|
||||
|
||||
/// insert a light related to the most recent insertBegin call.
|
||||
virtual void insertLight(float r, float g, float b, float radius);
|
||||
|
||||
/// finish inserting a new reference and return a handle to it.
|
||||
virtual std::string insertEnd (bool Enable);
|
||||
|
||||
/// configure lighting according to cell
|
||||
void configureAmbient();
|
||||
|
||||
/// configure fog according to cell
|
||||
void configureFog();
|
||||
|
||||
void setAmbientMode();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
InteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, MWWorld::Environment& environment,
|
||||
MWScene &_scene, MWWorld::PhysicsSystem *physics)
|
||||
: cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0)
|
||||
{
|
||||
mPhysics = physics;
|
||||
}
|
||||
|
||||
virtual ~InteriorCellRender() { destroy(); }
|
||||
|
||||
/// Make the cell visible. Load the cell if necessary.
|
||||
//virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
|
||||
virtual void show();
|
||||
|
||||
/// Remove the cell from rendering, but don't remove it from
|
||||
/// memory.
|
||||
virtual void hide();
|
||||
|
||||
/// Destroy all rendering objects connected with this cell.
|
||||
virtual void destroy(); // comment by Zini: shouldn't this go into the destructor?
|
||||
|
||||
/// Switch through lighting modes.
|
||||
void toggleLight();
|
||||
|
||||
/// Make the reference with the given handle visible.
|
||||
virtual void enable (const std::string& handle);
|
||||
|
||||
/// Make the reference with the given handle invisible.
|
||||
virtual void disable (const std::string& handle);
|
||||
|
||||
/// Remove the reference with the given handle permanently from the scene.
|
||||
virtual void deleteObject (const std::string& handle);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,89 +0,0 @@
|
||||
#include "mwscene.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "OgreRoot.h"
|
||||
#include "OgreRenderWindow.h"
|
||||
#include "OgreSceneManager.h"
|
||||
#include "OgreViewport.h"
|
||||
#include "OgreCamera.h"
|
||||
#include "OgreTextureManager.h"
|
||||
|
||||
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <components/esm/loadstat.hpp>
|
||||
|
||||
#include "player.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
||||
MWScene::MWScene(OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng)
|
||||
: rend(_rend)
|
||||
{
|
||||
eng = physEng;
|
||||
rend.createScene("PlayerCam", 55, 5);
|
||||
|
||||
// Set default mipmap level (NB some APIs ignore this)
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(5);
|
||||
|
||||
// Load resources
|
||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
||||
|
||||
// Turn the entire scene (represented by the 'root' node) -90
|
||||
// degrees around the x axis. This makes Z go upwards, and Y go into
|
||||
// the screen (when x is to the right.) This is the orientation that
|
||||
// Morrowind uses, and it automagically makes everything work as it
|
||||
// should.
|
||||
SceneNode *rt = rend.getScene()->getRootSceneNode();
|
||||
mwRoot = rt->createChildSceneNode();
|
||||
mwRoot->pitch(Degree(-90));
|
||||
|
||||
//used to obtain ingame information of ogre objects (which are faced or selected)
|
||||
mRaySceneQuery = rend.getScene()->createRayQuery(Ray());
|
||||
|
||||
Ogre::SceneNode *playerNode = mwRoot->createChildSceneNode ("player");
|
||||
playerNode->pitch(Degree(90));
|
||||
Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode();
|
||||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||
cameraPitchNode->attachObject(getCamera());
|
||||
|
||||
|
||||
mPlayer = new MWRender::Player (getCamera(), playerNode->getName());
|
||||
}
|
||||
|
||||
MWScene::~MWScene()
|
||||
{
|
||||
delete mPlayer;
|
||||
}
|
||||
|
||||
std::pair<std::string, float> MWScene::getFacedHandle (MWWorld::World& world)
|
||||
{
|
||||
std::string handle = "";
|
||||
|
||||
//get a ray pointing to the center of the viewport
|
||||
Ray centerRay = getCamera()->getCameraToViewportRay(
|
||||
getViewport()->getWidth()/2,
|
||||
getViewport()->getHeight()/2);
|
||||
//let's avoid the capsule shape of the player.
|
||||
centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection());
|
||||
btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y);
|
||||
btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y);
|
||||
|
||||
return eng->rayTest(from,to);
|
||||
}
|
||||
|
||||
bool MWScene::toggleRenderMode (int mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case MWWorld::World::Render_CollisionDebug:
|
||||
|
||||
// TODO use a proper function instead of accessing the member variable
|
||||
// directly.
|
||||
eng->setDebugRenderingMode (!eng->isDebugCreated);
|
||||
return eng->isDebugCreated;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
#ifndef _GAME_RENDER_MWSCENE_H
|
||||
#define _GAME_RENDER_MWSCENE_H
|
||||
|
||||
#include <utility>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Camera;
|
||||
class Viewport;
|
||||
class SceneManager;
|
||||
class SceneNode;
|
||||
class RaySceneQuery;
|
||||
class Quaternion;
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class Player;
|
||||
|
||||
/// \brief 3D-scene (rendering and physics)
|
||||
|
||||
class MWScene
|
||||
{
|
||||
OEngine::Render::OgreRenderer &rend;
|
||||
|
||||
/// Root node for all objects added to the scene. This is rotated so
|
||||
/// that the OGRE coordinate system matches that used internally in
|
||||
/// Morrowind.
|
||||
Ogre::SceneNode *mwRoot;
|
||||
Ogre::RaySceneQuery *mRaySceneQuery;
|
||||
|
||||
OEngine::Physic::PhysicEngine* eng;
|
||||
|
||||
MWRender::Player *mPlayer;
|
||||
|
||||
public:
|
||||
|
||||
MWScene (OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng);
|
||||
|
||||
~MWScene();
|
||||
|
||||
Ogre::Camera *getCamera() { return rend.getCamera(); }
|
||||
Ogre::SceneNode *getRoot() { return mwRoot; }
|
||||
Ogre::SceneManager *getMgr() { return rend.getScene(); }
|
||||
Ogre::Viewport *getViewport() { return rend.getViewport(); }
|
||||
Ogre::RaySceneQuery *getRaySceneQuery() { return mRaySceneQuery; }
|
||||
MWRender::Player *getPlayer() { return mPlayer; }
|
||||
|
||||
/// Gets the handle of the object the player is looking at
|
||||
/// pair<name, distance>
|
||||
/// name is empty and distance = -1 if there is no object which
|
||||
/// can be faced
|
||||
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||
|
||||
/// Toggle render mode
|
||||
/// \todo Using an int instead of a enum here to avoid cyclic includes. Will be fixed
|
||||
/// when the mw*-refactoring is done.
|
||||
/// \return Resulting mode
|
||||
bool toggleRenderMode (int mode);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,308 @@
|
||||
#include "npcanimation.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace NifOgre;
|
||||
namespace MWRender{
|
||||
NpcAnimation::~NpcAnimation(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::NPC>();
|
||||
|
||||
//Part selection on last character of the file string
|
||||
// " Tri Chest
|
||||
// * Tri Tail
|
||||
// : Tri Left Foot
|
||||
// < Tri Right Foot
|
||||
// > Tri Left Hand
|
||||
// ? Tri Right Hand
|
||||
// | Normal
|
||||
|
||||
//Mirroring Parts on second to last character
|
||||
//suffix == '*'
|
||||
// vector = Ogre::Vector3(-1,1,1);
|
||||
// suffix == '?'
|
||||
// vector = Ogre::Vector3(1,-1,1);
|
||||
// suffix == '<'
|
||||
// vector = Ogre::Vector3(1,1,-1);
|
||||
|
||||
|
||||
std::string hairID = ref->base->hair;
|
||||
std::string headID = ref->base->head;
|
||||
std::string npcName = ref->base->name;
|
||||
//ESMStore::Races r =
|
||||
const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race);
|
||||
|
||||
|
||||
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||
char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2);
|
||||
bool female = tolower(secondtolast) == 'f';
|
||||
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||
/*std::cout << "Race: " << ref->base->race ;
|
||||
if(female){
|
||||
std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n";
|
||||
}
|
||||
else{
|
||||
std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n";
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
std::string smodel = "meshes\\base_anim.nif";
|
||||
if(beast)
|
||||
smodel = "meshes\\base_animkna.nif";
|
||||
|
||||
insert = ptr.getRefData().getBaseNode();
|
||||
assert(insert);
|
||||
|
||||
NifOgre::NIFLoader::load(smodel);
|
||||
|
||||
base = mRend.getScene()->createEntity(smodel);
|
||||
base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones
|
||||
//stay in the same place when we skipanim, or open a gui window
|
||||
|
||||
|
||||
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){
|
||||
|
||||
for(unsigned int init = 0; init < transformations->size(); init++){
|
||||
rindexI.push_back(0);
|
||||
tindexI.push_back(0);
|
||||
}
|
||||
|
||||
stopTime = transformations->begin()->getStopTime();
|
||||
startTime = transformations->begin()->getStartTime();
|
||||
}
|
||||
textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel);
|
||||
insert->attachObject(base);
|
||||
|
||||
if(female)
|
||||
insert->scale(race->data.height.female, race->data.height.female, race->data.height.female);
|
||||
else
|
||||
insert->scale(race->data.height.male, race->data.height.male, race->data.height.male);
|
||||
std::string headModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(headID)->model;
|
||||
|
||||
std::string hairModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model;
|
||||
const ESM::BodyPart *chest = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
|
||||
const ESM::BodyPart *upperleg = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||
const ESM::BodyPart *groin = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
||||
const ESM::BodyPart *arml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); //We need two
|
||||
const ESM::BodyPart *neck = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck");
|
||||
const ESM::BodyPart *knee = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
|
||||
const ESM::BodyPart *ankle = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
|
||||
const ESM::BodyPart *foot = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
|
||||
const ESM::BodyPart *feet = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
|
||||
const ESM::BodyPart *tail = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail");
|
||||
const ESM::BodyPart *wristl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); //We need two
|
||||
const ESM::BodyPart *forearml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); //We need two
|
||||
const ESM::BodyPart *handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand"); //We need two
|
||||
const ESM::BodyPart *hair = mEnvironment.mWorld->getStore().bodyParts.search(hairID);
|
||||
const ESM::BodyPart *head = mEnvironment.mWorld->getStore().bodyParts.search(headID);
|
||||
if(bodyRaceID == "b_n_argonian_f_")
|
||||
forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two
|
||||
if(!handl)
|
||||
handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands");
|
||||
//const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle");
|
||||
//const ESM::BodyPart* clavicler = claviclel;
|
||||
const ESM::BodyPart* handr = handl;
|
||||
const ESM::BodyPart* forearmr = forearml;
|
||||
const ESM::BodyPart* wristr = wristl;
|
||||
const ESM::BodyPart* armr = arml;
|
||||
|
||||
|
||||
if(upperleg){
|
||||
insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg");
|
||||
insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg");
|
||||
|
||||
}
|
||||
if(foot){
|
||||
if(bodyRaceID.compare("b_n_khajiit_m_") == 0)
|
||||
{
|
||||
feet = foot;
|
||||
}
|
||||
else
|
||||
{
|
||||
insertBoundedPart("meshes\\" + foot->model, "Right Foot");
|
||||
insertBoundedPart("meshes\\" + foot->model + "*|", "Left Foot");
|
||||
}
|
||||
}
|
||||
if(groin){
|
||||
insertBoundedPart("meshes\\" + groin->model, "Groin");
|
||||
}
|
||||
if(knee)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e
|
||||
insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e
|
||||
|
||||
}
|
||||
if(ankle){
|
||||
|
||||
insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank);
|
||||
insertBoundedPart("meshes\\" + ankle->model, "Right Ankle");
|
||||
}
|
||||
if (armr){
|
||||
insertBoundedPart("meshes\\" + armr->model, "Right Upper Arm");
|
||||
}
|
||||
if(arml){
|
||||
insertBoundedPart("meshes\\" + arml->model + "*|", "Left Upper Arm");
|
||||
}
|
||||
|
||||
if (forearmr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + forearmr->model, "Right Forearm");
|
||||
}
|
||||
if(forearml)
|
||||
insertBoundedPart("meshes\\" + forearml->model + "*|", "Left Forearm");
|
||||
|
||||
if (wristr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + wristr->model, "Right Wrist");
|
||||
}
|
||||
|
||||
if(wristl)
|
||||
insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*if(claviclel)
|
||||
insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base);
|
||||
if(clavicler)
|
||||
insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/
|
||||
|
||||
|
||||
if(neck)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + neck->model, "Neck");
|
||||
}
|
||||
if(head)
|
||||
insertBoundedPart("meshes\\" + head->model, "Head");
|
||||
if(hair)
|
||||
insertBoundedPart("meshes\\" + hair->model, "Head");
|
||||
|
||||
if (chest){
|
||||
insertFreePart("meshes\\" + chest->model, ">\"", insert);
|
||||
|
||||
|
||||
}
|
||||
if (handr){
|
||||
insertFreePart("meshes\\" + handr->model , ">?", insert);
|
||||
|
||||
}
|
||||
if (handl){
|
||||
insertFreePart("meshes\\" + handl->model, ">>", insert);
|
||||
|
||||
}
|
||||
if(tail){
|
||||
insertFreePart("meshes\\" + tail->model, ">*", insert);
|
||||
}
|
||||
if(feet){
|
||||
std::string num = getUniqueID(feet->model);
|
||||
insertFreePart("meshes\\" + feet->model,"><", insert);
|
||||
insertFreePart("meshes\\" + feet->model,">:", insert);
|
||||
}
|
||||
//originalpos = insert->_getWorldAABB().getCenter();
|
||||
//originalscenenode = insert->getPosition();
|
||||
}
|
||||
|
||||
Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){
|
||||
NIFLoader::load(mesh);
|
||||
Entity* ent = mRend.getScene()->createEntity(mesh);
|
||||
|
||||
base->attachObjectToBone(bonename, ent);
|
||||
return ent;
|
||||
}
|
||||
void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){
|
||||
std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix;
|
||||
NIFLoader::load(meshNumbered);
|
||||
|
||||
Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered);
|
||||
|
||||
/*MaterialPtr material = ent->getSubEntity(0)->getMaterial();
|
||||
material->removeAllTechniques();
|
||||
|
||||
Ogre::Technique* tech = material->createTechnique();
|
||||
|
||||
Pass* pass2 = tech->createPass();
|
||||
pass2->setVertexProgram("Ogre/HardwareSkinningTwoWeights");
|
||||
pass2->setColourWriteEnabled(false);
|
||||
//tech->setSchemeName("blahblah");*/
|
||||
|
||||
|
||||
insert->attachObject(ent);
|
||||
entityparts.push_back(ent);
|
||||
shapes = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix));
|
||||
if(shapes){
|
||||
shapeparts.push_back(shapes);
|
||||
handleShapes(shapes, ent, base->getSkeleton());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void NpcAnimation::runAnimation(float timepassed){
|
||||
//1. Add the amount of time passed to time
|
||||
|
||||
//2. Handle the animation transforms dependent on time
|
||||
|
||||
//3. Handle the shapes dependent on animation transforms
|
||||
if(animate > 0){
|
||||
time += timepassed;
|
||||
|
||||
if(time > stopTime){
|
||||
animate--;
|
||||
|
||||
if(animate == 0)
|
||||
time = stopTime;
|
||||
else
|
||||
time = startTime + (time - stopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
Ogre::Vector3 current = insert->_getWorldAABB().getCenter();
|
||||
|
||||
//This is the attempt at npc physics
|
||||
//mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), current);
|
||||
|
||||
|
||||
|
||||
/*if(base->hasSkeleton())
|
||||
{
|
||||
|
||||
Ogre::Quaternion boneQuat = rotate;
|
||||
Ogre::Vector3 boneTrans = trans;
|
||||
mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), boneTrans + insert->getPosition());
|
||||
//mEnvironment.mWorld->setObjectPhysicsRotation(insert->getName(), boneQuat * insert->getOrientation());
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin();
|
||||
std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin();
|
||||
while(shapepartsiter != shapeparts.end())
|
||||
{
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter;
|
||||
Ogre::Entity* theentity = *entitypartsiter;
|
||||
/*
|
||||
Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0);
|
||||
if (pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded())
|
||||
std::cout << "It's hardware\n";
|
||||
else
|
||||
std::cout << "It's software\n";*/
|
||||
|
||||
handleShapes(shapes, theentity, theentity->getSkeleton());
|
||||
shapepartsiter++;
|
||||
entitypartsiter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#ifndef _GAME_RENDER_NPCANIMATION_H
|
||||
#define _GAME_RENDER_NPCANIMATION_H
|
||||
#include "animation.hpp"
|
||||
#include <components/nif/data.hpp>
|
||||
#include <components/nif/node.hpp>
|
||||
#include <components/nif/property.hpp>
|
||||
#include <components/nif/controller.hpp>
|
||||
#include <components/nif/extra.hpp>
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class NpcAnimation: public Animation{
|
||||
|
||||
|
||||
|
||||
public:
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||
~NpcAnimation();
|
||||
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
|
||||
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
|
||||
virtual void runAnimation(float timepassed);
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,185 @@
|
||||
#include "objects.hpp"
|
||||
#include <OgreSceneNode.h>
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
|
||||
bool Objects::lightConst = false;
|
||||
float Objects::lightConstValue = 0.0f;
|
||||
|
||||
bool Objects::lightLinear = true;
|
||||
int Objects::lightLinearMethod = 1;
|
||||
float Objects::lightLinearValue = 3;
|
||||
float Objects::lightLinearRadiusMult = 1;
|
||||
|
||||
bool Objects::lightQuadratic = false;
|
||||
int Objects::lightQuadraticMethod = 2;
|
||||
float Objects::lightQuadraticValue = 16;
|
||||
float Objects::lightQuadraticRadiusMult = 1;
|
||||
|
||||
bool Objects::lightOutQuadInLin = false;
|
||||
|
||||
int Objects::uniqueID = 0;
|
||||
|
||||
void Objects::setMwRoot(Ogre::SceneNode* root){
|
||||
mMwRoot = root;
|
||||
}
|
||||
void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
|
||||
Ogre::SceneNode* root = mMwRoot;
|
||||
Ogre::SceneNode* cellnode;
|
||||
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end())
|
||||
{
|
||||
//Create the scenenode and put it in the map
|
||||
cellnode = root->createChildSceneNode();
|
||||
mCellSceneNodes[ptr.getCell()] = cellnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellnode = mCellSceneNodes[ptr.getCell()];
|
||||
}
|
||||
|
||||
Ogre::SceneNode* insert = cellnode->createChildSceneNode();
|
||||
const float *f = ptr.getRefData().getPosition().pos;
|
||||
insert->setPosition(f[0], f[1], f[2]);
|
||||
insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale);
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ptr.getCellRef().pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
insert->setOrientation(xr*yr*zr);
|
||||
if (!enabled)
|
||||
insert->setVisible (false);
|
||||
ptr.getRefData().setBaseNode(insert);
|
||||
isStatic = static_;
|
||||
|
||||
|
||||
}
|
||||
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){
|
||||
Ogre::SceneNode* insert = ptr.getRefData().getBaseNode();
|
||||
assert(insert);
|
||||
|
||||
NifOgre::NIFLoader::load(mesh);
|
||||
Entity *ent = mRend.getScene()->createEntity(mesh);
|
||||
|
||||
if(!isStatic)
|
||||
{
|
||||
insert->attachObject(ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::StaticGeometry* sg = 0;
|
||||
if(mSG.find(ptr.getCell()) == mSG.end())
|
||||
{
|
||||
uniqueID = uniqueID +1;
|
||||
sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||
//Create the scenenode and put it in the map
|
||||
mSG[ptr.getCell()] = sg;
|
||||
}
|
||||
else
|
||||
{
|
||||
sg = mSG[ptr.getCell()];
|
||||
}
|
||||
|
||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||
sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000));
|
||||
|
||||
|
||||
mRend.getScene()->destroyEntity(ent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){
|
||||
Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle());
|
||||
assert(insert);
|
||||
Ogre::Light *light = mRend.getScene()->createLight();
|
||||
light->setDiffuseColour (r, g, b);
|
||||
|
||||
float cval=0.0f, lval=0.0f, qval=0.0f;
|
||||
|
||||
if(lightConst)
|
||||
cval = lightConstValue;
|
||||
if(!lightOutQuadInLin)
|
||||
{
|
||||
if(lightLinear)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
}
|
||||
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
|
||||
insert->attachObject(light);
|
||||
}
|
||||
|
||||
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode())
|
||||
{
|
||||
Ogre::SceneNode *parent = base->getParentSceneNode();
|
||||
|
||||
for (std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::const_iterator iter (
|
||||
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
|
||||
if (iter->second==parent)
|
||||
{
|
||||
base->removeAndDestroyAllChildren();
|
||||
mRend.getScene()->destroySceneNode (base);
|
||||
ptr.getRefData().setBaseNode (0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Objects::removeCell(MWWorld::Ptr::CellStore* store){
|
||||
if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
|
||||
{
|
||||
Ogre::SceneNode* base = mCellSceneNodes[store];
|
||||
base->removeAndDestroyAllChildren();
|
||||
mCellSceneNodes.erase(store);
|
||||
mRend.getScene()->destroySceneNode(base);
|
||||
base = 0;
|
||||
}
|
||||
|
||||
|
||||
if(mSG.find(store) != mSG.end())
|
||||
{
|
||||
Ogre::StaticGeometry* sg = mSG[store];
|
||||
mSG.erase(store);
|
||||
mRend.getScene()->destroyStaticGeometry (sg);
|
||||
sg = 0;
|
||||
}
|
||||
}
|
||||
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell){
|
||||
if(mSG.find(&cell) != mSG.end())
|
||||
{
|
||||
Ogre::StaticGeometry* sg = mSG[&cell];
|
||||
sg->build();
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
#ifndef _GAME_RENDER_OBJECTS_H
|
||||
#define _GAME_RENDER_OBJECTS_H
|
||||
|
||||
#include "components/esm_store/cell_store.hpp"
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class Objects{
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mSG;
|
||||
Ogre::SceneNode* mMwRoot;
|
||||
bool isStatic;
|
||||
static int uniqueID;
|
||||
static bool lightConst;
|
||||
static float lightConstValue;
|
||||
|
||||
static bool lightLinear;
|
||||
static int lightLinearMethod;
|
||||
static float lightLinearValue;
|
||||
static float lightLinearRadiusMult;
|
||||
|
||||
static bool lightQuadratic;
|
||||
static int lightQuadraticMethod;
|
||||
static float lightQuadraticValue;
|
||||
static float lightQuadraticRadiusMult;
|
||||
|
||||
static bool lightOutQuadInLin;
|
||||
public:
|
||||
Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){}
|
||||
~Objects(){}
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius);
|
||||
|
||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||
///< \return found?
|
||||
|
||||
void removeCell(MWWorld::Ptr::CellStore* store);
|
||||
void buildStaticGeometry(ESMS::CellStore<MWWorld::RefData> &cell);
|
||||
void setMwRoot(Ogre::SceneNode* root);
|
||||
};
|
||||
}
|
||||
#endif
|
@ -1,52 +0,0 @@
|
||||
#include "rendering_manager.hpp"
|
||||
|
||||
namespace MWRender {
|
||||
|
||||
RenderingManager::RenderingManager (SkyManager *skyManager) :
|
||||
mSkyManager(skyManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RenderingManager::~RenderingManager ()
|
||||
{
|
||||
delete mSkyManager;
|
||||
}
|
||||
|
||||
void RenderingManager::skyEnable ()
|
||||
{
|
||||
mSkyManager->enable();
|
||||
}
|
||||
|
||||
void RenderingManager::skyDisable ()
|
||||
{
|
||||
mSkyManager->disable();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetHour (double hour)
|
||||
{
|
||||
mSkyManager->setHour(hour);
|
||||
}
|
||||
|
||||
|
||||
void RenderingManager::skySetDate (int day, int month)
|
||||
{
|
||||
mSkyManager->setDate(day, month);
|
||||
}
|
||||
|
||||
int RenderingManager::skyGetMasserPhase() const
|
||||
{
|
||||
return mSkyManager->getMasserPhase();
|
||||
}
|
||||
|
||||
int RenderingManager::skyGetSecundaPhase() const
|
||||
{
|
||||
return mSkyManager->getSecundaPhase();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetMoonColour (bool red)
|
||||
{
|
||||
mSkyManager->setMoonColour(red);
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
#ifndef _GAME_RENDERING_MANAGER_H
|
||||
#define _GAME_RENDERING_MANAGER_H
|
||||
|
||||
|
||||
#include "sky.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
class RenderingManager {
|
||||
public:
|
||||
RenderingManager(SkyManager *skyManager);
|
||||
~RenderingManager();
|
||||
|
||||
void removeCell (MWWorld::Ptr::CellStore *store); // TODO do we want this?
|
||||
|
||||
void addObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store);
|
||||
void removeObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store);
|
||||
|
||||
void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position);
|
||||
void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale);
|
||||
void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation);
|
||||
void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store);
|
||||
|
||||
void setPhysicsDebugRendering (bool);
|
||||
bool getPhysicsDebugRendering() const;
|
||||
|
||||
void update (float duration);
|
||||
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
void skySetHour (double hour);
|
||||
void skySetDate (int day, int month);
|
||||
int skyGetMasserPhase() const;
|
||||
int skyGetSecundaPhase() const;
|
||||
void skySetMoonColour (bool red);
|
||||
|
||||
private:
|
||||
|
||||
SkyManager* mSkyManager;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,16 @@
|
||||
#ifndef _GAME_RENDERING_INTERFACE_H
|
||||
#define _GAME_RENDERING_INTERFACE_H
|
||||
namespace MWRender{
|
||||
class Objects;
|
||||
class Actors;
|
||||
class Player;
|
||||
|
||||
class RenderingInterface{
|
||||
public:
|
||||
virtual MWRender::Objects& getObjects() = 0;
|
||||
virtual MWRender::Player& getPlayer() = 0;
|
||||
virtual MWRender::Actors& getActors() = 0;
|
||||
virtual ~RenderingInterface(){};
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,248 @@
|
||||
#include "renderingmanager.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "OgreRoot.h"
|
||||
#include "OgreRenderWindow.h"
|
||||
#include "OgreSceneManager.h"
|
||||
#include "OgreViewport.h"
|
||||
#include "OgreCamera.h"
|
||||
#include "OgreTextureManager.h"
|
||||
|
||||
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <components/esm/loadstat.hpp>
|
||||
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
||||
namespace MWRender {
|
||||
|
||||
|
||||
|
||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mDebugging(engine)
|
||||
{
|
||||
mRendering.createScene("PlayerCam", 55, 5);
|
||||
mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), resDir);
|
||||
|
||||
// Set default mipmap level (NB some APIs ignore this)
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(5);
|
||||
|
||||
// Load resources
|
||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
||||
|
||||
// Turn the entire scene (represented by the 'root' node) -90
|
||||
// degrees around the x axis. This makes Z go upwards, and Y go into
|
||||
// the screen (when x is to the right.) This is the orientation that
|
||||
// Morrowind uses, and it automagically makes everything work as it
|
||||
// should.
|
||||
SceneNode *rt = mRendering.getScene()->getRootSceneNode();
|
||||
mMwRoot = rt->createChildSceneNode();
|
||||
mMwRoot->pitch(Degree(-90));
|
||||
mObjects.setMwRoot(mMwRoot);
|
||||
mActors.setMwRoot(mMwRoot);
|
||||
|
||||
//used to obtain ingame information of ogre objects (which are faced or selected)
|
||||
mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray());
|
||||
|
||||
Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player");
|
||||
playerNode->pitch(Degree(90));
|
||||
Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode();
|
||||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||
|
||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||
}
|
||||
|
||||
RenderingManager::~RenderingManager ()
|
||||
{
|
||||
delete mPlayer;
|
||||
delete mSkyManager;
|
||||
}
|
||||
|
||||
|
||||
MWRender::Objects& RenderingManager::getObjects(){
|
||||
return mObjects;
|
||||
}
|
||||
MWRender::Actors& RenderingManager::getActors(){
|
||||
return mActors;
|
||||
}
|
||||
|
||||
MWRender::Player& RenderingManager::getPlayer(){
|
||||
return (*mPlayer);
|
||||
}
|
||||
|
||||
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){
|
||||
mObjects.removeCell(store);
|
||||
mActors.removeCell(store);
|
||||
}
|
||||
|
||||
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
|
||||
{
|
||||
mObjects.buildStaticGeometry (*store);
|
||||
}
|
||||
|
||||
void RenderingManager::addObject (const MWWorld::Ptr& ptr){
|
||||
const MWWorld::Class& class_ =
|
||||
MWWorld::Class::get (ptr);
|
||||
class_.insertObjectRendering(ptr, *this);
|
||||
|
||||
}
|
||||
void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (!mObjects.deleteObject (ptr))
|
||||
{
|
||||
/// \todo delete non-object MW-references
|
||||
}
|
||||
if (!mActors.deleteObject (ptr))
|
||||
{
|
||||
/// \todo delete non-object MW-references
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position)
|
||||
{
|
||||
/// \todo move this to the rendering-subsystems
|
||||
mRendering.getScene()->getSceneNode (ptr.getRefData().getHandle())->
|
||||
setPosition (position);
|
||||
}
|
||||
|
||||
void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale){
|
||||
|
||||
}
|
||||
void RenderingManager::rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation){
|
||||
|
||||
}
|
||||
void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store){
|
||||
|
||||
}
|
||||
|
||||
void RenderingManager::update (float duration){
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RenderingManager::skyEnable ()
|
||||
{
|
||||
mSkyManager->enable();
|
||||
}
|
||||
|
||||
void RenderingManager::skyDisable ()
|
||||
{
|
||||
mSkyManager->disable();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetHour (double hour)
|
||||
{
|
||||
mSkyManager->setHour(hour);
|
||||
}
|
||||
|
||||
|
||||
void RenderingManager::skySetDate (int day, int month)
|
||||
{
|
||||
mSkyManager->setDate(day, month);
|
||||
}
|
||||
|
||||
int RenderingManager::skyGetMasserPhase() const
|
||||
{
|
||||
return mSkyManager->getMasserPhase();
|
||||
}
|
||||
|
||||
int RenderingManager::skyGetSecundaPhase() const
|
||||
{
|
||||
return mSkyManager->getSecundaPhase();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetMoonColour (bool red)
|
||||
{
|
||||
mSkyManager->setMoonColour(red);
|
||||
}
|
||||
bool RenderingManager::toggleRenderMode(int mode){
|
||||
return mDebugging.toggleRenderMode(mode);
|
||||
}
|
||||
|
||||
void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
|
||||
{
|
||||
Ogre::ColourValue color;
|
||||
color.setAsABGR (mCell.cell->ambi.fog);
|
||||
|
||||
float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity);
|
||||
float low = 200;
|
||||
|
||||
mRendering.getScene()->setFog (FOG_LINEAR, color, 0, low, high);
|
||||
mRendering.getCamera()->setFarClipDistance (high + 10);
|
||||
mRendering.getViewport()->setBackgroundColour (color);
|
||||
}
|
||||
|
||||
void RenderingManager::setAmbientMode()
|
||||
{
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0:
|
||||
|
||||
mRendering.getScene()->setAmbientLight(mAmbientColor);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
mRendering.getScene()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
mRendering.getScene()->setAmbientLight(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell)
|
||||
{
|
||||
mAmbientColor.setAsABGR (mCell.cell->ambi.ambient);
|
||||
setAmbientMode();
|
||||
|
||||
// Create a "sun" that shines light downwards. It doesn't look
|
||||
// completely right, but leave it for now.
|
||||
Ogre::Light *light = mRendering.getScene()->createLight();
|
||||
Ogre::ColourValue colour;
|
||||
colour.setAsABGR (mCell.cell->ambi.sunlight);
|
||||
light->setDiffuseColour (colour);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDirection(0,-1,0);
|
||||
}
|
||||
// Switch through lighting modes.
|
||||
|
||||
void RenderingManager::toggleLight()
|
||||
{
|
||||
if (mAmbientMode==2)
|
||||
mAmbientMode = 0;
|
||||
else
|
||||
++mAmbientMode;
|
||||
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0: std::cout << "Setting lights to normal\n"; break;
|
||||
case 1: std::cout << "Turning the lights up\n"; break;
|
||||
case 2: std::cout << "Turning the lights to full\n"; break;
|
||||
}
|
||||
|
||||
setAmbientMode();
|
||||
}
|
||||
|
||||
void RenderingManager::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName,
|
||||
int mode, int number)
|
||||
{
|
||||
mActors.playAnimationGroup(ptr, groupName, mode, number);
|
||||
}
|
||||
|
||||
void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mActors.skipAnimation(ptr);
|
||||
}
|
||||
void RenderingManager::addTime(){
|
||||
mActors.addTime();
|
||||
//Notify each animation that time has passed
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
#ifndef _GAME_RENDERING_MANAGER_H
|
||||
#define _GAME_RENDERING_MANAGER_H
|
||||
|
||||
|
||||
#include "sky.hpp"
|
||||
#include "debugging.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "renderinginterface.hpp"
|
||||
|
||||
#include "objects.hpp"
|
||||
#include "actors.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Camera;
|
||||
class Viewport;
|
||||
class SceneManager;
|
||||
class SceneNode;
|
||||
class RaySceneQuery;
|
||||
class Quaternion;
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
|
||||
|
||||
class RenderingManager: private RenderingInterface {
|
||||
|
||||
private:
|
||||
|
||||
|
||||
virtual MWRender::Objects& getObjects();
|
||||
virtual MWRender::Actors& getActors();
|
||||
|
||||
public:
|
||||
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment);
|
||||
virtual ~RenderingManager();
|
||||
|
||||
virtual MWRender::Player& getPlayer(); /// \todo move this to private again as soon as
|
||||
/// MWWorld::Player has been rewritten to not need access
|
||||
/// to internal details of the rendering system anymore
|
||||
|
||||
void toggleLight();
|
||||
bool toggleRenderMode(int mode);
|
||||
|
||||
void removeCell (MWWorld::Ptr::CellStore *store);
|
||||
|
||||
/// \todo this function should be removed later. Instead the rendering subsystems should track
|
||||
/// when rebatching is needed and update automatically at the end of each frame.
|
||||
void cellAdded (MWWorld::Ptr::CellStore *store);
|
||||
|
||||
void addObject (const MWWorld::Ptr& ptr);
|
||||
void removeObject (const MWWorld::Ptr& ptr);
|
||||
|
||||
void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position);
|
||||
void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale);
|
||||
void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation);
|
||||
|
||||
/// \param store Cell the object was in previously (\a ptr has already been updated to the new cell).
|
||||
void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store);
|
||||
|
||||
void update (float duration);
|
||||
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
void skySetHour (double hour);
|
||||
void skySetDate (int day, int month);
|
||||
int skyGetMasserPhase() const;
|
||||
int skyGetSecundaPhase() const;
|
||||
void skySetMoonColour (bool red);
|
||||
void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||
/// configure fog according to cell
|
||||
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||
|
||||
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
|
||||
int number = 1);
|
||||
///< Run animation for a MW-reference. Calls to this function for references that are currently not
|
||||
/// in the rendered scene should be ignored.
|
||||
///
|
||||
/// \param mode: 0 normal, 1 immediate start, 2 immediate loop
|
||||
/// \param number How offen the animation should be run
|
||||
|
||||
void skipAnimation (const MWWorld::Ptr& ptr);
|
||||
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
|
||||
/// references that are currently not in the rendered scene should be ignored.
|
||||
|
||||
void addTime();
|
||||
|
||||
private:
|
||||
|
||||
void setAmbientMode();
|
||||
SkyManager* mSkyManager;
|
||||
OEngine::Render::OgreRenderer &mRendering;
|
||||
|
||||
MWRender::Objects mObjects;
|
||||
MWRender::Actors mActors;
|
||||
|
||||
// 0 normal, 1 more bright, 2 max
|
||||
int mAmbientMode;
|
||||
|
||||
Ogre::ColourValue mAmbientColor;
|
||||
|
||||
/// Root node for all objects added to the scene. This is rotated so
|
||||
/// that the OGRE coordinate system matches that used internally in
|
||||
/// Morrowind.
|
||||
Ogre::SceneNode *mMwRoot;
|
||||
Ogre::RaySceneQuery *mRaySceneQuery;
|
||||
|
||||
OEngine::Physic::PhysicEngine* mPhysicsEngine;
|
||||
|
||||
MWRender::Player *mPlayer;
|
||||
MWRender::Debugging mDebugging;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,127 @@
|
||||
|
||||
#include "animationextensions.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
#include <components/interpreter/interpreter.hpp>
|
||||
#include <components/interpreter/runtime.hpp>
|
||||
#include <components/interpreter/opcodes.hpp>
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Animation
|
||||
{
|
||||
template<class R>
|
||||
class OpSkipAnim : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
context.getWorld().skipAnimation (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpPlayAnim : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string group = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer mode = 0;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
mode = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (mode<0 || mode>2)
|
||||
throw std::runtime_error ("animation mode out of range");
|
||||
}
|
||||
|
||||
context.getWorld().playAnimationGroup (ptr, group, mode, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpLoopAnim : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string group = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer loops = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (loops<0)
|
||||
throw std::runtime_error ("number of animation loops must be non-negative");
|
||||
|
||||
Interpreter::Type_Integer mode = 0;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
mode = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (mode<0 || mode>2)
|
||||
throw std::runtime_error ("animation mode out of range");
|
||||
}
|
||||
|
||||
context.getWorld().playAnimationGroup (ptr, group, mode, loops);
|
||||
}
|
||||
};
|
||||
|
||||
const int opcodeSkipAnim = 0x2000138;
|
||||
const int opcodeSkipAnimExplicit = 0x2000139;
|
||||
const int opcodePlayAnim = 0x20006;
|
||||
const int opcodePlayAnimExplicit = 0x20007;
|
||||
const int opcodeLoopAnim = 0x20008;
|
||||
const int opcodeLoopAnimExplicit = 0x20009;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
extensions.registerInstruction ("skipanim", "", opcodeSkipAnim, opcodeSkipAnimExplicit);
|
||||
extensions.registerInstruction ("playgroup", "c/l", opcodePlayAnim, opcodePlayAnimExplicit);
|
||||
extensions.registerInstruction ("loopgroup", "cl/l", opcodeLoopAnim, opcodeLoopAnimExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
interpreter.installSegment5 (opcodeSkipAnim, new OpSkipAnim<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeSkipAnimExplicit, new OpSkipAnim<ExplicitRef>);
|
||||
interpreter.installSegment3 (opcodePlayAnim, new OpPlayAnim<ImplicitRef>);
|
||||
interpreter.installSegment3 (opcodePlayAnimExplicit, new OpPlayAnim<ExplicitRef>);
|
||||
interpreter.installSegment3 (opcodeLoopAnim, new OpLoopAnim<ImplicitRef>);
|
||||
interpreter.installSegment3 (opcodeLoopAnimExplicit, new OpLoopAnim<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#ifndef GAME_SCRIPT_ANIMATIONEXTENSIONS_H
|
||||
#define GAME_SCRIPT_ANIMATIONEXTENSIONS_H
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Extensions;
|
||||
}
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
class Interpreter;
|
||||
}
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Animation
|
||||
{
|
||||
void registerExtensions (Compiler::Extensions& extensions);
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue