Merge branch 'master' into move

move
Marc Zinnschlag 9 years ago
commit 6a2fe564ef

@ -94,6 +94,7 @@ Programmers
Nolan Poe (nopoe) Nolan Poe (nopoe)
Paul Cercueil (pcercuei) Paul Cercueil (pcercuei)
Paul McElroy (Greendogo) Paul McElroy (Greendogo)
Pi03k
Pieter van der Kloet (pvdk) Pieter van der Kloet (pvdk)
pkubik pkubik
Radu-Marius Popovici (rpopovici) Radu-Marius Popovici (rpopovici)

@ -90,7 +90,7 @@ opencs_units (view/render
opencs_units_noqt (view/render opencs_units_noqt (view/render
lighting lightingday lightingnight lighting lightingday lightingnight
lightingbright object cell terrainstorage tagbase cellarrow cellmarker lightingbright object cell terrainstorage tagbase cellarrow cellmarker cellborder
) )
opencs_hdrs_noqt (view/render opencs_hdrs_noqt (view/render

@ -47,7 +47,7 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
void CSVDoc::SubView::closeEvent (QCloseEvent *event) void CSVDoc::SubView::closeEvent (QCloseEvent *event)
{ {
emit updateSubViewIndicies (this); emit updateSubViewIndices (this);
} }
std::string CSVDoc::SubView::getTitle() const std::string CSVDoc::SubView::getTitle() const

@ -64,7 +64,7 @@ namespace CSVDoc
void updateTitle(); void updateTitle();
void updateSubViewIndicies (SubView *view = 0); void updateSubViewIndices (SubView *view = NULL);
void universalIdChanged (const CSMWorld::UniversalId& universalId); void universalIdChanged (const CSMWorld::UniversalId& universalId);

@ -343,7 +343,7 @@ void CSVDoc::View::updateTitle()
setWindowTitle (QString::fromUtf8(stream.str().c_str())); setWindowTitle (QString::fromUtf8(stream.str().c_str()));
} }
void CSVDoc::View::updateSubViewIndicies(SubView *view) void CSVDoc::View::updateSubViewIndices(SubView *view)
{ {
CSMPrefs::Category& windows = CSMPrefs::State::get()["Windows"]; CSMPrefs::Category& windows = CSMPrefs::State::get()["Windows"];
@ -373,7 +373,7 @@ void CSVDoc::View::updateSubViewIndicies(SubView *view)
else else
{ {
delete subView->titleBarWidget(); delete subView->titleBarWidget();
subView->setTitleBarWidget (0); subView->setTitleBarWidget (NULL);
} }
} }
} }
@ -402,7 +402,7 @@ void CSVDoc::View::updateActions()
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews), mScroll(0), mScrollbarOnly(false) mViewTotal (totalViews), mScroll(NULL), mScrollbarOnly(false)
{ {
CSMPrefs::Category& windows = CSMPrefs::State::get()["Windows"]; CSMPrefs::Category& windows = CSMPrefs::State::get()["Windows"];
@ -419,10 +419,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
} }
else else
{ {
mScroll = new QScrollArea(this); createScrollArea();
mScroll->setWidgetResizable(true);
mScroll->setWidget(&mSubViewWindow);
setCentralWidget(mScroll);
} }
mOperations = new Operations; mOperations = new Operations;
@ -570,36 +567,11 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
// //
mScrollbarOnly = windows["mainwindow-scrollbar"].toString() == "Scrollbar Only"; mScrollbarOnly = windows["mainwindow-scrollbar"].toString() == "Scrollbar Only";
QDesktopWidget *dw = QApplication::desktop(); updateWidth(windows["grow-limit"].isTrue(), minWidth);
QRect rect;
if (windows["grow-limit"].isTrue())
rect = dw->screenGeometry(this);
else
rect = dw->screenGeometry(dw->screen(dw->screenNumber(this)));
if (!mScrollbarOnly && mScroll && mSubViews.size() > 1)
{
int newWidth = width()+minWidth;
int frameWidth = frameGeometry().width() - width();
if (newWidth+frameWidth <= rect.width())
{
resize(newWidth, height());
// WARNING: below code assumes that new subviews are added to the right
if (x() > rect.width()-(newWidth+frameWidth))
move(rect.width()-(newWidth+frameWidth), y()); // shift left to stay within the screen
}
else
{
// full width
resize(rect.width()-frameWidth, height());
mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minWidth);
move(0, y());
}
}
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
updateSubViewIndicies(); updateSubViewIndices();
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this, connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&))); SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
@ -608,8 +580,8 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
connect (view, SIGNAL (updateTitle()), this, SLOT (updateTitle())); connect (view, SIGNAL (updateTitle()), this, SLOT (updateTitle()));
connect (view, SIGNAL (updateSubViewIndicies (SubView *)), connect (view, SIGNAL (updateSubViewIndices (SubView *)),
this, SLOT (updateSubViewIndicies (SubView *))); this, SLOT (updateSubViewIndices (SubView *)));
view->show(); view->show();
@ -631,7 +603,7 @@ void CSVDoc::View::moveScrollBarToEnd(int min, int max)
void CSVDoc::View::settingChanged (const CSMPrefs::Setting *setting) void CSVDoc::View::settingChanged (const CSMPrefs::Setting *setting)
{ {
if (*setting=="Windows/hide-subview") if (*setting=="Windows/hide-subview")
updateSubViewIndicies (0); updateSubViewIndices (NULL);
else if (*setting=="Windows/mainwindow-scrollbar") else if (*setting=="Windows/mainwindow-scrollbar")
{ {
if (setting->toString()!="Grow Only") if (setting->toString()!="Grow Only")
@ -651,10 +623,7 @@ void CSVDoc::View::settingChanged (const CSMPrefs::Setting *setting)
} }
else else
{ {
mScroll = new QScrollArea(this); createScrollArea();
mScroll->setWidgetResizable(true);
mScroll->setWidget(&mSubViewWindow);
setCentralWidget(mScroll);
} }
} }
else if (mScroll) else if (mScroll)
@ -662,7 +631,7 @@ void CSVDoc::View::settingChanged (const CSMPrefs::Setting *setting)
mScroll->takeWidget(); mScroll->takeWidget();
setCentralWidget (&mSubViewWindow); setCentralWidget (&mSubViewWindow);
mScroll->deleteLater(); mScroll->deleteLater();
mScroll = 0; mScroll = NULL;
} }
} }
} }
@ -959,3 +928,41 @@ void CSVDoc::View::merge()
{ {
emit mergeDocument (mDocument); emit mergeDocument (mDocument);
} }
void CSVDoc::View::updateWidth(bool isGrowLimit, int minSubViewWidth)
{
QDesktopWidget *dw = QApplication::desktop();
QRect rect;
if (isGrowLimit)
rect = dw->screenGeometry(this);
else
rect = dw->screenGeometry(dw->screen(dw->screenNumber(this)));
if (!mScrollbarOnly && mScroll && mSubViews.size() > 1)
{
int newWidth = width()+minSubViewWidth;
int frameWidth = frameGeometry().width() - width();
if (newWidth+frameWidth <= rect.width())
{
resize(newWidth, height());
// WARNING: below code assumes that new subviews are added to the right
if (x() > rect.width()-(newWidth+frameWidth))
move(rect.width()-(newWidth+frameWidth), y()); // shift left to stay within the screen
}
else
{
// full width
resize(rect.width()-frameWidth, height());
mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minSubViewWidth);
move(0, y());
}
}
}
void CSVDoc::View::createScrollArea()
{
mScroll = new QScrollArea(this);
mScroll->setWidgetResizable(true);
mScroll->setWidget(&mSubViewWindow);
setCentralWidget(mScroll);
}

