Handle BSTriShape basic geometry

macos_ci_fix
Alexei Kotov 1 year ago
parent af24d3fd3c
commit 0497fd111f

@ -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…
Cancel
Save