Port CharacterPreview

c++11
scrawl 10 years ago
parent 820f4a2688
commit 72c1f37527

@ -22,10 +22,10 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
actors objects renderingmanager animation sky npcanimation vismask
creatureanimation effectmanager util renderinginterface pathgrid rendermode
bulletdebugdraw globalmap
bulletdebugdraw globalmap characterpreview
# camera
# localmap occlusionquery water shadows
# characterpreview ripplesimulation refraction
# ripplesimulation refraction
# terrainstorage weaponanimation
)

@ -60,8 +60,10 @@ namespace
namespace MWGui
{
CharacterCreation::CharacterCreation()
: mNameDialog(0)
CharacterCreation::CharacterCreation(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem)
: mViewer(viewer)
, mResourceSystem(resourceSystem)
, mNameDialog(0)
, mRaceDialog(0)
, mClassChoiceDialog(0)
, mGenerateClassQuestionDialog(0)
@ -146,7 +148,7 @@ namespace MWGui
case GM_Race:
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
mRaceDialog = 0;
mRaceDialog = new RaceDialog();
mRaceDialog = new RaceDialog(mViewer, mResourceSystem);
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
mRaceDialog->setRaceId(mPlayerRaceId);
mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
@ -261,12 +263,6 @@ namespace MWGui
}
}
void CharacterCreation::doRenderUpdate()
{
if (mRaceDialog)
mRaceDialog->doRenderUpdate();
}
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
{
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);

@ -8,6 +8,16 @@
#include "../mwmechanics/stat.hpp"
namespace osgViewer
{
class Viewer;
}
namespace Resource
{
class ResourceSystem;
}
namespace MWGui
{
class WindowBase;
@ -29,7 +39,7 @@ namespace MWGui
public:
typedef std::vector<int> SkillList;
CharacterCreation();
CharacterCreation(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem);
~CharacterCreation();
//Show a dialog
@ -39,9 +49,11 @@ namespace MWGui
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
void configureSkills (const SkillList& major, const SkillList& minor);
void doRenderUpdate();
private:
osgViewer::Viewer* mViewer;
Resource::ResourceSystem* mResourceSystem;
//Dialogs
TextInputDialog* mNameDialog;
RaceDialog* mRaceDialog;

@ -8,6 +8,10 @@
#include <MyGUI_InputManager.h>
#include <MyGUI_Button.h>
#include <osg/Texture2D>
#include <components/myguiplatform/myguitexture.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/world.hpp"
@ -48,22 +52,23 @@ namespace
namespace MWGui
{
InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop)
InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop, osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem)
: WindowPinnableBase("openmw_inventory_window.layout")
, mTrading(false)
, mLastXSize(0)
, mLastYSize(0)
#if 0
, mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr()))
#endif
, mPreviewDirty(true)
, mPreviewResize(true)
, mViewer(viewer)
, mResourceSystem(resourceSystem)
, mPreview(new MWRender::InventoryPreview(viewer, resourceSystem, MWBase::Environment::get().getWorld()->getPlayerPtr()))
, mDragAndDrop(dragAndDrop)
, mSortModel(NULL)
, mTradeModel(NULL)
, mSelectedItem(-1)
, mGuiMode(GM_Inventory)
{
mPreviewTexture.reset(new osgMyGUI::OSGTexture(mPreview->getTexture()));
mPreview->rebuild();
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize);
getWidget(mAvatar, "Avatar");
@ -79,6 +84,8 @@ namespace MWGui
getWidget(mArmorRating, "ArmorRating");
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
mAvatarImage->setRenderItemTexture(mPreviewTexture.get());
mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
getWidget(mItemView, "ItemView");
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
@ -115,17 +122,13 @@ namespace MWGui
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel(mSortModel);
mPreview.reset(NULL);
mAvatarImage->setImageTexture("");
#if 0
MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().getTexture("CharacterPreview");
if (tex)
MyGUI::RenderManager::getInstance().destroyTexture(tex);
mPreview.reset(new MWRender::InventoryPreview(mPtr));
mPreview->setup();
#endif
mPreviewDirty = true;
mPreviewResize = true;
mPreview->updatePtr(mPtr);
mPreview->rebuild();
mPreview->update();
dirtyPreview();
updatePreviewSize();
}
void InventoryWindow::setGuiMode(GuiMode mode)
@ -158,7 +161,7 @@ namespace MWGui
static_cast<int>(Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height));
if (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight())
mPreviewResize = true;
updatePreviewSize();
mMainWidget->setPosition(pos);
mMainWidget->setSize(size);
@ -319,7 +322,8 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
mItemView->update();
mPreviewDirty = true;
dirtyPreview();
}
void InventoryWindow::open()
@ -366,10 +370,31 @@ namespace MWGui
{
mLastXSize = mMainWidget->getSize().width;
mLastYSize = mMainWidget->getSize().height;
mPreviewResize = true;
updatePreviewSize();
updateArmorRating();
}
}
void InventoryWindow::updateArmorRating()
{
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
+ MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
if (mArmorRating->getTextSize().width > mArmorRating->getSize().width)
mArmorRating->setCaptionWithReplacing (MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
}
void InventoryWindow::updatePreviewSize()
{
MyGUI::IntSize size = mAvatarImage->getSize();
int width = std::min(mPreview->getTextureWidth(), size.width);
int height = std::min(mPreview->getTextureHeight(), size.height);
mPreview->setViewport(width, height);
mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, height/float(mPreview->getTextureHeight()),
width/float(mPreview->getTextureWidth()), 0.f));
}
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
{
if (_sender == mFilterAll)
@ -483,8 +508,6 @@ namespace MWGui
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
{
return MWWorld::Ptr();
#if 0
int slot = mPreview->getSlotSelected (x, y);
if (slot == -1)
@ -503,7 +526,6 @@ namespace MWGui
}
return MWWorld::Ptr();
#endif
}
void InventoryWindow::updateEncumbranceBar()
@ -529,36 +551,11 @@ namespace MWGui
mTrading = trading;
}
void InventoryWindow::doRenderUpdate ()
void InventoryWindow::dirtyPreview()
{
#if 0
mPreview->onFrame();
if (mPreviewResize || mPreviewDirty)
{
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
+ MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
if (mArmorRating->getTextSize().width > mArmorRating->getSize().width)
mArmorRating->setCaptionWithReplacing (MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
}
if (mPreviewResize)
{
mPreviewResize = false;
MyGUI::IntSize size = mAvatarImage->getSize();
mPreview->resize(size.width, size.height);
mAvatarImage->setImageTexture("CharacterPreview");
mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height)));
mAvatarImage->setImageTile(MyGUI::IntSize(std::min(512, size.width), std::min(1024, size.height)));
}
if (mPreviewDirty)
{
mPreviewDirty = false;
mPreview->update ();
mPreview->update();
mAvatarImage->setImageTexture("CharacterPreview");
}
#endif
updateArmorRating();
}
void InventoryWindow::notifyContentChanged()
@ -569,7 +566,7 @@ namespace MWGui
MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(
MWBase::Environment::get().getWorld()->getPlayerPtr());
mPreviewDirty = true;
dirtyPreview();
}
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
@ -675,8 +672,6 @@ namespace MWGui
void InventoryWindow::rebuildAvatar()
{
#if 0
mPreview->rebuild();
#endif
}
}

