Flipped the MESH_ENABLED switch. Added missing components and updated stuff to be closer to mesh-development head.

This commit is contained in:
Shyotl
2011-07-30 20:30:07 -05:00
parent c081efa460
commit b258b71e07
51 changed files with 3264 additions and 1451 deletions

View File

@@ -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