mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
Merge pull request #2883 from Capostrophic/nilines
Handle NiLines (feature #5445)
This commit is contained in:
commit
f5e2e53bcf
8 changed files with 101 additions and 24 deletions
|
@ -23,6 +23,7 @@
|
||||||
Bug #5435: Enemies can't hurt the player when collision is off
|
Bug #5435: Enemies can't hurt the player when collision is off
|
||||||
Bug #5441: Enemies can't push a player character when in critical strike stance
|
Bug #5441: Enemies can't push a player character when in critical strike stance
|
||||||
Feature #5362: Show the soul gems' trapped soul in count dialog
|
Feature #5362: Show the soul gems' trapped soul in count dialog
|
||||||
|
Feature #5445: Handle NiLines
|
||||||
|
|
||||||
0.46.0
|
0.46.0
|
||||||
------
|
------
|
||||||
|
|
|
@ -110,6 +110,32 @@ void NiTriStripsData::read(NIFStream *nif)
|
||||||
nif->getUShorts(strips[i], lengths[i]);
|
nif->getUShorts(strips[i], lengths[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NiLinesData::read(NIFStream *nif)
|
||||||
|
{
|
||||||
|
NiGeometryData::read(nif);
|
||||||
|
size_t num = vertices.size();
|
||||||
|
std::vector<char> flags;
|
||||||
|
nif->getChars(flags, num);
|
||||||
|
// Can't construct a line from a single vertex.
|
||||||
|
if (num < 2)
|
||||||
|
return;
|
||||||
|
// Convert connectivity flags into usable geometry. The last element needs special handling.
|
||||||
|
for (size_t i = 0; i < num-1; ++i)
|
||||||
|
{
|
||||||
|
if (flags[i] & 1)
|
||||||
|
{
|
||||||
|
lines.emplace_back(i);
|
||||||
|
lines.emplace_back(i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there are just two vertices, they can be connected twice. Probably isn't critical.
|
||||||
|
if (flags[num-1] & 1)
|
||||||
|
{
|
||||||
|
lines.emplace_back(num-1);
|
||||||
|
lines.emplace_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NiAutoNormalParticlesData::read(NIFStream *nif)
|
void NiAutoNormalParticlesData::read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
NiGeometryData::read(nif);
|
NiGeometryData::read(nif);
|
||||||
|
|
|
@ -62,6 +62,14 @@ public:
|
||||||
void read(NIFStream *nif);
|
void read(NIFStream *nif);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NiLinesData : public NiGeometryData
|
||||||
|
{
|
||||||
|
// Lines, series of indices that correspond to connected vertices.
|
||||||
|
std::vector<unsigned short> lines;
|
||||||
|
|
||||||
|
void read(NIFStream *nif);
|
||||||
|
};
|
||||||
|
|
||||||
class NiAutoNormalParticlesData : public NiGeometryData
|
class NiAutoNormalParticlesData : public NiGeometryData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -54,6 +54,7 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
|
||||||
newFactory.insert(makeEntry("NiBillboardNode", &construct <NiNode> , RC_NiBillboardNode ));
|
newFactory.insert(makeEntry("NiBillboardNode", &construct <NiNode> , RC_NiBillboardNode ));
|
||||||
newFactory.insert(makeEntry("NiTriShape", &construct <NiTriShape> , RC_NiTriShape ));
|
newFactory.insert(makeEntry("NiTriShape", &construct <NiTriShape> , RC_NiTriShape ));
|
||||||
newFactory.insert(makeEntry("NiTriStrips", &construct <NiTriStrips> , RC_NiTriStrips ));
|
newFactory.insert(makeEntry("NiTriStrips", &construct <NiTriStrips> , RC_NiTriStrips ));
|
||||||
|
newFactory.insert(makeEntry("NiLines", &construct <NiLines> , RC_NiLines ));
|
||||||
newFactory.insert(makeEntry("NiRotatingParticles", &construct <NiRotatingParticles> , RC_NiRotatingParticles ));
|
newFactory.insert(makeEntry("NiRotatingParticles", &construct <NiRotatingParticles> , RC_NiRotatingParticles ));
|
||||||
newFactory.insert(makeEntry("NiAutoNormalParticles", &construct <NiAutoNormalParticles> , RC_NiAutoNormalParticles ));
|
newFactory.insert(makeEntry("NiAutoNormalParticles", &construct <NiAutoNormalParticles> , RC_NiAutoNormalParticles ));
|
||||||
newFactory.insert(makeEntry("NiCamera", &construct <NiCamera> , RC_NiCamera ));
|
newFactory.insert(makeEntry("NiCamera", &construct <NiCamera> , RC_NiCamera ));
|
||||||
|
@ -97,6 +98,7 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
|
||||||
newFactory.insert(makeEntry("NiFloatData", &construct <NiFloatData> , RC_NiFloatData ));
|
newFactory.insert(makeEntry("NiFloatData", &construct <NiFloatData> , RC_NiFloatData ));
|
||||||
newFactory.insert(makeEntry("NiTriShapeData", &construct <NiTriShapeData> , RC_NiTriShapeData ));
|
newFactory.insert(makeEntry("NiTriShapeData", &construct <NiTriShapeData> , RC_NiTriShapeData ));
|
||||||
newFactory.insert(makeEntry("NiTriStripsData", &construct <NiTriStripsData> , RC_NiTriStripsData ));
|
newFactory.insert(makeEntry("NiTriStripsData", &construct <NiTriStripsData> , RC_NiTriStripsData ));
|
||||||
|
newFactory.insert(makeEntry("NiLinesData", &construct <NiLinesData> , RC_NiLinesData ));
|
||||||
newFactory.insert(makeEntry("NiVisData", &construct <NiVisData> , RC_NiVisData ));
|
newFactory.insert(makeEntry("NiVisData", &construct <NiVisData> , RC_NiVisData ));
|
||||||
newFactory.insert(makeEntry("NiColorData", &construct <NiColorData> , RC_NiColorData ));
|
newFactory.insert(makeEntry("NiColorData", &construct <NiColorData> , RC_NiColorData ));
|
||||||
newFactory.insert(makeEntry("NiPixelData", &construct <NiPixelData> , RC_NiPixelData ));
|
newFactory.insert(makeEntry("NiPixelData", &construct <NiPixelData> , RC_NiPixelData ));
|
||||||
|
|
|
@ -182,6 +182,26 @@ struct NiTriStrips : NiGeometry
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NiLines : NiGeometry
|
||||||
|
{
|
||||||
|
NiLinesDataPtr data;
|
||||||
|
|
||||||
|
void read(NIFStream *nif)
|
||||||
|
{
|
||||||
|
Node::read(nif);
|
||||||
|
data.read(nif);
|
||||||
|
skin.read(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
data.post(nif);
|
||||||
|
skin.post(nif);
|
||||||
|
if (!skin.empty())
|
||||||
|
nif->setUseSkinning(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct NiCamera : Node
|
struct NiCamera : Node
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,7 @@ enum RecordType
|
||||||
RC_NiCollisionSwitch,
|
RC_NiCollisionSwitch,
|
||||||
RC_NiTriShape,
|
RC_NiTriShape,
|
||||||
RC_NiTriStrips,
|
RC_NiTriStrips,
|
||||||
|
RC_NiLines,
|
||||||
RC_NiRotatingParticles,
|
RC_NiRotatingParticles,
|
||||||
RC_NiAutoNormalParticles,
|
RC_NiAutoNormalParticles,
|
||||||
RC_NiBSParticleNode,
|
RC_NiBSParticleNode,
|
||||||
|
@ -83,6 +84,7 @@ enum RecordType
|
||||||
RC_NiFloatData,
|
RC_NiFloatData,
|
||||||
RC_NiTriShapeData,
|
RC_NiTriShapeData,
|
||||||
RC_NiTriStripsData,
|
RC_NiTriStripsData,
|
||||||
|
RC_NiLinesData,
|
||||||
RC_NiVisData,
|
RC_NiVisData,
|
||||||
RC_NiColorData,
|
RC_NiColorData,
|
||||||
RC_NiPixelData,
|
RC_NiPixelData,
|
||||||
|
|
|
@ -142,6 +142,7 @@ class NiRotatingParticlesData;
|
||||||
class NiAutoNormalParticlesData;
|
class NiAutoNormalParticlesData;
|
||||||
class NiPalette;
|
class NiPalette;
|
||||||
struct NiParticleModifier;
|
struct NiParticleModifier;
|
||||||
|
struct NiLinesData;
|
||||||
|
|
||||||
using NodePtr = RecordPtrT<Node>;
|
using NodePtr = RecordPtrT<Node>;
|
||||||
using ExtraPtr = RecordPtrT<Extra>;
|
using ExtraPtr = RecordPtrT<Extra>;
|
||||||
|
@ -158,6 +159,7 @@ using NiColorDataPtr = RecordPtrT<NiColorData>;
|
||||||
using NiKeyframeDataPtr = RecordPtrT<NiKeyframeData>;
|
using NiKeyframeDataPtr = RecordPtrT<NiKeyframeData>;
|
||||||
using NiTriShapeDataPtr = RecordPtrT<NiTriShapeData>;
|
using NiTriShapeDataPtr = RecordPtrT<NiTriShapeData>;
|
||||||
using NiTriStripsDataPtr = RecordPtrT<NiTriStripsData>;
|
using NiTriStripsDataPtr = RecordPtrT<NiTriStripsData>;
|
||||||
|
using NiLinesDataPtr = RecordPtrT<NiLinesData>;
|
||||||
using NiSkinInstancePtr = RecordPtrT<NiSkinInstance>;
|
using NiSkinInstancePtr = RecordPtrT<NiSkinInstance>;
|
||||||
using NiSourceTexturePtr = RecordPtrT<NiSourceTexture>;
|
using NiSourceTexturePtr = RecordPtrT<NiSourceTexture>;
|
||||||
using NiRotatingParticlesDataPtr = RecordPtrT<NiRotatingParticlesData>;
|
using NiRotatingParticlesDataPtr = RecordPtrT<NiRotatingParticlesData>;
|
||||||
|
|
|
@ -612,7 +612,9 @@ namespace NifOsg
|
||||||
|
|
||||||
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
|
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
|
||||||
|
|
||||||
if ((nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips) && !skipMeshes)
|
const bool isGeometry = nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines;
|
||||||
|
|
||||||
|
if (isGeometry && !skipMeshes)
|
||||||
{
|
{
|
||||||
const std::string nodeName = Misc::StringUtils::lowerCase(nifNode->name);
|
const std::string nodeName = Misc::StringUtils::lowerCase(nifNode->name);
|
||||||
static const std::string markerName = "tri editormarker";
|
static const std::string markerName = "tri editormarker";
|
||||||
|
@ -624,9 +626,9 @@ namespace NifOsg
|
||||||
Nif::NiSkinInstancePtr skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin;
|
Nif::NiSkinInstancePtr skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin;
|
||||||
|
|
||||||
if (skin.empty())
|
if (skin.empty())
|
||||||
handleTriShape(nifNode, node, composite, boundTextures, animflags);
|
handleGeometry(nifNode, node, composite, boundTextures, animflags);
|
||||||
else
|
else
|
||||||
handleSkinnedTriShape(nifNode, node, composite, boundTextures, animflags);
|
handleSkinnedGeometry(nifNode, node, composite, boundTextures, animflags);
|
||||||
|
|
||||||
if (!nifNode->controller.empty())
|
if (!nifNode->controller.empty())
|
||||||
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
|
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
|
||||||
|
@ -1099,8 +1101,11 @@ namespace NifOsg
|
||||||
partsys->getOrCreateStateSet();
|
partsys->getOrCreateStateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void triCommonToGeometry(osg::Geometry *geometry, const std::vector<osg::Vec3f>& vertices, const std::vector<osg::Vec3f>& normals, const std::vector<std::vector<osg::Vec2f>>& uvlist, const std::vector<osg::Vec4f>& colors, const std::vector<unsigned int>& boundTextures, const std::string& name)
|
void handleNiGeometryData(osg::Geometry *geometry, const Nif::NiGeometryData* data, const std::vector<unsigned int>& boundTextures, const std::string& name)
|
||||||
{
|
{
|
||||||
|
const auto& vertices = data->vertices;
|
||||||
|
const auto& normals = data->normals;
|
||||||
|
const auto& colors = data->colors;
|
||||||
if (!vertices.empty())
|
if (!vertices.empty())
|
||||||
geometry->setVertexArray(new osg::Vec3Array(vertices.size(), vertices.data()));
|
geometry->setVertexArray(new osg::Vec3Array(vertices.size(), vertices.data()));
|
||||||
if (!normals.empty())
|
if (!normals.empty())
|
||||||
|
@ -1108,6 +1113,7 @@ namespace NifOsg
|
||||||
if (!colors.empty())
|
if (!colors.empty())
|
||||||
geometry->setColorArray(new osg::Vec4Array(colors.size(), colors.data()), osg::Array::BIND_PER_VERTEX);
|
geometry->setColorArray(new osg::Vec4Array(colors.size(), colors.data()), osg::Array::BIND_PER_VERTEX);
|
||||||
|
|
||||||
|
const auto& uvlist = data->uvlist;
|
||||||
int textureStage = 0;
|
int textureStage = 0;
|
||||||
for (const unsigned int uvSet : boundTextures)
|
for (const unsigned int uvSet : boundTextures)
|
||||||
{
|
{
|
||||||
|
@ -1124,43 +1130,53 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void triShapeToGeometry(const Nif::Node *nifNode, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
void handleNiGeometry(const Nif::Node *nifNode, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
bool vertexColorsPresent = false;
|
const Nif::NiGeometryData* niGeometryData = nullptr;
|
||||||
if (nifNode->recType == Nif::RC_NiTriShape)
|
if (nifNode->recType == Nif::RC_NiTriShape)
|
||||||
{
|
{
|
||||||
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
|
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
|
||||||
if (!triShape->data.empty())
|
if (!triShape->data.empty())
|
||||||
{
|
{
|
||||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||||
vertexColorsPresent = !data->colors.empty();
|
niGeometryData = static_cast<const Nif::NiGeometryData*>(data);
|
||||||
triCommonToGeometry(geometry, data->vertices, data->normals, data->uvlist, data->colors, boundTextures, triShape->name);
|
|
||||||
if (!data->triangles.empty())
|
if (!data->triangles.empty())
|
||||||
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, data->triangles.size(),
|
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, data->triangles.size(),
|
||||||
(unsigned short*)data->triangles.data()));
|
(unsigned short*)data->triangles.data()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (nifNode->recType == Nif::RC_NiTriStrips)
|
||||||
{
|
{
|
||||||
const Nif::NiTriStrips* triStrips = static_cast<const Nif::NiTriStrips*>(nifNode);
|
const Nif::NiTriStrips* triStrips = static_cast<const Nif::NiTriStrips*>(nifNode);
|
||||||
if (!triStrips->data.empty())
|
if (!triStrips->data.empty())
|
||||||
{
|
{
|
||||||
const Nif::NiTriStripsData* data = triStrips->data.getPtr();
|
const Nif::NiTriStripsData* data = triStrips->data.getPtr();
|
||||||
vertexColorsPresent = !data->colors.empty();
|
niGeometryData = static_cast<const Nif::NiGeometryData*>(data);
|
||||||
triCommonToGeometry(geometry, data->vertices, data->normals, data->uvlist, data->colors, boundTextures, triStrips->name);
|
|
||||||
if (!data->strips.empty())
|
if (!data->strips.empty())
|
||||||
{
|
{
|
||||||
for (const std::vector<unsigned short>& strip : data->strips)
|
for (const auto& strip : data->strips)
|
||||||
{
|
{
|
||||||
// Can't make a triangle from less than three vertices.
|
if (strip.size() >= 3)
|
||||||
if (strip.size() < 3)
|
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
|
||||||
continue;
|
(unsigned short*)strip.data()));
|
||||||
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
|
|
||||||
(unsigned short*)strip.data()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (nifNode->recType == Nif::RC_NiLines)
|
||||||
|
{
|
||||||
|
const Nif::NiLines* lines = static_cast<const Nif::NiLines*>(nifNode);
|
||||||
|
if (!lines->data.empty())
|
||||||
|
{
|
||||||
|
const Nif::NiLinesData* data = lines->data.getPtr();
|
||||||
|
niGeometryData = static_cast<const Nif::NiGeometryData*>(data);
|
||||||
|
const auto& line = data->lines;
|
||||||
|
if (!line.empty())
|
||||||
|
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, line.size(), (unsigned short*)line.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (niGeometryData)
|
||||||
|
handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->name);
|
||||||
|
|
||||||
// osg::Material properties are handled here for two reasons:
|
// osg::Material properties are handled here for two reasons:
|
||||||
// - if there are no vertex colors, we need to disable colorMode.
|
// - if there are no vertex colors, we need to disable colorMode.
|
||||||
|
@ -1168,15 +1184,15 @@ namespace NifOsg
|
||||||
// above the actual renderable would be tedious.
|
// above the actual renderable would be tedious.
|
||||||
std::vector<const Nif::Property*> drawableProps;
|
std::vector<const Nif::Property*> drawableProps;
|
||||||
collectDrawableProperties(nifNode, drawableProps);
|
collectDrawableProperties(nifNode, drawableProps);
|
||||||
applyDrawableProperties(parentNode, drawableProps, composite, vertexColorsPresent, animflags);
|
applyDrawableProperties(parentNode, drawableProps, composite, niGeometryData && !niGeometryData->colors.empty(), animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleTriShape(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
void handleGeometry(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips);
|
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines);
|
||||||
osg::ref_ptr<osg::Drawable> drawable;
|
osg::ref_ptr<osg::Drawable> drawable;
|
||||||
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
|
||||||
triShapeToGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags);
|
handleNiGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags);
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
@ -1215,12 +1231,12 @@ namespace NifOsg
|
||||||
return morphGeom;
|
return morphGeom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSkinnedTriShape(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
void handleSkinnedGeometry(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
||||||
const std::vector<unsigned int>& boundTextures, int animflags)
|
const std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips);
|
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines);
|
||||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
triShapeToGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags);
|
handleNiGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags);
|
||||||
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||||
rig->setSourceGeometry(geometry);
|
rig->setSourceGeometry(geometry);
|
||||||
rig->setName(nifNode->name);
|
rig->setName(nifNode->name);
|
||||||
|
|
Loading…
Reference in a new issue