@ -6,6 +6,16 @@
#include "../mwworld/ptr.hpp"
namespace osgViewer
{
class Viewer;
}
namespace Resource
{
class ResourceSystem;
}
namespace MWRender
{
class InventoryPreview;
@ -27,12 +37,10 @@ namespace MWGui
class InventoryWindow : public WindowPinnableBase
{
public:
InventoryWindow(DragAndDrop* dragAndDrop);
InventoryWindow(DragAndDrop* dragAndDrop, osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem);
virtual void open();
void doRenderUpdate();
/// start trading, disables item drag&drop
void setTrading(bool trading);
@ -62,8 +70,6 @@ namespace MWGui
private:
DragAndDrop* mDragAndDrop;
bool mPreviewDirty;
bool mPreviewResize;
int mSelectedItem;
MWWorld::Ptr mPtr;
@ -93,6 +99,10 @@ namespace MWGui
int mLastXSize;
int mLastYSize;
Resource::ResourceSystem* mResourceSystem;
osgViewer::Viewer* mViewer;
std::auto_ptr<MyGUI::ITexture> mPreviewTexture;
std::auto_ptr<MWRender::InventoryPreview> mPreview;
bool mTrading;
@ -113,6 +123,9 @@ namespace MWGui
void updateEncumbranceBar();
void notifyContentChanged();
void dirtyPreview();
void updatePreviewSize();
void updateArmorRating();
void adjustPanes();

@ -5,8 +5,12 @@
#include <MyGUI_RenderManager.h>
#include <MyGUI_Gui.h>
#include <osg/Texture2D>
#include <boost/format.hpp>
#include <components/myguiplatform/myguitexture.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -37,8 +41,10 @@ namespace
namespace MWGui
{
RaceDialog::RaceDialog()
RaceDialog::RaceDialog(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem)
: WindowModal("openmw_chargen_race.layout")
, mViewer(viewer)
, mResourceSystem(resourceSystem)
, mGenderIndex(0)
, mFaceIndex(0)
, mHairIndex(0)
@ -125,19 +131,20 @@ namespace MWGui
updateSkills();
updateSpellPowers();
//mPreview.reset(NULL);
mPreviewImage->setRenderItemTexture(NULL);
mPreviewImage->setImageTexture("");
mPreview.reset(NULL);
mPreviewTexture.reset(NULL);
const std::string textureName = "CharacterHeadPreview";
MyGUI::RenderManager::getInstance().destroyTexture(MyGUI::RenderManager::getInstance().getTexture(textureName));
mPreview.reset(new MWRender::RaceSelectionPreview(mViewer, mResourceSystem));
mPreview->rebuild();
mPreview->setAngle (mCurrentAngle);
//mPreview.reset(new MWRender::RaceSelectionPreview());
//mPreview->setup();
//mPreview->update (mCurrentAngle);
mPreviewTexture.reset(new osgMyGUI::OSGTexture(mPreview->getTexture()));
mPreviewImage->setRenderItemTexture(mPreviewTexture.get());
mPreviewImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
//const ESM::NPC& proto = mPreview->getPrototype();
ESM::NPC proto;
const ESM::NPC& proto = mPreview->getPrototype();
setRaceId(proto.mRace);
recountParts();
@ -153,8 +160,6 @@ namespace MWGui
mHairIndex = i;
}
mPreviewImage->setImageTexture (textureName);
mPreviewDirty = true;
size_t initialPos = mHeadRotate->getScrollRange()/2+mHeadRotate->getScrollRange()/10;
@ -182,10 +187,10 @@ namespace MWGui
void RaceDialog::close()
{
mPreviewImage->setImageTexture("");
const std::string textureName = "CharacterHeadPreview";
MyGUI::RenderManager::getInstance().destroyTexture(MyGUI::RenderManager::getInstance().getTexture(textureName));
//mPreview.reset(NULL);
mPreviewImage->setRenderItemTexture(NULL);
mPreviewTexture.reset(NULL);
mPreview.reset(NULL);
}
// widget controls
@ -205,8 +210,8 @@ namespace MWGui
void RaceDialog::onHeadRotate(MyGUI::ScrollBar* scroll, size_t _position)
{
float angle = (float(_position) / (scroll->getScrollRange()-1) - 0.5f) * 3.14f * 2;
//mPreview->update (angle);
mPreviewDirty = true;
mPreview->setAngle (angle);
mCurrentAngle = angle;
}
@ -317,7 +322,7 @@ namespace MWGui
void RaceDialog::updatePreview()
{
ESM::NPC record;// = mPreview->getPrototype();
ESM::NPC record = mPreview->getPrototype();
record.mRace = mCurrentRaceId;
record.setIsMale(mGenderIndex == 0);
@ -326,27 +331,12 @@ namespace MWGui
try
{
//mPreview->setPrototype(record);
mPreview->setPrototype(record);
}
catch (std::exception& e)
{
std::cerr << "Error creating preview: " << e.what() << std::endl;
}
mPreviewDirty = true;
}
void RaceDialog::doRenderUpdate()
{
//if (!mPreview.get())
return;
//mPreview->onFrame();
if (mPreviewDirty)
{
//mPreview->render();
mPreviewDirty = false;
}
}
void RaceDialog::updateRaces()
@ -451,8 +441,6 @@ namespace MWGui
const ESM::NPC& RaceDialog::getResult() const
{
static ESM::NPC result;
return result;
//return mPreview->getPrototype();
return mPreview->getPrototype();
}
}

@ -19,12 +19,22 @@ namespace ESM
struct NPC;
}
namespace osgViewer
{
class Viewer;
}
namespace Resource
{
class ResourceSystem;
}
namespace MWGui
{
class RaceDialog : public WindowModal
{
public:
RaceDialog();
RaceDialog(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem);
enum Gender
{
@ -35,13 +45,9 @@ namespace MWGui
const ESM::NPC &getResult() const;
const std::string &getRaceId() const { return mCurrentRaceId; }
Gender getGender() const { return mGenderIndex == 0 ? GM_Male : GM_Female; }
// getFace()
// getHair()
void setRaceId(const std::string &raceId);
void setGender(Gender gender) { mGenderIndex = gender == GM_Male ? 0 : 1; }
// setFace()
// setHair()
void setNextButtonShow(bool shown);
virtual void open();
@ -60,8 +66,6 @@ namespace MWGui
*/
EventHandle_WindowBase eventDone;
void doRenderUpdate();
protected:
void onHeadRotate(MyGUI::ScrollBar* _sender, size_t _position);
@ -89,6 +93,9 @@ namespace MWGui
void getBodyParts (int part, std::vector<std::string>& out);
osgViewer::Viewer* mViewer;
Resource::ResourceSystem* mResourceSystem;
std::vector<std::string> mAvailableHeads;
std::vector<std::string> mAvailableHairs;
@ -108,7 +115,8 @@ namespace MWGui
float mCurrentAngle;
//std::auto_ptr<MWRender::RaceSelectionPreview> mPreview;
std::auto_ptr<MWRender::RaceSelectionPreview> mPreview;
std::auto_ptr<MyGUI::ITexture> mPreviewTexture;
bool mPreviewDirty;
};

@ -275,7 +275,7 @@ namespace MWGui
mJournal = JournalWindow::create(JournalViewModel::create ());
mMessageBoxManager = new MessageBoxManager(
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fMessageTimePerChar")->getFloat());
mInventoryWindow = new InventoryWindow(mDragAndDrop);
mInventoryWindow = new InventoryWindow(mDragAndDrop, mViewer, mResourceSystem);
mTradeWindow = new TradeWindow();
trackWindow(mTradeWindow, "barter");
mSpellBuyingWindow = new SpellBuyingWindow();
@ -324,7 +324,7 @@ namespace MWGui
mHud->setVisible(mHudEnabled);
mCharGen = new CharacterCreation();
mCharGen = new CharacterCreation(mViewer, mResourceSystem);
// Setup player stats
for (int i = 0; i < ESM::Attribute::Length; ++i)
@ -358,7 +358,7 @@ namespace MWGui
{
disallowAll();
delete mCharGen;
mCharGen = new CharacterCreation();
mCharGen = new CharacterCreation(mViewer, mResourceSystem);
mGuiModes.clear();
MWBase::Environment::get().getInputManager()->changeInputMode(false);
mHud->unsetSelectedWeapon();

@ -1081,12 +1081,21 @@ namespace MWRender
return true;
}
bool Animation::hasNode(const std::string &name)
bool Animation::hasNode(const std::string &name) const
{
std::string lowerName = Misc::StringUtils::lowerCase(name);
return (mNodeMap.find(lowerName) != mNodeMap.end());
}
const osg::Node* Animation::getNode(const std::string &name) const
{
std::string lowerName = Misc::StringUtils::lowerCase(name);
NodeMap::const_iterator found = mNodeMap.find(lowerName);
if (found == mNodeMap.end())
throw std::runtime_error("Can't find node " + name);
return found->second;
}
float Animation::AnimationTime::getValue(osg::NodeVisitor*)
{
if (mTimePtr)

@ -354,7 +354,11 @@ public:
/// Is there a node with the specified name?
/// @note The matching is case-insensitive.
bool hasNode(const std::string& name);
bool hasNode(const std::string& name) const;
/// Return a node with the specified name, throws an exception if the node is not found.
/// @note The matching is case-insensitive.
const osg::Node* getNode(const std::string& name) const;
virtual void showWeapons(bool showWeapon) {}
virtual void showCarriedLeft(bool show) {}

@ -1,189 +1,186 @@
#include "characterpreview.hpp"
#include <OgreSceneManager.h>
#include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreCamera.h>
#include <OgreSceneNode.h>
#include <OgreTextureManager.h>
#include <OgreViewport.h>
#include <OgreRenderTexture.h>
#include <libs/openengine/ogre/selectionbuffer.hpp>
#include <osg/Texture2D>
#include <osg/Camera>
#include <osg/PositionAttitudeTransform>
#include <osgViewer/Viewer>
#include <osg/LightModel>
#include <components/sceneutil/lightmanager.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp"
#include "renderconst.hpp"
#include "npcanimation.hpp"
namespace MWRender
{
CharacterPreview::CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name,
Ogre::Vector3 position, Ogre::Vector3 lookAt)
: mRecover(false)
, mRenderTarget(NULL)
, mViewport(NULL)
, mCamera(NULL)
, mSceneMgr (0)
, mNode(NULL)
class DrawOnceCallback : public osg::NodeCallback
{
public:
DrawOnceCallback ()
: mRendered(false)
{
}
virtual void operator () (osg::Node* node, osg::NodeVisitor* nv)
{
if (!mRendered)
{
mRendered = true;
}
else
{
node->setNodeMask(0);
}
traverse(node, nv);
}
void redrawNextFrame()
{
mRendered = false;
}
private:
bool mRendered;
};
CharacterPreview::CharacterPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem,
MWWorld::Ptr character, int sizeX, int sizeY, const osg::Vec3f& position, const osg::Vec3f& lookAt)
: mViewer(viewer)
, mResourceSystem(resourceSystem)
, mPosition(position)
, mLookAt(lookAt)
, mCharacter(character)
, mAnimation(NULL)
, mName(name)
, mSizeX(sizeX)
, mSizeY(sizeY)
{
mTexture = new osg::Texture2D;
mTexture->setTextureSize(sizeX, sizeY);
mTexture->setInternalFormat(GL_RGBA);
mTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
mCamera = new osg::Camera;
// hints that the camera is not relative to the master camera
mCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
mCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
mCamera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 0.f));
mCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const float fovYDegrees = 12.3f;
mCamera->setProjectionMatrixAsPerspective(fovYDegrees, sizeX/static_cast<float>(sizeY), 0.1f, 10000.f); // zNear and zFar are autocomputed
mCamera->setViewport(0, 0, sizeX, sizeY);
mCamera->setRenderOrder(osg::Camera::PRE_RENDER);
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture);
mCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager;
lightManager->setStartLight(1);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel;
lightmodel->setAmbientIntensity(osg::Vec4(0.25, 0.25, 0.25, 1.0));
stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
/// \todo Read the fallback values from INIImporter (Inventory:Directional*) ?
osg::ref_ptr<osg::Light> light = new osg::Light;
light->setPosition(osg::Vec4(-0.3,0.3,0.7, 0.0));
light->setDiffuse(osg::Vec4(1,1,1,1));
light->setAmbient(osg::Vec4(0,0,0,1));
light->setSpecular(osg::Vec4(0,0,0,0));
light->setLightNum(0);
light->setConstantAttenuation(1.f);
light->setLinearAttenuation(0.f);
light->setQuadraticAttenuation(0.f);
osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
lightSource->setLight(light);
lightSource->setStateSetModes(*stateset, osg::StateAttribute::ON);
lightManager->setStateSet(stateset);
lightManager->addChild(lightSource);
mCamera->addChild(lightManager);
mNode = new osg::PositionAttitudeTransform;
lightManager->addChild(mNode);
mDrawOnceCallback = new DrawOnceCallback;
mCamera->addUpdateCallback(mDrawOnceCallback);
mViewer->getSceneData()->asGroup()->addChild(mCamera);
mCharacter.mCell = NULL;
}
void CharacterPreview::onSetup()
CharacterPreview::~CharacterPreview ()
{
mViewer->getSceneData()->asGroup()->removeChild(mCamera);
}
void CharacterPreview::onFrame()
int CharacterPreview::getTextureWidth() const
{
if (mRecover)
{
setupRenderTarget();
mRenderTarget->update();
mRecover = false;
}
return mSizeX;
}
void CharacterPreview::setup ()
int CharacterPreview::getTextureHeight() const
{
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
// This is a dummy light to turn off shadows without having to use a separate set of shaders
Ogre::Light* l = mSceneMgr->createLight();
l->setType (Ogre::Light::LT_DIRECTIONAL);
l->setDiffuseColour (Ogre::ColourValue(0,0,0));
/// \todo Read the fallback values from INIImporter (Inventory:Directional*)
l = mSceneMgr->createLight();
l->setType (Ogre::Light::LT_DIRECTIONAL);
l->setDirection (Ogre::Vector3(0.3f, -0.7f, 0.3f));
l->setDiffuseColour (Ogre::ColourValue(1,1,1));
mSceneMgr->setAmbientLight (Ogre::ColourValue(0.25, 0.25, 0.25));
mCamera = mSceneMgr->createCamera (mName);
mCamera->setFOVy(Ogre::Degree(12.3f));
mCamera->setAspectRatio (float(mSizeX) / float(mSizeY));
Ogre::SceneNode* renderRoot = mSceneMgr->getRootSceneNode()->createChildSceneNode("renderRoot");
// leftover of old coordinate system. TODO: remove this and adjust positions/orientations to match
renderRoot->pitch(Ogre::Degree(-90));
mNode = renderRoot->createChildSceneNode();
mAnimation = new NpcAnimation(mCharacter, mNode,
0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
Ogre::Vector3 scale = mNode->getScale();
mCamera->setPosition(mPosition * scale);
mCamera->lookAt(mLookAt * scale);
mCamera->setNearClipDistance (1);
mCamera->setFarClipDistance (1000);
mTexture = Ogre::TextureManager::getSingleton().createManual(mName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mSizeX, mSizeY, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET, this);
setupRenderTarget();
return mSizeY;
}
onSetup ();
void CharacterPreview::onSetup()
{
}
CharacterPreview::~CharacterPreview ()
osg::ref_ptr<osg::Texture2D> CharacterPreview::getTexture()
{
if (mSceneMgr)
{
mSceneMgr->destroyAllCameras();
delete mAnimation;
Ogre::Root::getSingleton().destroySceneManager(mSceneMgr);
Ogre::TextureManager::getSingleton().remove(mName);
}
return mTexture;
}
void CharacterPreview::rebuild()
{
delete mAnimation;
mAnimation = NULL;
mAnimation = new NpcAnimation(mCharacter, mNode,
0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
float scale=1.f;
mCharacter.getClass().adjustScale(mCharacter, scale);
mNode->setScale(Ogre::Vector3(scale));
mCamera->setPosition(mPosition * mNode->getScale());
mCamera->lookAt(mLookAt * mNode->getScale());
mAnimation = new NpcAnimation(mCharacter, mNode, mResourceSystem, 0, true, true,
(renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
onSetup();
}
void CharacterPreview::loadResource(Ogre::Resource *resource)
{
Ogre::Texture* tex = dynamic_cast<Ogre::Texture*>(resource);
if (!tex)
return;
tex->createInternalResources();
mRenderTarget = NULL;
mViewport = NULL;
mRecover = true;
redraw();
}
void CharacterPreview::setupRenderTarget()
void CharacterPreview::redraw()
{
mRenderTarget = mTexture->getBuffer()->getRenderTarget();
mRenderTarget->removeAllViewports ();
mViewport = mRenderTarget->addViewport(mCamera);
mViewport->setOverlaysEnabled(false);
mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0));
mViewport->setShadowsEnabled(false);
mRenderTarget->setActive(true);
mRenderTarget->setAutoUpdated (false);
mCamera->setNodeMask(~0);
mDrawOnceCallback->redrawNextFrame();
}
// --------------------------------------------------------------------------------------------------
InventoryPreview::InventoryPreview(MWWorld::Ptr character)
: CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 71, -700), Ogre::Vector3(0,71,0))
, mSizeX(0)
, mSizeY(0)
, mSelectionBuffer(NULL)
InventoryPreview::InventoryPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character)
: CharacterPreview(viewer, resourceSystem, character, 512, 1024, osg::Vec3f(0, 700, 71), osg::Vec3f(0,0,71))
{
}
InventoryPreview::~InventoryPreview()
void InventoryPreview::setViewport(int sizeX, int sizeY)
{
delete mSelectionBuffer;
}
void InventoryPreview::resize(int sizeX, int sizeY)
{
mSizeX = sizeX;
mSizeY = sizeY;
sizeX = std::max(sizeX, 0);
sizeY = std::max(sizeY, 0);
mViewport->setDimensions (0, 0, std::min(1.f, float(mSizeX) / float(512)), std::min(1.f, float(mSizeY) / float(1024)));
mTexture->load();
mCamera->setViewport(0, 0, std::min(mSizeX, sizeX), std::min(mSizeY, sizeY));
if (!mRenderTarget)
setupRenderTarget();
mRenderTarget->update();
redraw();
}
void InventoryPreview::update()
@ -191,6 +188,7 @@ namespace MWRender
if (!mAnimation)
return;
mAnimation->showWeapons(true);
mAnimation->updateParts();
MWWorld::InventoryStore &inv = mCharacter.getClass().getInventoryStore(mCharacter);
@ -250,70 +248,51 @@ namespace MWRender
mAnimation->runAnimation(0.0f);
mNode->setOrientation (Ogre::Quaternion::IDENTITY);
mViewport->setDimensions (0, 0, std::min(1.f, float(mSizeX) / float(512)), std::min(1.f, float(mSizeY) / float(1024)));
mTexture->load();
if (!mRenderTarget)
setupRenderTarget();
mRenderTarget->update();
mSelectionBuffer->update();
redraw();
}
void InventoryPreview::setupRenderTarget()
int InventoryPreview::getSlotSelected (int posX, int posY)
{
CharacterPreview::setupRenderTarget();
mViewport->setDimensions (0, 0, std::min(1.f, float(mSizeX) / float(512)), std::min(1.f, float(mSizeY) / float(1024)));
// TODO: implement
return 0;
}
int InventoryPreview::getSlotSelected (int posX, int posY)
void InventoryPreview::updatePtr(const MWWorld::Ptr &ptr)
{
return mSelectionBuffer->getSelected (posX, posY);
mCharacter = MWWorld::Ptr(ptr.getBase(), NULL);
}
void InventoryPreview::onSetup ()
void InventoryPreview::onSetup()
{
delete mSelectionBuffer;
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
osg::Vec3f scale (1.f, 1.f, 1.f);
mCharacter.getClass().adjustScale(mCharacter, scale);
mAnimation->showWeapons(true);
mNode->setScale(scale);
mCurrentAnimGroup = "inventoryhandtohand";
mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
mCamera->setViewMatrixAsLookAt(mPosition * scale.z(), mLookAt * scale.z(), osg::Vec3f(0,0,1));
}
// --------------------------------------------------------------------------------------------------
RaceSelectionPreview::RaceSelectionPreview()
: CharacterPreview(MWBase::Environment::get().getWorld()->getPlayerPtr(),
512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 8, -125), Ogre::Vector3(0,127,0))
RaceSelectionPreview::RaceSelectionPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem)
: CharacterPreview(viewer, resourceSystem, MWBase::Environment::get().getWorld()->getPlayerPtr(),
512, 512, osg::Vec3f(0, 125, 8), osg::Vec3f(0,0,8))
, mBase (*mCharacter.get<ESM::NPC>()->mBase)
, mRef(&mBase)
, mPitch(Ogre::Degree(6))
, mPitchRadians(osg::DegreesToRadians(6.f))
{
mCharacter = MWWorld::Ptr(&mRef, NULL);
}
void RaceSelectionPreview::update(float angle)
RaceSelectionPreview::~RaceSelectionPreview()
{
mAnimation->runAnimation(0.0f);
mNode->setOrientation(Ogre::Quaternion(Ogre::Radian(angle), Ogre::Vector3::UNIT_Z)
* Ogre::Quaternion(mPitch, Ogre::Vector3::UNIT_X));
updateCamera();
}
void RaceSelectionPreview::render()
void RaceSelectionPreview::setAngle(float angleRadians)
{
mTexture->load();
if (!mRenderTarget)
setupRenderTarget();
mRenderTarget->update();
mNode->setAttitude(osg::Quat(mPitchRadians, osg::Vec3(1,0,0))
* osg::Quat(angleRadians, osg::Vec3(0,0,1)));
redraw();
}
void RaceSelectionPreview::setPrototype(const ESM::NPC &proto)
@ -321,27 +300,53 @@ namespace MWRender
mBase = proto;
mBase.mId = "player";
rebuild();
mAnimation->runAnimation(0.0f);
updateCamera();
}
void RaceSelectionPreview::onSetup ()
class UpdateCameraCallback : public osg::NodeCallback
{
mAnimation->play("idle", 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
public:
UpdateCameraCallback(osg::ref_ptr<const osg::Node> nodeToFollow, const osg::Vec3& posOffset, const osg::Vec3& lookAtOffset)
: mNodeToFollow(nodeToFollow)
, mPosOffset(posOffset)
, mLookAtOffset(lookAtOffset)
{
}
updateCamera();
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osg::Camera* cam = static_cast<osg::Camera*>(node);
void RaceSelectionPreview::updateCamera()
// Update keyframe controllers in the scene graph first...
traverse(node, nv);
// Now update camera utilizing the updated head position
osg::MatrixList mats = mNodeToFollow->getWorldMatrices();
if (!mats.size())
return;
osg::Matrix worldMat = mats[0];
osg::Vec3 headOffset = worldMat.getTrans();
cam->setViewMatrixAsLookAt(headOffset + mPosOffset, headOffset + mLookAtOffset, osg::Vec3(0,0,1));
}
private:
osg::ref_ptr<const osg::Node> mNodeToFollow;
osg::Vec3 mPosOffset;
osg::Vec3 mLookAtOffset;
};
void RaceSelectionPreview::onSetup ()
{
Ogre::Vector3 scale = mNode->getScale();
Ogre::Node* headNode = mAnimation->getNode("Bip01 Head");
if (!headNode)
return;
Ogre::Vector3 headOffset = headNode->_getDerivedPosition();
headOffset = mNode->convertLocalToWorldPosition(headOffset);
mAnimation->play("idle", 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
mAnimation->runAnimation(0.f);
mCamera->setPosition(headOffset + mPosition * scale);
mCamera->lookAt(headOffset + mPosition*Ogre::Vector3(0,1,0) * scale);
// attach camera to follow the head node
if (mUpdateCameraCallback)
mCamera->removeUpdateCallback(mUpdateCameraCallback);
const osg::Node* head = mAnimation->getNode("Bip01 Head");
mUpdateCameraCallback = new UpdateCameraCallback(head, mPosition, mLookAt);
mCamera->addUpdateCallback(mUpdateCameraCallback);
}
}