@ -95,7 +95,8 @@ namespace CSVDoc
void resizeViewHeight (int height); void resizeViewHeight (int height);
void updateScrollbar(); void updateScrollbar();
void updateWidth(bool isGrowLimit, int minSubViewWidth);
void createScrollArea();
public: public:
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
@ -143,7 +144,7 @@ namespace CSVDoc
void updateTitle(); void updateTitle();
// called when subviews are added or removed // called when subviews are added or removed
void updateSubViewIndicies (SubView *view = 0); void updateSubViewIndices (SubView *view = NULL);
private slots: private slots:

@ -99,6 +99,9 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Mask_Terrain)); mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Mask_Terrain));
mTerrain->loadCell(esmLand.mX, mTerrain->loadCell(esmLand.mX,
esmLand.mY); esmLand.mY);
mCellBorder.reset(new CellBorder(mCellNode, mCoordinates));
mCellBorder->buildShape(esmLand);
} }
} }
} }

@ -16,6 +16,7 @@
#include "object.hpp" #include "object.hpp"
#include "cellarrow.hpp" #include "cellarrow.hpp"
#include "cellmarker.hpp" #include "cellmarker.hpp"
#include "cellborder.hpp"
class QModelIndex; class QModelIndex;
@ -44,6 +45,7 @@ namespace CSVRender
CSMWorld::CellCoordinates mCoordinates; CSMWorld::CellCoordinates mCoordinates;
std::auto_ptr<CellArrow> mCellArrows[4]; std::auto_ptr<CellArrow> mCellArrows[4];
std::auto_ptr<CellMarker> mCellMarker; std::auto_ptr<CellMarker> mCellMarker;
std::auto_ptr<CellBorder> mCellBorder;
bool mDeleted; bool mDeleted;
int mSubMode; int mSubMode;
unsigned int mSubModeElementMask; unsigned int mSubModeElementMask;

