mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 17:09:41 +00:00
Handle BSTriShape basic geometry
This commit is contained in:
parent
af24d3fd3c
commit
0497fd111f
2 changed files with 99 additions and 4 deletions
|
@ -393,6 +393,8 @@ namespace Nif
|
|||
mShaderProperty.read(nif);
|
||||
mAlphaProperty.read(nif);
|
||||
mVertDesc.read(nif);
|
||||
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||
mVertDesc.mFlags |= BSVertexDesc::VertexAttribute::Full_Precision;
|
||||
|
||||
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
|
||||
mTriangles.resize(nif->get<uint32_t>() * 3);
|
||||
|
@ -464,10 +466,7 @@ namespace Nif
|
|||
|
||||
void BSVertexData::read(NIFStream* nif, uint16_t flags)
|
||||
{
|
||||
bool fullPrecision = true;
|
||||
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_SSE)
|
||||
fullPrecision = flags & BSVertexDesc::VertexAttribute::Full_Precision;
|
||||
|
||||
bool fullPrecision = flags & BSVertexDesc::VertexAttribute::Full_Precision;
|
||||
bool hasVertex = flags & BSVertexDesc::VertexAttribute::Vertex;
|
||||
bool hasTangent = flags & BSVertexDesc::VertexAttribute::Tangents;
|
||||
bool hasUV = flags & BSVertexDesc::VertexAttribute::UVs;
|
||||
|
|
|
@ -775,6 +775,8 @@ namespace NifOsg
|
|||
{
|
||||
if (isNiGeometry)
|
||||
handleNiGeometry(nifNode, parent, node, composite, args.mBoundTextures, args.mAnimFlags);
|
||||
else // isBSGeometry
|
||||
handleBSGeometry(nifNode, parent, node, composite, args.mBoundTextures, args.mAnimFlags);
|
||||
|
||||
if (!nifNode->mController.empty())
|
||||
handleMeshControllers(nifNode, node, composite, args.mBoundTextures, args.mAnimFlags);
|
||||
|
@ -1554,6 +1556,100 @@ namespace NifOsg
|
|||
parentNode->addChild(drawable);
|
||||
}
|
||||
|
||||
void handleBSGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
|
||||
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
|
||||
int animflags)
|
||||
{
|
||||
assert(isTypeBSGeometry(nifNode->recType));
|
||||
|
||||
auto bsTriShape = static_cast<const Nif::BSTriShape*>(nifNode);
|
||||
const std::vector<unsigned short>& triangles = bsTriShape->mTriangles;
|
||||
if (triangles.empty())
|
||||
return;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry);
|
||||
geometry->addPrimitiveSet(new osg::DrawElementsUShort(
|
||||
osg::PrimitiveSet::TRIANGLES, triangles.size(), triangles.data()));
|
||||
|
||||
auto normbyteToFloat = [](uint8_t value) { return value / 255.f * 2.f - 1.f; };
|
||||
auto halfToFloat = [](uint16_t value)
|
||||
{
|
||||
uint32_t bits = static_cast<uint32_t>(value & 0x8000) << 16;
|
||||
|
||||
const uint32_t exp16 = (value & 0x7c00) >> 10;
|
||||
uint32_t frac16 = value & 0x3ff;
|
||||
if (exp16)
|
||||
bits |= (exp16 + 0x70) << 23;
|
||||
else if (frac16)
|
||||
{
|
||||
uint8_t offset = 0;
|
||||
do
|
||||
{
|
||||
++offset;
|
||||
frac16 <<= 1;
|
||||
}
|
||||
while ((frac16 & 0x400) != 0x400);
|
||||
frac16 &= 0x3ff;
|
||||
bits |= (0x71 - offset) << 23;
|
||||
}
|
||||
bits |= frac16 << 13;
|
||||
|
||||
float result;
|
||||
std::memcpy(&result, &bits, sizeof(float));
|
||||
return result;
|
||||
};
|
||||
|
||||
const bool fullPrecision = bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::Full_Precision;
|
||||
const bool hasVertices = bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::Vertex;
|
||||
const bool hasNormals = bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::Normals;
|
||||
const bool hasColors = bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::Vertex_Colors;
|
||||
const bool hasUV = bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::UVs;
|
||||
|
||||
std::vector<osg::Vec3f> vertices;
|
||||
std::vector<osg::Vec3f> normals;
|
||||
std::vector<osg::Vec4ub> colors;
|
||||
std::vector<osg::Vec2f> uvlist;
|
||||
for (auto& elem : bsTriShape->mVertData)
|
||||
{
|
||||
if (hasVertices)
|
||||
{
|
||||
if (fullPrecision)
|
||||
vertices.emplace_back(elem.mVertex.x(), elem.mVertex.y(), elem.mVertex.z());
|
||||
else
|
||||
vertices.emplace_back(halfToFloat(elem.mHalfVertex[0]), halfToFloat(elem.mHalfVertex[1]), halfToFloat(elem.mHalfVertex[2]));
|
||||
}
|
||||
if (hasNormals)
|
||||
normals.emplace_back(normbyteToFloat(elem.mNormal[0]), normbyteToFloat(elem.mNormal[1]), normbyteToFloat(elem.mNormal[2]));
|
||||
if (hasColors)
|
||||
colors.emplace_back(elem.mVertColor[0], elem.mVertColor[1], elem.mVertColor[2], elem.mVertColor[3]);
|
||||
if (hasUV)
|
||||
uvlist.emplace_back(halfToFloat(elem.mUV[0]), 1.0 - halfToFloat(elem.mUV[1]));
|
||||
}
|
||||
|
||||
if (!vertices.empty())
|
||||
geometry->setVertexArray(new osg::Vec3Array(vertices.size(), vertices.data()));
|
||||
if (!normals.empty())
|
||||
geometry->setNormalArray(
|
||||
new osg::Vec3Array(normals.size(), normals.data()), osg::Array::BIND_PER_VERTEX);
|
||||
if (!colors.empty())
|
||||
geometry->setColorArray(
|
||||
new osg::Vec4ubArray(colors.size(), colors.data()), osg::Array::BIND_PER_VERTEX);
|
||||
if (!uvlist.empty())
|
||||
geometry->setTexCoordArray(0, new osg::Vec2Array(uvlist.size(), uvlist.data()),
|
||||
osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
std::vector<const Nif::NiProperty*> drawableProps;
|
||||
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||
if (!bsTriShape->mShaderProperty.empty())
|
||||
drawableProps.emplace_back(bsTriShape->mShaderProperty.getPtr());
|
||||
if (!bsTriShape->mAlphaProperty.empty())
|
||||
drawableProps.emplace_back(bsTriShape->mAlphaProperty.getPtr());
|
||||
applyDrawableProperties(parentNode, drawableProps, composite, !colors.empty(), animflags);
|
||||
|
||||
geometry->setName(nifNode->mName);
|
||||
parentNode->addChild(geometry);
|
||||
}
|
||||
|
||||
osg::BlendFunc::BlendFuncMode getBlendMode(int mode)
|
||||
{
|
||||
switch (mode)
|
||||
|
|
Loading…
Reference in a new issue