From 15235061e8a8f64dd94640d27eadfce23ccb76f6 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 18 Jun 2011 01:02:03 -0500 Subject: SH-828 Fix for using uninitialized data when normals or texture coordinates are absent from collada file (can now upload meshes without normals or texture coordinates). --- indra/llmath/llvolume.cpp | 141 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 29 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8c81f27784..7c7c4306da 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2379,11 +2379,16 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const { bool retval = false; - if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) + + const F32 epsilon = 0.00001f; + + if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && + abs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && + abs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) { if (angle_cutoff > 1.f) { - retval = (mData[NORMAL].equals3(rhs.mData[NORMAL])); + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); } else { @@ -2499,38 +2504,52 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } { - U16* n = (U16*) &(norm[0]); - for (U32 j = 0; j < num_verts; ++j) + if (!norm.empty()) + { + U16* n = (U16*) &(norm[0]); + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + n += 3; + } + } + else { - norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); - norm_out->div(65535.f); - norm_out->mul(2.f); - norm_out->sub(1.f); - norm_out++; - n += 3; + memset(norm_out, 0, sizeof(LLVector4a)*num_verts); } } { - U16* t = (U16*) &(tc[0]); - for (U32 j = 0; j < num_verts; j+=2) + if (!tc.empty()) { - if (j < num_verts-1) - { - tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); - } - else + U16* t = (U16*) &(tc[0]); + for (U32 j = 0; j < num_verts; j+=2) { - tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); - } + if (j < num_verts-1) + { + tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); + } + else + { + tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); + } - t += 4; + t += 4; - tc_out->div(65535.f); - tc_out->mul(tc_range); - tc_out->add(min_tc4); + tc_out->div(65535.f); + tc_out->mul(tc_range); + tc_out->add(min_tc4); - tc_out++; + tc_out++; + } + } + else + { + memset(tc_out, 0, sizeof(LLVector2)*num_verts); } } @@ -2656,6 +2675,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) min.setMin(min, face.mPositions[i]); max.setMax(max, face.mPositions[i]); } + + 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 < 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); + } } } } @@ -5696,8 +5734,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) { cv.setPosition(mPositions[index]); - cv.setNormal(mNormals[index]); - cv.mTexCoord = mTexCoords[index]; + if (mNormals) + { + cv.setNormal(mNormals[index]); + } + else + { + cv.getNormal().clear(); + } + + if (mTexCoords) + { + cv.mTexCoord = mTexCoords[index]; + } + else + { + cv.mTexCoord.clear(); + } } bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const @@ -5727,7 +5780,10 @@ void LLVolumeFace::optimize(F32 angle_cutoff) LLVolumeFace new_face; //map of points to vector of vertices at that point - VertexMapData::PointMap point_map; + std::map > point_map; + + LLVector4a range; + range.setSub(mExtents[1],mExtents[0]); //remove redundant vertices for (U32 i = 0; i < mNumIndices; ++i) @@ -5738,7 +5794,19 @@ void LLVolumeFace::optimize(F32 angle_cutoff) getVertexData(index, cv); BOOL found = FALSE; - VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + + LLVector4a pos; + pos.setSub(mPositions[index], mExtents[0]); + pos.div(range); + + U64 pos64 = 0; + + pos64 = (U16) (pos[0]*65535); + pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); + pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); + + std::map >::iterator point_iter = point_map.find(pos64); + if (point_iter != point_map.end()) { //duplicate point might exist for (U32 j = 0; j < point_iter->second.size(); ++j) @@ -5770,11 +5838,26 @@ void LLVolumeFace::optimize(F32 angle_cutoff) } else { - point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + point_map[pos64].push_back(d); } } } + llassert(new_face.mNumIndices == mNumIndices); + llassert(new_face.mNumVertices <= mNumVertices); + + if (angle_cutoff > 1.f && !mNormals) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!mTexCoords) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + swapData(new_face); } -- cgit v1.2.3 From 7201d55396be92b18074ac926698688f9067f222 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 20 Jun 2011 17:18:43 -0400 Subject: BUILDFIX: linux build broken - abs() used instead of fabs() linux caught the fact that we're using an integer absolute value function when we should be using a floating-point version. --- indra/llmath/llvolume.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 7c7c4306da..d401ce7de7 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -32,6 +32,7 @@ #if !LL_WINDOWS #include #endif +#include #include "llerror.h" #include "llmemtype.h" @@ -2383,8 +2384,8 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs const F32 epsilon = 0.00001f; if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && - abs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && - abs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) + fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && + fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) { if (angle_cutoff > 1.f) { -- cgit v1.2.3 From f83b08b69c84d6df9cebb79167804cd295555481 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 24 Jun 2011 15:09:10 -0600 Subject: fix for SH-1878: Viewer hang in GLOD_Group::adaptTriangleBudget during LLModelPreview::genLODs; SH-1891: viewer crashes while previewing "RYOMA 3D XML File.dae"; SH-1890: Crash loading palm tree --- indra/llmath/llvolume.cpp | 58 +++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index d401ce7de7..bddb8d8c66 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2774,11 +2774,13 @@ void LLVolume::makeTetrahedron() n[2] = cv[2].getNormal(); n += 3; - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - + if(tc) + { + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + } //side 2 cv[0].setPosition(p[3]); @@ -2797,11 +2799,14 @@ void LLVolume::makeTetrahedron() n[2] = cv[2].getNormal(); n += 3; - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - + if(tc) + { + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + } + //side 3 cv[0].setPosition(p[3]); cv[1].setPosition(p[1]); @@ -2819,10 +2824,13 @@ void LLVolume::makeTetrahedron() n[2] = cv[2].getNormal(); n += 3; - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; + if(tc) + { + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + } //side 4 cv[0].setPosition(p[2]); @@ -2841,10 +2849,13 @@ void LLVolume::makeTetrahedron() n[2] = cv[2].getNormal(); n += 3; - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; + if(tc) + { + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + } //set index buffer for (U16 i = 0; i < 12; i++) @@ -5613,7 +5624,16 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + + if(src.mTexCoords) + { + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + } + else + { + ll_aligned_free_16(mTexCoords) ; + mTexCoords = NULL ; + } if (src.mBinormals) -- cgit v1.2.3