@ -0,0 +1,96 @@
#include "cellborder.hpp"
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include <components/esm/loadland.hpp>
#include "mask.hpp"
#include "../../model/world/cellcoordinates.hpp"
const int CSVRender::CellBorder::CellSize = ESM::Land::REAL_SIZE;
const int CSVRender::CellBorder::VertexCount = (ESM::Land::LAND_SIZE * 4) - 3;
CSVRender::CellBorder::CellBorder(osg::Group* cellNode, const CSMWorld::CellCoordinates& coords)
: mParentNode(cellNode)
{
mBaseNode = new osg::PositionAttitudeTransform();
mBaseNode->setNodeMask(Mask_CellBorder);
mBaseNode->setPosition(osg::Vec3f(coords.getX() * CellSize, coords.getY() * CellSize, 10));
mParentNode->addChild(mBaseNode);
}
CSVRender::CellBorder::~CellBorder()
{
mParentNode->removeChild(mBaseNode);
}
void CSVRender::CellBorder::buildShape(const ESM::Land& esmLand)
{
const ESM::Land::LandData* landData = esmLand.getLandData(ESM::Land::DATA_VHGT);
if (!landData)
return;
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
// Vertices
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array();
int x = 0, y = 0;
for (; x < ESM::Land::LAND_SIZE; ++x)
vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)]));
x = ESM::Land::LAND_SIZE - 1;
for (; y < ESM::Land::LAND_SIZE; ++y)
vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)]));
y = ESM::Land::LAND_SIZE - 1;
for (; x >= 0; --x)
vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)]));
x = 0;
for (; y >= 0; --y)
vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)]));
geometry->setVertexArray(vertices);
// Color
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array();
colors->push_back(osg::Vec4f(0.f, 0.5f, 0.f, 1.f));
geometry->setColorArray(colors, osg::Array::BIND_PER_PRIMITIVE_SET);
// Primitive
osg::ref_ptr<osg::DrawElementsUShort> primitives =
new osg::DrawElementsUShort(osg::PrimitiveSet::LINE_STRIP, VertexCount+1);
for (size_t i = 0; i < VertexCount; ++i)
primitives->setElement(i, i);
primitives->setElement(VertexCount, 0);
geometry->addPrimitiveSet(primitives);
geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->addDrawable(geometry);
mBaseNode->addChild(geode);
}
size_t CSVRender::CellBorder::landIndex(int x, int y)
{
return y * ESM::Land::LAND_SIZE + x;
}
float CSVRender::CellBorder::scaleToWorld(int value)
{
return (CellSize + 128) * (float)value / ESM::Land::LAND_SIZE;
}

