Flipped the MESH_ENABLED switch. Added missing components and updated stuff to be closer to mesh-development head.
This commit is contained in:
@@ -26,15 +26,20 @@
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#if MESH_ENABLED
|
||||
#include "llmodel.h"
|
||||
#if MESH_IMPORT
|
||||
#include "llconvexdecomposition.h"
|
||||
#endif //MESH_IMPORT
|
||||
#include "llsdserialize.h"
|
||||
#include "llvector4a.h"
|
||||
|
||||
#if MESH_IMPORT
|
||||
#include "dae.h"
|
||||
#include "dae/daeErrorHandler.h"
|
||||
#include "dom/domConstants.h"
|
||||
#include "dom/domMesh.h"
|
||||
#endif //MESH_IMPORT
|
||||
|
||||
#ifdef LL_STANDALONE
|
||||
# include <zlib.h>
|
||||
@@ -67,87 +72,13 @@ LLModel::~LLModel()
|
||||
{
|
||||
if (mDecompID >= 0)
|
||||
{
|
||||
#if MESH_IMPORT
|
||||
LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
|
||||
#endif //MESH_IMPORT
|
||||
}
|
||||
}
|
||||
|
||||
void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Array& inputs, U32 min_idx, U32 max_idx)
|
||||
{
|
||||
for (U32 j = 0; j < inputs.getCount(); ++j)
|
||||
{
|
||||
if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
|
||||
{ //found vertex array
|
||||
const domURIFragmentType& uri = inputs[j]->getSource();
|
||||
daeElementRef elem = uri.getElement();
|
||||
domVertices* vertices = (domVertices*) elem.cast();
|
||||
|
||||
domInputLocal_Array& v_inp = vertices->getInput_array();
|
||||
if (inputs[j]->getOffset() != 0)
|
||||
{
|
||||
llerrs << "Vertex array offset MUST be zero." << llendl;
|
||||
}
|
||||
|
||||
for (U32 k = 0; k < v_inp.getCount(); ++k)
|
||||
{
|
||||
if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
|
||||
{
|
||||
const domURIFragmentType& uri = v_inp[k]->getSource();
|
||||
|
||||
daeElementRef elem = uri.getElement();
|
||||
domSource* src = (domSource*) elem.cast();
|
||||
|
||||
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
|
||||
{
|
||||
llerrs << "Vertex array stride MUST be three." << llendl;
|
||||
}
|
||||
|
||||
domListOfFloats& v = src->getFloat_array()->getValue();
|
||||
|
||||
LLVector4a min;
|
||||
min.set(v[min_idx], v[min_idx+1], v[min_idx+2]);
|
||||
LLVector4a max = min;
|
||||
|
||||
for (U32 j = min_idx; j <= max_idx; ++j)
|
||||
{ //copy vertex array
|
||||
face.mPositions[j-min_idx].set(v[j*3+0], v[j*3+1], v[j*3+2]);
|
||||
update_min_max(min, max, face.mPositions[j-min_idx]);
|
||||
}
|
||||
|
||||
face.mExtents[0] = min;
|
||||
face.mExtents[1] = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
|
||||
{
|
||||
//found normal array for this triangle list
|
||||
const domURIFragmentType& uri = inputs[j]->getSource();
|
||||
daeElementRef elem = uri.getElement();
|
||||
domSource* src = (domSource*) elem.cast();
|
||||
domListOfFloats& n = src->getFloat_array()->getValue();
|
||||
|
||||
for (U32 j = min_idx; j <= max_idx; ++j)
|
||||
{
|
||||
LLVector4a* norm = (LLVector4a*) face.mNormals + (j-min_idx);
|
||||
norm->set(n[j*3+0], n[j*3+1], n[j*3+2]);
|
||||
norm->normalize3();
|
||||
}
|
||||
}
|
||||
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
|
||||
{ //found texCoords
|
||||
const domURIFragmentType& uri = inputs[j]->getSource();
|
||||
daeElementRef elem = uri.getElement();
|
||||
domSource* src = (domSource*) elem.cast();
|
||||
domListOfFloats& u = src->getFloat_array()->getValue();
|
||||
|
||||
for (U32 j = min_idx; j <= max_idx; ++j)
|
||||
{
|
||||
face.mTexCoords[j-min_idx].setVec(u[j*2+0], u[j*2+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if MESH_IMPORT
|
||||
|
||||
bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
|
||||
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
|
||||
@@ -329,6 +260,19 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
|
||||
{
|
||||
face_list.push_back(face);
|
||||
face_list.rbegin()->fillFromLegacyData(verts, indices);
|
||||
LLVolumeFace& new_face = *face_list.rbegin();
|
||||
if (!norm_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mNormals);
|
||||
new_face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (!tc_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
|
||||
face = LLVolumeFace();
|
||||
point_map.clear();
|
||||
}
|
||||
@@ -348,6 +292,18 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
|
||||
face_list.push_back(face);
|
||||
|
||||
face_list.rbegin()->fillFromLegacyData(verts, indices);
|
||||
LLVolumeFace& new_face = *face_list.rbegin();
|
||||
if (!norm_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mNormals);
|
||||
new_face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (!tc_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return LLModel::NO_ERRORS ;
|
||||
@@ -524,6 +480,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
|
||||
{
|
||||
face_list.push_back(face);
|
||||
face_list.rbegin()->fillFromLegacyData(verts, indices);
|
||||
LLVolumeFace& new_face = *face_list.rbegin();
|
||||
if (!norm_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mNormals);
|
||||
new_face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (!tc_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
|
||||
face = LLVolumeFace();
|
||||
verts.clear();
|
||||
indices.clear();
|
||||
@@ -544,6 +513,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
|
||||
materials.push_back(material);
|
||||
face_list.push_back(face);
|
||||
face_list.rbegin()->fillFromLegacyData(verts, indices);
|
||||
|
||||
LLVolumeFace& new_face = *face_list.rbegin();
|
||||
if (!norm_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mNormals);
|
||||
new_face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (!tc_source)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return LLModel::NO_ERRORS ;
|
||||
@@ -733,6 +715,19 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
|
||||
materials.push_back(material);
|
||||
face_list.push_back(face);
|
||||
face_list.rbegin()->fillFromLegacyData(new_verts, indices);
|
||||
|
||||
LLVolumeFace& new_face = *face_list.rbegin();
|
||||
if (!n)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mNormals);
|
||||
new_face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (!t)
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return LLModel::NO_ERRORS ;
|
||||
@@ -817,9 +812,9 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
|
||||
|
||||
if (getNumVolumeFaces() > 0)
|
||||
{
|
||||
optimizeVolumeFaces();
|
||||
normalizeVolumeFaces();
|
||||
|
||||
optimizeVolumeFaces();
|
||||
|
||||
if (getNumVolumeFaces() > 0)
|
||||
{
|
||||
return TRUE;
|
||||
@@ -833,6 +828,7 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif //MESH_IMPORT
|
||||
|
||||
void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
||||
{
|
||||
@@ -844,7 +840,7 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
||||
LLVolumeFace& face = *currentFaceIt;
|
||||
LLVector4a *pos = (LLVector4a*) face.mPositions;
|
||||
|
||||
for (U32 i=0; i<face.mNumVertices; ++i )
|
||||
for (U32 i=0; i< (U32)face.mNumVertices; ++i )
|
||||
{
|
||||
pos[i].add( pivot );
|
||||
}
|
||||
@@ -853,81 +849,10 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
||||
|
||||
void LLModel::optimizeVolumeFaces()
|
||||
{
|
||||
#if 0 //VECTORIZE ?
|
||||
for (std::vector<LLVolumeFace>::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); )
|
||||
for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i)
|
||||
{
|
||||
std::vector<LLVolumeFace>::iterator cur_iter = iter++;
|
||||
LLVolumeFace& face = *cur_iter;
|
||||
|
||||
for (S32 i = 0; i < (S32) face.mNumIndices; i += 3)
|
||||
{ //remove zero area triangles
|
||||
U16 i0 = face.mIndices[i+0];
|
||||
U16 i1 = face.mIndices[i+1];
|
||||
U16 i2 = face.mIndices[i+2];
|
||||
|
||||
if (i0 == i1 ||
|
||||
i1 == i2 ||
|
||||
i0 == i2)
|
||||
{ //duplicate index in triangle, remove triangle
|
||||
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
|
||||
i -= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVolumeFace::VertexData& v0 = face.mVertices[i0];
|
||||
LLVolumeFace::VertexData& v1 = face.mVertices[i1];
|
||||
LLVolumeFace::VertexData& v2 = face.mVertices[i2];
|
||||
|
||||
if (v0.mPosition == v1.mPosition ||
|
||||
v1.mPosition == v2.mPosition ||
|
||||
v2.mPosition == v0.mPosition)
|
||||
{ //zero area triangle, delete
|
||||
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
|
||||
i-=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remove unreference vertices
|
||||
std::vector<bool> ref;
|
||||
ref.resize(face.mNumVertices);
|
||||
|
||||
for (U32 i = 0; i < ref.size(); ++i)
|
||||
{
|
||||
ref[i] = false;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
ref[face.mIndices[i]] = true;
|
||||
}
|
||||
|
||||
U32 unref_count = 0;
|
||||
for (U32 i = 0; i < ref.size(); ++i)
|
||||
{
|
||||
if (!ref[i])
|
||||
{
|
||||
//vertex is unreferenced
|
||||
face.mVertices.erase(face.mVertices.begin()+(i-unref_count));
|
||||
U16 idx = (U16) (i-unref_count);
|
||||
|
||||
for (U32 j = 0; j < face.mNumIndices; ++j)
|
||||
{ //decrement every index array value greater than idx
|
||||
if (face.mIndices[j] > idx)
|
||||
{
|
||||
--face.mIndices[j];
|
||||
}
|
||||
}
|
||||
++unref_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (face.mVertices.empty() || face.mIndices.empty())
|
||||
{ //face is empty, remove it
|
||||
iter = mVolumeFaces.erase(cur_iter);
|
||||
}
|
||||
mVolumeFaces[i].optimize();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Shrink the model to fit
|
||||
@@ -962,6 +887,25 @@ void LLModel::normalizeVolumeFaces()
|
||||
|
||||
update_min_max(min, max, face.mExtents[0]);
|
||||
update_min_max(min, max, face.mExtents[1]);
|
||||
|
||||
if (face.mTexCoords)
|
||||
{
|
||||
LLVector2& min_tc = face.mTexCoordExtents[0];
|
||||
LLVector2& max_tc = face.mTexCoordExtents[1];
|
||||
|
||||
min_tc = face.mTexCoords[0];
|
||||
max_tc = face.mTexCoords[0];
|
||||
|
||||
for (U32 j = 1; j < (U32)face.mNumVertices; ++j)
|
||||
{
|
||||
update_min_max(min_tc, max_tc, face.mTexCoords[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
face.mTexCoordExtents[0].set(0,0);
|
||||
face.mTexCoordExtents[1].set(1,1);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the extents of the model
|
||||
@@ -1025,12 +969,15 @@ void LLModel::normalizeVolumeFaces()
|
||||
LLVector4a* pos = (LLVector4a*) face.mPositions;
|
||||
LLVector4a* norm = (LLVector4a*) face.mNormals;
|
||||
|
||||
for (U32 j = 0; j < face.mNumVertices; ++j)
|
||||
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
|
||||
{
|
||||
pos[j].add(trans);
|
||||
pos[j].mul(scale);
|
||||
norm[j].mul(inv_scale);
|
||||
norm[j].normalize3();
|
||||
if (norm && !norm[j].equals3(LLVector4a::getZero()))
|
||||
{
|
||||
norm[j].mul(inv_scale);
|
||||
norm[j].normalize3();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,8 +1020,26 @@ void LLModel::setVolumeFaceData(
|
||||
face.resizeIndices(num_indices);
|
||||
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
|
||||
if (norm.get())
|
||||
{
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(face.mNormals);
|
||||
face.mNormals = NULL;
|
||||
}
|
||||
|
||||
if (tc.get())
|
||||
{
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(face.mTexCoords);
|
||||
face.mTexCoords = NULL;
|
||||
}
|
||||
|
||||
U32 size = (num_indices*2+0xF)&~0xF;
|
||||
LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
|
||||
}
|
||||
@@ -1160,7 +1125,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
faceted.resizeVertices(vol_face.mNumIndices);
|
||||
faceted.resizeIndices(vol_face.mNumIndices);
|
||||
//bake out triangles into temporary face, clearing texture coordinates
|
||||
for (U32 i = 0; i < vol_face.mNumIndices; ++i)
|
||||
for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i)
|
||||
{
|
||||
U32 idx = vol_face.mIndices[i];
|
||||
|
||||
@@ -1170,7 +1135,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
}
|
||||
|
||||
//generate normals for temporary face
|
||||
for (U32 i = 0; i < faceted.mNumIndices; i += 3)
|
||||
for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3)
|
||||
{ //for each triangle
|
||||
U16 i0 = faceted.mIndices[i+0];
|
||||
U16 i1 = faceted.mIndices[i+1];
|
||||
@@ -1199,12 +1164,12 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
|
||||
//generate normals for welded face based on new topology (step 3)
|
||||
|
||||
for (U32 i = 0; i < faceted.mNumVertices; i++)
|
||||
for (U32 i = 0; i < (U32)faceted.mNumVertices; i++)
|
||||
{
|
||||
faceted.mNormals[i].clear();
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < faceted.mNumIndices; i += 3)
|
||||
for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3)
|
||||
{ //for each triangle
|
||||
U16 i0 = faceted.mIndices[i+0];
|
||||
U16 i1 = faceted.mIndices[i+1];
|
||||
@@ -1233,7 +1198,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
//normalize normals and build point map
|
||||
LLVolumeFace::VertexMapData::PointMap point_map;
|
||||
|
||||
for (U32 i = 0; i < faceted.mNumVertices; ++i)
|
||||
for (U32 i = 0; i < (U32)faceted.mNumVertices; ++i)
|
||||
{
|
||||
faceted.mNormals[i].normalize3();
|
||||
|
||||
@@ -1251,18 +1216,31 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
new_face.resizeIndices(vol_face.mNumIndices);
|
||||
new_face.resizeVertices(vol_face.mNumIndices);
|
||||
|
||||
for (U32 i = 0; i < vol_face.mNumIndices; ++i)
|
||||
for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i)
|
||||
{
|
||||
U32 idx = vol_face.mIndices[i];
|
||||
LLVolumeFace::VertexData v;
|
||||
new_face.mPositions[i] = vol_face.mPositions[idx];
|
||||
new_face.mNormals[i].clear();
|
||||
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
|
||||
new_face.mIndices[i] = i;
|
||||
}
|
||||
|
||||
if (vol_face.mTexCoords)
|
||||
{
|
||||
for (U32 i = 0; i < (U32)vol_face.mNumIndices; i++)
|
||||
{
|
||||
U32 idx = vol_face.mIndices[i];
|
||||
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(new_face.mTexCoords);
|
||||
new_face.mTexCoords = NULL;
|
||||
}
|
||||
|
||||
//generate normals for new face
|
||||
for (U32 i = 0; i < new_face.mNumIndices; i += 3)
|
||||
for (U32 i = 0; i < (U32)new_face.mNumIndices; i += 3)
|
||||
{ //for each triangle
|
||||
U16 i0 = new_face.mIndices[i+0];
|
||||
U16 i1 = new_face.mIndices[i+1];
|
||||
@@ -1287,7 +1265,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
}
|
||||
|
||||
//swap out normals in new_face with best match from point map (step 5)
|
||||
for (U32 i = 0; i < new_face.mNumVertices; ++i)
|
||||
for (U32 i = 0; i < (U32)new_face.mNumVertices; ++i)
|
||||
{
|
||||
//LLVolumeFace::VertexData v = new_face.mVertices[i];
|
||||
|
||||
@@ -1320,6 +1298,8 @@ void LLModel::generateNormals(F32 angle_cutoff)
|
||||
}
|
||||
}
|
||||
|
||||
#if MESH_IMPORT
|
||||
|
||||
//static
|
||||
std::string LLModel::getElementLabel(daeElement *element)
|
||||
{ // try to get a decent label for this element
|
||||
@@ -1375,6 +1355,7 @@ LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
|
||||
ret->mLabel = getElementLabel(mesh);
|
||||
return ret;
|
||||
}
|
||||
#endif MESH_IMPORT
|
||||
|
||||
std::string LLModel::getName() const
|
||||
{
|
||||
@@ -1395,7 +1376,8 @@ LLSD LLModel::writeModel(
|
||||
const LLModel::Decomposition& decomp,
|
||||
BOOL upload_skin,
|
||||
BOOL upload_joints,
|
||||
BOOL nowrite)
|
||||
BOOL nowrite,
|
||||
BOOL as_slm)
|
||||
{
|
||||
LLSD mdl;
|
||||
|
||||
@@ -1419,12 +1401,20 @@ LLSD LLModel::writeModel(
|
||||
!decomp.mHull.empty())
|
||||
{
|
||||
mdl["physics_convex"] = decomp.asLLSD();
|
||||
if (!decomp.mHull.empty())
|
||||
{ //convex decomposition exists, physics mesh will not be used
|
||||
if (!decomp.mHull.empty() && !as_slm)
|
||||
{ //convex decomposition exists, physics mesh will not be used (unless this is an slm file)
|
||||
model[LLModel::LOD_PHYSICS] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (as_slm)
|
||||
{ //save material list names
|
||||
for (U32 i = 0; i < high->mMaterialList.size(); ++i)
|
||||
{
|
||||
mdl["material_list"][i] = high->mMaterialList[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
|
||||
{
|
||||
if (model[idx] && model[idx]->getNumVolumeFaces() > 0)
|
||||
@@ -1436,7 +1426,7 @@ LLSD LLModel::writeModel(
|
||||
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
|
||||
{ //for each face
|
||||
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
|
||||
for (U32 j = 0; j < face.mNumVertices; ++j)
|
||||
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
|
||||
{
|
||||
update_min_max(min_pos, max_pos, face.mPositions[j].getF32ptr());
|
||||
}
|
||||
@@ -1462,24 +1452,30 @@ LLSD LLModel::writeModel(
|
||||
U32 tc_idx = 0;
|
||||
|
||||
LLVector2* ftc = (LLVector2*) face.mTexCoords;
|
||||
LLVector2 min_tc = ftc[0];
|
||||
LLVector2 max_tc = min_tc;
|
||||
|
||||
//get texture coordinate domain
|
||||
for (U32 j = 0; j < face.mNumVertices; ++j)
|
||||
LLVector2 min_tc;
|
||||
LLVector2 max_tc;
|
||||
|
||||
if (ftc)
|
||||
{
|
||||
update_min_max(min_tc, max_tc, ftc[j]);
|
||||
min_tc = ftc[0];
|
||||
max_tc = min_tc;
|
||||
|
||||
//get texture coordinate domain
|
||||
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
|
||||
{
|
||||
update_min_max(min_tc, max_tc, ftc[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLVector2 tc_range = max_tc - min_tc;
|
||||
|
||||
for (U32 j = 0; j < face.mNumVertices; ++j)
|
||||
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
|
||||
{ //for each vert
|
||||
|
||||
F32* pos = face.mPositions[j].getF32ptr();
|
||||
F32* norm = face.mNormals[j].getF32ptr();
|
||||
|
||||
//position + normal
|
||||
|
||||
//position
|
||||
for (U32 k = 0; k < 3; ++k)
|
||||
{ //for each component
|
||||
//convert to 16-bit normalized across domain
|
||||
@@ -1489,33 +1485,44 @@ LLSD LLModel::writeModel(
|
||||
//write to binary buffer
|
||||
verts[vert_idx++] = buff[0];
|
||||
verts[vert_idx++] = buff[1];
|
||||
|
||||
//convert to 16-bit normalized
|
||||
val = (U16) ((norm[k]+1.f)*0.5f*65535);
|
||||
|
||||
//write to binary buffer
|
||||
normals[norm_idx++] = buff[0];
|
||||
normals[norm_idx++] = buff[1];
|
||||
}
|
||||
|
||||
if (face.mNormals)
|
||||
{ //normals
|
||||
F32* norm = face.mNormals[j].getF32ptr();
|
||||
|
||||
for (U32 k = 0; k < 3; ++k)
|
||||
{ //for each component
|
||||
//convert to 16-bit normalized
|
||||
U16 val = (U16) ((norm[k]+1.f)*0.5f*65535);
|
||||
U8* buff = (U8*) &val;
|
||||
|
||||
//write to binary buffer
|
||||
normals[norm_idx++] = buff[0];
|
||||
normals[norm_idx++] = buff[1];
|
||||
}
|
||||
}
|
||||
|
||||
F32* src_tc = (F32*) face.mTexCoords[j].mV;
|
||||
|
||||
//texcoord
|
||||
for (U32 k = 0; k < 2; ++k)
|
||||
{ //for each component
|
||||
//convert to 16-bit normalized
|
||||
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
|
||||
if (face.mTexCoords)
|
||||
{
|
||||
for (U32 k = 0; k < 2; ++k)
|
||||
{ //for each component
|
||||
//convert to 16-bit normalized
|
||||
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
|
||||
|
||||
U8* buff = (U8*) &val;
|
||||
//write to binary buffer
|
||||
tc[tc_idx++] = buff[0];
|
||||
tc[tc_idx++] = buff[1];
|
||||
U8* buff = (U8*) &val;
|
||||
//write to binary buffer
|
||||
tc[tc_idx++] = buff[0];
|
||||
tc[tc_idx++] = buff[1];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
U32 idx_idx = 0;
|
||||
for (U32 j = 0; j < face.mNumIndices; ++j)
|
||||
for (U32 j = 0; j < (U32)face.mNumIndices; ++j)
|
||||
{
|
||||
U8* buff = (U8*) &(face.mIndices[j]);
|
||||
indices[idx_idx++] = buff[0];
|
||||
@@ -1525,12 +1532,19 @@ LLSD LLModel::writeModel(
|
||||
//write out face data
|
||||
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
|
||||
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
|
||||
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
|
||||
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
|
||||
|
||||
mdl[model_names[idx]][i]["Position"] = verts;
|
||||
mdl[model_names[idx]][i]["Normal"] = normals;
|
||||
mdl[model_names[idx]][i]["TexCoord0"] = tc;
|
||||
|
||||
if (face.mNormals)
|
||||
{
|
||||
mdl[model_names[idx]][i]["Normal"] = normals;
|
||||
}
|
||||
|
||||
if (face.mTexCoords)
|
||||
{
|
||||
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
|
||||
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
|
||||
mdl[model_names[idx]][i]["TexCoord0"] = tc;
|
||||
}
|
||||
mdl[model_names[idx]][i]["TriangleList"] = indices;
|
||||
|
||||
if (skinning)
|
||||
@@ -1544,7 +1558,7 @@ LLSD LLModel::writeModel(
|
||||
|
||||
std::stringstream ostr;
|
||||
|
||||
for (U32 j = 0; j < face.mNumVertices; ++j)
|
||||
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector3 pos(face.mPositions[j].getF32ptr());
|
||||
|
||||
@@ -1588,10 +1602,10 @@ LLSD LLModel::writeModel(
|
||||
}
|
||||
}
|
||||
|
||||
return writeModelToStream(ostr, mdl, nowrite);
|
||||
return writeModelToStream(ostr, mdl, nowrite, as_slm);
|
||||
}
|
||||
|
||||
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
|
||||
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)
|
||||
{
|
||||
U32 bytes = 0;
|
||||
|
||||
@@ -1599,6 +1613,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
|
||||
|
||||
LLSD header;
|
||||
|
||||
if (as_slm && mdl.has("material_list"))
|
||||
{ //save material binding names to header
|
||||
header["material_list"] = mdl["material_list"];
|
||||
}
|
||||
|
||||
std::string skin;
|
||||
|
||||
if (mdl.has("skin"))
|
||||
@@ -1689,13 +1708,13 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
||||
}
|
||||
else
|
||||
{ //no exact match found, get closest point
|
||||
const F32 epsilon = 2.f/65536;
|
||||
const F32 epsilon = 1e-5f;
|
||||
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
|
||||
weight_map::iterator iter_down = ++iter_up;
|
||||
|
||||
weight_map::iterator best = iter_up;
|
||||
|
||||
F32 min_dist = (iter->first - pos).magVecSquared();
|
||||
F32 min_dist = (iter->first - pos).magVec();
|
||||
|
||||
bool done = false;
|
||||
while (!done)
|
||||
@@ -1706,7 +1725,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
||||
if (iter_up != mSkinWeights.end() && ++iter_up != mSkinWeights.end())
|
||||
{
|
||||
done = false;
|
||||
F32 dist = (iter_up->first - pos).magVecSquared();
|
||||
F32 dist = (iter_up->first - pos).magVec();
|
||||
|
||||
if (dist < epsilon)
|
||||
{
|
||||
@@ -1724,7 +1743,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
||||
{
|
||||
done = false;
|
||||
|
||||
F32 dist = (iter_down->first - pos).magVecSquared();
|
||||
F32 dist = (iter_down->first - pos).magVec();
|
||||
|
||||
if (dist < epsilon)
|
||||
{
|
||||
@@ -1792,6 +1811,15 @@ bool LLModel::loadModel(std::istream& is)
|
||||
}
|
||||
}
|
||||
|
||||
if (header.has("material_list"))
|
||||
{ //load material list names
|
||||
mMaterialList.clear();
|
||||
for (U32 i = 0; i < (U32)header["material_list"].size(); ++i)
|
||||
{
|
||||
mMaterialList.push_back(header["material_list"][i].asString());
|
||||
}
|
||||
}
|
||||
|
||||
std::string nm[] =
|
||||
{
|
||||
"lowest_lod",
|
||||
@@ -1808,6 +1836,7 @@ bool LLModel::loadModel(std::istream& is)
|
||||
if (header[nm[lod]]["offset"].asInteger() == -1 ||
|
||||
header[nm[lod]]["size"].asInteger() == 0 )
|
||||
{ //cannot load requested LOD
|
||||
llwarns << "LoD data is invalid!" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1821,7 +1850,7 @@ bool LLModel::loadModel(std::istream& is)
|
||||
is.seekg(cur_pos);
|
||||
}
|
||||
|
||||
if (lod == LLModel::LOD_PHYSICS)
|
||||
if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)
|
||||
{
|
||||
std::ios::pos_type cur_pos = is.tellg();
|
||||
loadDecomposition(header, is);
|
||||
@@ -1868,11 +1897,66 @@ bool LLModel::loadModel(std::istream& is)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "unpackVolumeFaces failed!" << llendl;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void LLModel::matchMaterialOrder(LLModel* ref)
|
||||
{
|
||||
llassert(ref->mMaterialList.size() == mMaterialList.size());
|
||||
|
||||
std::map<std::string, U32> index_map;
|
||||
|
||||
//build a map of material slot names to face indexes
|
||||
bool reorder = false;
|
||||
std::set<std::string> base_mat;
|
||||
std::set<std::string> cur_mat;
|
||||
|
||||
for (U32 i = 0; i < mMaterialList.size(); i++)
|
||||
{
|
||||
index_map[ref->mMaterialList[i]] = i;
|
||||
if (!reorder)
|
||||
{ //if any material name does not match reference, we need to reorder
|
||||
reorder = ref->mMaterialList[i] != mMaterialList[i];
|
||||
}
|
||||
base_mat.insert(ref->mMaterialList[i]);
|
||||
cur_mat.insert(mMaterialList[i]);
|
||||
}
|
||||
|
||||
|
||||
if (reorder &&
|
||||
base_mat == cur_mat) //don't reorder if material name sets don't match
|
||||
{
|
||||
std::vector<LLVolumeFace> new_face_list;
|
||||
new_face_list.resize(mVolumeFaces.size());
|
||||
|
||||
std::vector<std::string> new_material_list;
|
||||
new_material_list.resize(mVolumeFaces.size());
|
||||
|
||||
//rebuild face list so materials have the same order
|
||||
//as the reference model
|
||||
for (U32 i = 0; i < mMaterialList.size(); ++i)
|
||||
{
|
||||
U32 ref_idx = index_map[mMaterialList[i]];
|
||||
new_face_list[ref_idx] = mVolumeFaces[i];
|
||||
|
||||
new_material_list[ref_idx] = mMaterialList[i];
|
||||
}
|
||||
|
||||
llassert(new_material_list == ref->mMaterialList);
|
||||
|
||||
mVolumeFaces = new_face_list;
|
||||
}
|
||||
|
||||
//override material list with reference model ordering
|
||||
mMaterialList = ref->mMaterialList;
|
||||
}
|
||||
|
||||
|
||||
bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
|
||||
{
|
||||
@@ -1926,7 +2010,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
{
|
||||
if (skin.has("joint_names"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["joint_names"].size(); ++i)
|
||||
for (U32 i = 0; i < (U32)skin["joint_names"].size(); ++i)
|
||||
{
|
||||
mJointNames.push_back(skin["joint_names"][i]);
|
||||
}
|
||||
@@ -1934,7 +2018,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
|
||||
if (skin.has("inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i)
|
||||
for (U32 i = 0; i < (U32)skin["inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
@@ -1962,7 +2046,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
|
||||
if (skin.has("alt_inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
|
||||
for (U32 i = 0; i < (U32)skin["alt_inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
@@ -2034,7 +2118,7 @@ LLModel::Decomposition::Decomposition(LLSD& data)
|
||||
|
||||
void LLModel::Decomposition::fromLLSD(LLSD& decomp)
|
||||
{
|
||||
if (decomp.has("HullList"))
|
||||
if (decomp.has("HullList") && decomp.has("Positions"))
|
||||
{
|
||||
// updated for const-correctness. gcc is picky about this type of thing - Nyx
|
||||
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
|
||||
@@ -2190,6 +2274,8 @@ LLSD LLModel::Decomposition::asLLSD() const
|
||||
ret["Min"] = min.getValue();
|
||||
ret["Max"] = max.getValue();
|
||||
|
||||
LLVector3 range = max-min;
|
||||
|
||||
if (!hulls.empty())
|
||||
{
|
||||
ret["HullList"] = hulls;
|
||||
@@ -2199,10 +2285,6 @@ LLSD LLModel::Decomposition::asLLSD() const
|
||||
{
|
||||
LLSD::Binary p(total*3*2);
|
||||
|
||||
LLVector3 min(-0.5f, -0.5f, -0.5f);
|
||||
LLVector3 max(0.5f, 0.5f, 0.5f);
|
||||
LLVector3 range = max-min;
|
||||
|
||||
U32 vert_idx = 0;
|
||||
|
||||
for (U32 i = 0; i < mHull.size(); ++i)
|
||||
@@ -2214,12 +2296,10 @@ LLSD LLModel::Decomposition::asLLSD() const
|
||||
for (U32 j = 0; j < mHull[i].size(); ++j)
|
||||
{
|
||||
U64 test = 0;
|
||||
const F32* src = mHull[i][j].mV;
|
||||
|
||||
for (U32 k = 0; k < 3; k++)
|
||||
{
|
||||
F32* src = (F32*) (mHull[i][j].mV);
|
||||
|
||||
llassert(src[k] <= 0.501f && src[k] >= -0.501f);
|
||||
|
||||
//convert to 16-bit normalized across domain
|
||||
U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
|
||||
|
||||
@@ -2258,19 +2338,15 @@ LLSD LLModel::Decomposition::asLLSD() const
|
||||
{
|
||||
LLSD::Binary p(mBaseHull.size()*3*2);
|
||||
|
||||
LLVector3 min(-0.5f, -0.5f, -0.5f);
|
||||
LLVector3 max(0.5f, 0.5f, 0.5f);
|
||||
LLVector3 range = max-min;
|
||||
|
||||
U32 vert_idx = 0;
|
||||
for (U32 j = 0; j < mBaseHull.size(); ++j)
|
||||
{
|
||||
const F32* v = mBaseHull[j].mV;
|
||||
|
||||
for (U32 k = 0; k < 3; k++)
|
||||
{
|
||||
llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
|
||||
|
||||
//convert to 16-bit normalized across domain
|
||||
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
|
||||
U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535);
|
||||
|
||||
U8* buff = (U8*) &val;
|
||||
//write to binary buffer
|
||||
@@ -2315,4 +2391,4 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
|
||||
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MESH_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user