@ -1,45 +1,48 @@
#ifndef MWRENDER_CHARACTERPREVIEW_H
#define MWRENDER_CHARACTERPREVIEW_H
#include <OgreRenderTarget.h>
#include <OgreMaterialManager.h>
#include <OgreVector3.h>
#include <osg/ref_ptr>
#include <components/esm/loadnpc.hpp>
#include <components/resource/resourcesystem.hpp>
#include "../mwworld/ptr.hpp"
namespace OEngine
namespace osg
{
namespace Render
{
class SelectionBuffer;
class Texture2D;
class Camera;
}
namespace osgViewer
{
class Viewer;
}
namespace MWRender
{
class NpcAnimation;
class DrawOnceCallback;
class CharacterPreview : public Ogre::ManualResourceLoader
class CharacterPreview
{
public:
CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name,
Ogre::Vector3 position, Ogre::Vector3 lookAt);
CharacterPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character, int sizeX, int sizeY,
const osg::Vec3f& position, const osg::Vec3f& lookAt);
virtual ~CharacterPreview();
virtual void setup ();
virtual void onSetup();
virtual void rebuild();
int getTextureWidth() const;
int getTextureHeight() const;
void onFrame();
void redraw();
void loadResource(Ogre::Resource *resource);
void rebuild();
private:
bool mRecover; // Texture content was lost and needs to be re-rendered
osg::ref_ptr<osg::Texture2D> getTexture();
private:
CharacterPreview(const CharacterPreview&);
@ -47,28 +50,23 @@ namespace MWRender
protected:
virtual bool renderHeadOnly() { return false; }
virtual void onSetup();
virtual void setupRenderTarget();
Ogre::TexturePtr mTexture;
Ogre::RenderTarget* mRenderTarget;
Ogre::Viewport* mViewport;
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::SceneNode* mNode;
osg::ref_ptr<osgViewer::Viewer> mViewer;
Resource::ResourceSystem* mResourceSystem;
osg::ref_ptr<osg::Texture2D> mTexture;
osg::ref_ptr<osg::Camera> mCamera;
osg::ref_ptr<DrawOnceCallback> mDrawOnceCallback;
Ogre::Vector3 mPosition;
Ogre::Vector3 mLookAt;
osg::Vec3f mPosition;
osg::Vec3f mLookAt;
MWWorld::Ptr mCharacter;
MWRender::NpcAnimation* mAnimation;
osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
std::string mCurrentAnimGroup;
std::string mName;
int mSizeX;
int mSizeY;
};
@ -77,25 +75,21 @@ namespace MWRender
{
public:
InventoryPreview(MWWorld::Ptr character);
virtual ~InventoryPreview();
virtual void onSetup();
InventoryPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character);
void updatePtr(const MWWorld::Ptr& ptr);
void update(); // Render preview again, e.g. after changed equipment
void resize(int sizeX, int sizeY);
void setViewport(int sizeX, int sizeY);
int getSlotSelected(int posX, int posY);
protected:
virtual void setupRenderTarget();
private:
int mSizeX;
int mSizeY;
OEngine::Render::SelectionBuffer* mSelectionBuffer;
virtual void onSetup();
};
class UpdateCameraCallback;
class RaceSelectionPreview : public CharacterPreview
{
ESM::NPC mBase;
@ -104,16 +98,13 @@ namespace MWRender
protected:
virtual bool renderHeadOnly() { return true; }
void updateCamera();
virtual void onSetup();
public:
RaceSelectionPreview();
RaceSelectionPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem);
virtual ~RaceSelectionPreview();
virtual void onSetup();
void render();
void update(float angle);
void setAngle(float angleRadians);
const ESM::NPC &getPrototype() const {
return mBase;
@ -123,7 +114,9 @@ namespace MWRender
private:
Ogre::Radian mPitch;
osg::ref_ptr<UpdateCameraCallback> mUpdateCameraCallback;
float mPitchRadians;
};
}

Loading…
Cancel
Save