@ -0,0 +1,54 @@
#ifndef OPENCS_VIEW_CELLBORDER_H
#define OPENCS_VIEW_CELLBORDER_H
#include <cstddef>
#include <osg/ref_ptr>
namespace osg
{
class Group;
class PositionAttitudeTransform;
}
namespace ESM
{
struct Land;
}
namespace CSMWorld
{
class CellCoordinates;
}
namespace CSVRender
{
class CellBorder
{
public:
CellBorder(osg::Group* cellNode, const CSMWorld::CellCoordinates& coords);
~CellBorder();
void buildShape(const ESM::Land& esmLand);
private:
static const int CellSize;
static const int VertexCount;
size_t landIndex(int x, int y);
float scaleToWorld(int val);
// unimplemented
CellBorder(const CellBorder&);
CellBorder& operator=(const CellBorder&);
osg::Group* mParentNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
};
}
#endif

@ -598,7 +598,7 @@ CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibil
mControlElements->addButton (":placeholder", Mask_CellMarker, ":placeholder", mControlElements->addButton (":placeholder", Mask_CellMarker, ":placeholder",
"Cell marker"); "Cell marker");
mControlElements->addButton (":placeholder", Mask_CellArrow, ":placeholder", "Cell arrows"); mControlElements->addButton (":placeholder", Mask_CellArrow, ":placeholder", "Cell arrows");
mControlElements->addButton (":placeholder", Mask_CellBorder, ":placeholder", "Cell border"); mControlElements->addButton (":scenetoolbar/grid", Mask_CellBorder, ":scenetoolbar/grid-small", "Cell border");
mControlElements->setSelectionMask (0xffffffff); mControlElements->setSelectionMask (0xffffffff);

@ -1363,6 +1363,7 @@ namespace MWRender
foundKeyframeCtrl = true; foundKeyframeCtrl = true;
break; break;
} }
cb = cb->getNestedCallback();
} }
if (foundKeyframeCtrl) if (foundKeyframeCtrl)

@ -182,23 +182,30 @@ void WeaponAnimation::deleteControllers()
void WeaponAnimation::configureControllers(float characterPitchRadians) void WeaponAnimation::configureControllers(float characterPitchRadians)
{ {
if (!mSpineControllers[0])
return;
if (mPitchFactor == 0.f || characterPitchRadians == 0.f) if (mPitchFactor == 0.f || characterPitchRadians == 0.f)
{ {
for (int i=0; i<2; ++i) setControllerEnabled(false);
mSpineControllers[i]->setEnabled(false);
return; return;
} }
float pitch = characterPitchRadians * mPitchFactor; float pitch = characterPitchRadians * mPitchFactor;
osg::Quat rotate (pitch/2, osg::Vec3f(-1,0,0)); osg::Quat rotate (pitch/2, osg::Vec3f(-1,0,0));
setControllerRotate(rotate);
setControllerEnabled(true);
}
void WeaponAnimation::setControllerRotate(const osg::Quat& rotate)
{
for (int i=0; i<2; ++i) for (int i=0; i<2; ++i)
{ if (mSpineControllers[i])
mSpineControllers[i]->setRotate(rotate); mSpineControllers[i]->setRotate(rotate);
mSpineControllers[i]->setEnabled(true); }
}
void WeaponAnimation::setControllerEnabled(bool enabled)
{
for (int i=0; i<2; ++i)
if (mSpineControllers[i])
mSpineControllers[i]->setEnabled(enabled);
} }
} }

@ -52,6 +52,9 @@ namespace MWRender
osg::ref_ptr<RotateController> mSpineControllers[2]; osg::ref_ptr<RotateController> mSpineControllers[2];
void setControllerRotate(const osg::Quat& rotate);
void setControllerEnabled(bool enabled);
virtual osg::Group* getArrowBone() = 0; virtual osg::Group* getArrowBone() = 0;
virtual osg::Node* getWeaponNode() = 0; virtual osg::Node* getWeaponNode() = 0;
virtual Resource::ResourceSystem* getResourceSystem() = 0; virtual Resource::ResourceSystem* getResourceSystem() = 0;

@ -2039,7 +2039,7 @@ namespace MWWorld
bool World::isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const bool World::isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const
{ {
if (!(cell->getCell()->mData.mFlags & ESM::Cell::HasWater)) { if (!(cell->getCell()->hasWater())) {
return false; return false;
} }
return pos.z() < cell->getWaterLevel(); return pos.z() < cell->getWaterLevel();

@ -141,7 +141,7 @@ struct Cell
bool hasWater() const bool hasWater() const
{ {
return (mData.mFlags&HasWater) != 0; return ((mData.mFlags&HasWater) != 0) || isExterior();
} }
// Restore the given reader to the stored position. Will try to open // Restore the given reader to the stored position. Will try to open

@ -470,7 +470,7 @@ namespace NifOsg
const Nif::NiTextureEffect* textureEffect = static_cast<const Nif::NiTextureEffect*>(nifNode); const Nif::NiTextureEffect* textureEffect = static_cast<const Nif::NiTextureEffect*>(nifNode);
if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map) if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map)
{ {
std::cerr << "Unhandled NiTextureEffect type " << textureEffect->textureType << std::endl; std::cerr << "Unhandled NiTextureEffect type " << textureEffect->textureType << " in " << mFilename << std::endl;
return; return;
} }
@ -487,7 +487,7 @@ namespace NifOsg
texGen->setMode(osg::TexGen::SPHERE_MAP); texGen->setMode(osg::TexGen::SPHERE_MAP);
break; break;
default: default:
std::cerr << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType << std::endl; std::cerr << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType << " in " << mFilename << std::endl;
return; return;
} }
@ -1374,17 +1374,15 @@ namespace NifOsg
case Nif::NiTexturingProperty::DarkTexture: case Nif::NiTexturingProperty::DarkTexture:
case Nif::NiTexturingProperty::BumpTexture: case Nif::NiTexturingProperty::BumpTexture:
case Nif::NiTexturingProperty::DetailTexture: case Nif::NiTexturingProperty::DetailTexture:
case Nif::NiTexturingProperty::DecalTexture:
break; break;
case Nif::NiTexturingProperty::GlossTexture: case Nif::NiTexturingProperty::GlossTexture:
{ {
// Not used by the vanilla engine. MCP (Morrowind Code Patch) adds an option to use Gloss maps:
// "- Gloss map fix. Morrowind removed gloss map entries from model files after loading them. This stops Morrowind from removing them."
std::cerr << "NiTexturingProperty::GlossTexture in " << mFilename << " not currently used." << std::endl; std::cerr << "NiTexturingProperty::GlossTexture in " << mFilename << " not currently used." << std::endl;
continue; continue;
} }
case Nif::NiTexturingProperty::DecalTexture:
{
std::cerr << "NiTexturingProperty::DecalTexture in " << mFilename << " not currently used." << std::endl;
continue;
}
default: default:
{ {
std::cerr << "Warning: unhandled texture stage " << i << " in " << mFilename << std::endl; std::cerr << "Warning: unhandled texture stage " << i << " in " << mFilename << std::endl;
@ -1435,16 +1433,16 @@ namespace NifOsg
{ {
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine; osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
texEnv->setScale_RGB(2.f); texEnv->setScale_RGB(2.f);
texEnv->setCombine_Alpha(GL_MODULATE); texEnv->setCombine_Alpha(osg::TexEnvCombine::MODULATE);
texEnv->setOperand0_Alpha(GL_SRC_ALPHA); texEnv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
texEnv->setOperand1_Alpha(GL_SRC_ALPHA); texEnv->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);
texEnv->setSource0_Alpha(GL_PREVIOUS_ARB); texEnv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
texEnv->setSource1_Alpha(GL_TEXTURE); texEnv->setSource1_Alpha(osg::TexEnvCombine::TEXTURE);
texEnv->setCombine_RGB(GL_MODULATE); texEnv->setCombine_RGB(osg::TexEnvCombine::MODULATE);
texEnv->setOperand0_RGB(GL_SRC_COLOR); texEnv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
texEnv->setOperand1_RGB(GL_SRC_COLOR); texEnv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
texEnv->setSource0_RGB(GL_PREVIOUS_ARB); texEnv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
texEnv->setSource1_RGB(GL_TEXTURE); texEnv->setSource1_RGB(osg::TexEnvCombine::TEXTURE);
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
} }
else if (i == Nif::NiTexturingProperty::BumpTexture) else if (i == Nif::NiTexturingProperty::BumpTexture)
@ -1452,6 +1450,21 @@ namespace NifOsg
// Set this texture to Off by default since we can't render it with the fixed-function pipeline // Set this texture to Off by default since we can't render it with the fixed-function pipeline
stateset->setTextureMode(texUnit, GL_TEXTURE_2D, osg::StateAttribute::OFF); stateset->setTextureMode(texUnit, GL_TEXTURE_2D, osg::StateAttribute::OFF);
} }
else if (i == Nif::NiTexturingProperty::DecalTexture)
{
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
texEnv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
texEnv->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
texEnv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
texEnv->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
texEnv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
texEnv->setSource2_RGB(osg::TexEnvCombine::TEXTURE);
texEnv->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);
texEnv->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
texEnv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
texEnv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
}
switch (i) switch (i)
{ {
@ -1470,6 +1483,9 @@ namespace NifOsg
case Nif::NiTexturingProperty::DetailTexture: case Nif::NiTexturingProperty::DetailTexture:
texture2d->setName("detailMap"); texture2d->setName("detailMap");
break; break;
case Nif::NiTexturingProperty::DecalTexture:
texture2d->setName("decalMap");
break;
default: default:
break; break;
} }

@ -13,6 +13,10 @@ namespace Resource
} }
ResourceManager::~ResourceManager()
{
}
void ResourceManager::updateCache(double referenceTime) void ResourceManager::updateCache(double referenceTime)
{ {
mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime); mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);

@ -18,6 +18,7 @@ namespace Resource
{ {
public: public:
ResourceManager(const VFS::Manager* vfs); ResourceManager(const VFS::Manager* vfs);
virtual ~ResourceManager();
/// Clear cache entries that have not been referenced for longer than expiryDelay. /// Clear cache entries that have not been referenced for longer than expiryDelay.
virtual void updateCache(double referenceTime); virtual void updateCache(double referenceTime);

@ -102,9 +102,15 @@ namespace SceneUtil
// Need to invert culling because of the negative scale // Need to invert culling because of the negative scale
// Note: for absolute correctness we would need to check the current front face for every mesh then invert it // Note: for absolute correctness we would need to check the current front face for every mesh then invert it
// However MW isn't doing this either, so don't. Assuming all meshes are using backface culling is more efficient. // However MW isn't doing this either, so don't. Assuming all meshes are using backface culling is more efficient.
static osg::ref_ptr<osg::StateSet> frontFaceStateSet;
if (!frontFaceStateSet)
{
frontFaceStateSet = new osg::StateSet;
osg::FrontFace* frontFace = new osg::FrontFace; osg::FrontFace* frontFace = new osg::FrontFace;
frontFace->setMode(osg::FrontFace::CLOCKWISE); frontFace->setMode(osg::FrontFace::CLOCKWISE);
trans->getOrCreateStateSet()->setAttributeAndModes(frontFace, osg::StateAttribute::ON); frontFaceStateSet->setAttributeAndModes(frontFace, osg::StateAttribute::ON);
}
trans->setStateSet(frontFaceStateSet);
} }
if (trans) if (trans)

@ -88,11 +88,11 @@ namespace Shader
return newStateSet.get(); return newStateSet.get();
} }
const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap", "specularMap" }; const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap", "specularMap", "decalMap" };
bool isTextureNameRecognized(const std::string& name) bool isTextureNameRecognized(const std::string& name)
{ {
for (unsigned int i=0; i<sizeof(defaultTextures)/sizeof(defaultTextures[0]); ++i) for (unsigned int i=0; i<sizeof(defaultTextures)/sizeof(defaultTextures[0]); ++i)
if (name.c_str() == defaultTextures[i]) if (name == defaultTextures[i])
return true; return true;
return false; return false;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

@ -80,6 +80,8 @@
<file alias="free-camera">flying eye.png</file> <file alias="free-camera">flying eye.png</file>
<file alias="orbiting-camera">orbit2.png</file> <file alias="orbiting-camera">orbit2.png</file>
<file alias="play">scene-play.png</file> <file alias="play">scene-play.png</file>
<file alias="grid">grid-view.png</file>
<file alias="grid-small">grid-view-small.png</file>
<file alias="scene-view-1">scene-view-references.png</file> <file alias="scene-view-1">scene-view-references.png</file>
<file alias="scene-view-16">scene-view-terrain.png</file> <file alias="scene-view-16">scene-view-terrain.png</file>
<file alias="scene-view-4">scene-view-water.png</file> <file alias="scene-view-4">scene-view-water.png</file>

@ -15,6 +15,11 @@ uniform sampler2D detailMap;
varying vec2 detailMapUV; varying vec2 detailMapUV;
#endif #endif
#if @decalMap
uniform sampler2D decalMap;
varying vec2 decalMapUV;
#endif
#if @emissiveMap #if @emissiveMap
uniform sampler2D emissiveMap; uniform sampler2D emissiveMap;
varying vec2 emissiveMapUV; varying vec2 emissiveMapUV;
@ -67,6 +72,11 @@ void main()
gl_FragData[0].xyz *= texture2D(darkMap, darkMapUV).xyz; gl_FragData[0].xyz *= texture2D(darkMap, darkMapUV).xyz;
#endif #endif
#if @decalMap
vec4 decalTex = texture2D(decalMap, decalMapUV);
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, decalTex.xyz, decalTex.a);
#endif
vec3 viewNormal = passViewNormal; vec3 viewNormal = passViewNormal;
#if @normalMap #if @normalMap

@ -12,6 +12,10 @@ varying vec2 darkMapUV;
varying vec2 detailMapUV; varying vec2 detailMapUV;
#endif #endif
#if @decalMap
varying vec2 decalMapUV;
#endif
#if @emissiveMap #if @emissiveMap
varying vec2 emissiveMapUV; varying vec2 emissiveMapUV;
#endif #endif
@ -68,7 +72,11 @@ void main(void)
#endif #endif
#if @detailMap #if @detailMap
detailMapUV = (gl_TextureMatrix[@detailMap] * gl_MultiTexCoord@detailMap).xy; detailMapUV = (gl_TextureMatrix[@detailMapUV] * gl_MultiTexCoord@detailMapUV).xy;
#endif
#if @decalMap
decalMapUV = (gl_TextureMatrix[@decalMapUV] * gl_MultiTexCoord@decalMapUV).xy;
#endif #endif
#if @emissiveMap #if @emissiveMap

Loading…
Cancel
Save