A majority of vectorization done. Note that it's INCOMPLETE. LLVolumeFace and LLVertexBuffer haven't been updated, so it's very dirty(and buggy) at those transitions. Compiles on windoze.
This commit is contained in:
@@ -17,13 +17,16 @@ set(llmath_SOURCE_FILES
|
||||
llcamera.cpp
|
||||
llcoordframe.cpp
|
||||
llline.cpp
|
||||
llmatrix3a.cpp
|
||||
llmodularmath.cpp
|
||||
llperlin.cpp
|
||||
llquaternion.cpp
|
||||
llrect.cpp
|
||||
llsphere.cpp
|
||||
llvector4a.cpp
|
||||
llvolume.cpp
|
||||
llvolumemgr.cpp
|
||||
llvolumeoctree.cpp
|
||||
llsdutil_math.cpp
|
||||
m3math.cpp
|
||||
m4math.cpp
|
||||
@@ -53,21 +56,32 @@ set(llmath_HEADER_FILES
|
||||
llinterp.h
|
||||
llline.h
|
||||
llmath.h
|
||||
llmatrix3a.h
|
||||
llmatrix3a.inl
|
||||
llmodularmath.h
|
||||
lloctree.h
|
||||
llperlin.h
|
||||
llplane.h
|
||||
llquantize.h
|
||||
llquaternion.h
|
||||
llquaternion2.h
|
||||
llquaternion2.inl
|
||||
llrect.h
|
||||
llsimdmath.h
|
||||
llsimdtypes.h
|
||||
llsimdtypes.inl
|
||||
llsphere.h
|
||||
lltreenode.h
|
||||
llvector4a.h
|
||||
llvector4a.inl
|
||||
llvector4logical.h
|
||||
llv4math.h
|
||||
llv4matrix3.h
|
||||
llv4matrix4.h
|
||||
llv4vector3.h
|
||||
llvolume.h
|
||||
llvolumemgr.h
|
||||
llvolumeoctree.h
|
||||
llsdutil_math.h
|
||||
m3math.h
|
||||
m4math.h
|
||||
|
||||
@@ -92,7 +92,7 @@ F32 LLCamera::getMaxView() const
|
||||
|
||||
// ---------------- LLCamera::setFoo() member functions ----------------
|
||||
|
||||
void LLCamera::setUserClipPlane(LLPlane const& plane)
|
||||
void LLCamera::setUserClipPlane(LLPlane& plane)
|
||||
{
|
||||
mPlaneCount = 7;
|
||||
mAgentPlanes[6] = plane;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "llmath.h"
|
||||
#include "llcoordframe.h"
|
||||
#include "llplane.h"
|
||||
#include "llvector4a.h"
|
||||
|
||||
const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
|
||||
const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
|
||||
@@ -143,7 +144,7 @@ public:
|
||||
virtual ~LLCamera();
|
||||
|
||||
|
||||
void setUserClipPlane(LLPlane const& plane);
|
||||
void setUserClipPlane(LLPlane& plane);
|
||||
void disableUserClipPlane();
|
||||
virtual void setView(F32 vertical_fov_rads);
|
||||
void setViewHeightInPixels(S32 height);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
// So, let's define _USE_MATH_DEFINES before including math.h
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include "math.h"
|
||||
|
||||
// Class from which different types of interpolators can be derived
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <complex>
|
||||
#include <vector>
|
||||
#include "lldefs.h"
|
||||
#include "llstl.h" // *TODO: Remove when LLString is gone
|
||||
#include "llstring.h" // *TODO: Remove when LLString is gone
|
||||
@@ -541,4 +541,7 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
|
||||
data.erase(data.begin(), data.begin()+i);
|
||||
}
|
||||
}
|
||||
|
||||
// Include simd math header
|
||||
#include "llsimdmath.h"
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "lltreenode.h"
|
||||
#include "v3math.h"
|
||||
#include "llvector4a.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
@@ -85,6 +86,7 @@ template <class T>
|
||||
class LLOctreeNode : public LLTreeNode<T>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef LLOctreeTraveler<T> oct_traveler;
|
||||
typedef LLTreeTraveler<T> tree_traveler;
|
||||
typedef typename std::set<LLPointer<T> > element_list;
|
||||
@@ -174,7 +176,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,5 @@
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
|
||||
#include "llrect.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "xform.h"
|
||||
#include "llmemory.h"
|
||||
#include <vector>
|
||||
|
||||
template <class T> class LLTreeNode;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llmemory.h"
|
||||
#include "llmath.h"
|
||||
|
||||
#include <set>
|
||||
@@ -43,9 +44,15 @@
|
||||
#include "v4math.h"
|
||||
#include "m4math.h"
|
||||
#include "m3math.h"
|
||||
#include "llmatrix3a.h"
|
||||
#include "lloctree.h"
|
||||
#include "lldarray.h"
|
||||
#include "llvolume.h"
|
||||
#include "llstl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llvector4a.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
#define DEBUG_SILHOUETTE_BINORMALS 0
|
||||
#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette
|
||||
@@ -135,102 +142,231 @@ BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* cent
|
||||
// and returns the intersection point along dir in intersection_t.
|
||||
|
||||
// Moller-Trumbore algorithm
|
||||
BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
|
||||
F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided)
|
||||
BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t)
|
||||
{
|
||||
|
||||
/* find vectors for two edges sharing vert0 */
|
||||
LLVector4a edge1;
|
||||
edge1.setSub(vert1, vert0);
|
||||
|
||||
LLVector4a edge2;
|
||||
edge2.setSub(vert2, vert0);
|
||||
|
||||
/* begin calculating determinant - also used to calculate U parameter */
|
||||
LLVector4a pvec;
|
||||
pvec.setCross3(dir, edge2);
|
||||
|
||||
/* if determinant is near zero, ray lies in plane of triangle */
|
||||
LLVector4a det;
|
||||
det.setAllDot3(edge1, pvec);
|
||||
|
||||
if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7)
|
||||
{
|
||||
/* calculate distance from vert0 to ray origin */
|
||||
LLVector4a tvec;
|
||||
tvec.setSub(orig, vert0);
|
||||
|
||||
/* calculate U parameter and test bounds */
|
||||
LLVector4a u;
|
||||
u.setAllDot3(tvec,pvec);
|
||||
|
||||
if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) &&
|
||||
(u.lessEqual(det).getGatheredBits() & 0x7))
|
||||
{
|
||||
/* prepare to test V parameter */
|
||||
LLVector4a qvec;
|
||||
qvec.setCross3(tvec, edge1);
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
LLVector4a v;
|
||||
v.setAllDot3(dir, qvec);
|
||||
|
||||
|
||||
//if (!(v < 0.f || u + v > det))
|
||||
|
||||
LLVector4a sum_uv;
|
||||
sum_uv.setAdd(u, v);
|
||||
|
||||
S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7;
|
||||
S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7;
|
||||
|
||||
if (v_gequal && sum_lequal)
|
||||
{
|
||||
/* calculate t, scale parameters, ray intersects triangle */
|
||||
LLVector4a t;
|
||||
t.setAllDot3(edge2,qvec);
|
||||
|
||||
t.div(det);
|
||||
u.div(det);
|
||||
v.div(det);
|
||||
|
||||
intersection_a = u[0];
|
||||
intersection_b = v[0];
|
||||
intersection_t = t[0];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t)
|
||||
{
|
||||
F32 u, v, t;
|
||||
|
||||
/* find vectors for two edges sharing vert0 */
|
||||
LLVector3 edge1 = vert1 - vert0;
|
||||
LLVector4a edge1;
|
||||
edge1.setSub(vert1, vert0);
|
||||
|
||||
LLVector3 edge2 = vert2 - vert0;;
|
||||
|
||||
LLVector4a edge2;
|
||||
edge2.setSub(vert2, vert0);
|
||||
|
||||
/* begin calculating determinant - also used to calculate U parameter */
|
||||
LLVector3 pvec = dir % edge2;
|
||||
|
||||
LLVector4a pvec;
|
||||
pvec.setCross3(dir, edge2);
|
||||
|
||||
/* if determinant is near zero, ray lies in plane of triangle */
|
||||
F32 det = edge1 * pvec;
|
||||
F32 det = edge1.dot3(pvec).getF32();
|
||||
|
||||
if (!two_sided)
|
||||
|
||||
if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
if (det < F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* calculate distance from vert0 to ray origin */
|
||||
LLVector3 tvec = orig - vert0;
|
||||
|
||||
/* calculate U parameter and test bounds */
|
||||
u = tvec * pvec;
|
||||
|
||||
if (u < 0.f || u > det)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* prepare to test V parameter */
|
||||
LLVector3 qvec = tvec % edge1;
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
v = dir * qvec;
|
||||
if (v < 0.f || u + v > det)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* calculate t, scale parameters, ray intersects triangle */
|
||||
t = edge2 * qvec;
|
||||
F32 inv_det = 1.0 / det;
|
||||
t *= inv_det;
|
||||
u *= inv_det;
|
||||
v *= inv_det;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
F32 inv_det = 1.f / det;
|
||||
|
||||
/* calculate distance from vert0 to ray origin */
|
||||
LLVector4a tvec;
|
||||
tvec.setSub(orig, vert0);
|
||||
|
||||
else // two sided
|
||||
{
|
||||
if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
F32 inv_det = 1.0 / det;
|
||||
|
||||
/* calculate distance from vert0 to ray origin */
|
||||
LLVector3 tvec = orig - vert0;
|
||||
|
||||
/* calculate U parameter and test bounds */
|
||||
u = (tvec * pvec) * inv_det;
|
||||
if (u < 0.f || u > 1.f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* prepare to test V parameter */
|
||||
LLVector3 qvec = tvec - edge1;
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
v = (dir * qvec) * inv_det;
|
||||
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* calculate t, ray intersects triangle */
|
||||
t = (edge2 * qvec) * inv_det;
|
||||
/* calculate U parameter and test bounds */
|
||||
u = (tvec.dot3(pvec).getF32()) * inv_det;
|
||||
if (u < 0.f || u > 1.f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* prepare to test V parameter */
|
||||
tvec.sub(edge1);
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
v = (dir.dot3(tvec).getF32()) * inv_det;
|
||||
|
||||
if (intersection_a != NULL)
|
||||
*intersection_a = u;
|
||||
if (intersection_b != NULL)
|
||||
*intersection_b = v;
|
||||
if (intersection_t != NULL)
|
||||
*intersection_t = t;
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* calculate t, ray intersects triangle */
|
||||
t = (edge2.dot3(tvec).getF32()) * inv_det;
|
||||
|
||||
intersection_a = u;
|
||||
intersection_b = v;
|
||||
intersection_t = t;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//helper for non-aligned vectors
|
||||
BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided)
|
||||
{
|
||||
LLVector4a vert0a, vert1a, vert2a, origa, dira;
|
||||
vert0a.load3(vert0.mV);
|
||||
vert1a.load3(vert1.mV);
|
||||
vert2a.load3(vert2.mV);
|
||||
origa.load3(orig.mV);
|
||||
dira.load3(dir.mV);
|
||||
|
||||
if (two_sided)
|
||||
{
|
||||
return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira,
|
||||
intersection_a, intersection_b, intersection_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira,
|
||||
intersection_a, intersection_b, intersection_t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle>
|
||||
{
|
||||
public:
|
||||
const LLVolumeFace* mFace;
|
||||
|
||||
LLVolumeOctreeRebound(const LLVolumeFace* face)
|
||||
{
|
||||
mFace = face;
|
||||
}
|
||||
|
||||
virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch)
|
||||
{ //this is a depth first traversal, so it's safe to assum all children have complete
|
||||
//bounding data
|
||||
|
||||
LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0);
|
||||
|
||||
LLVector4a& min = node->mExtents[0];
|
||||
LLVector4a& max = node->mExtents[1];
|
||||
|
||||
if (!branch->getData().empty())
|
||||
{ //node has data, find AABB that binds data set
|
||||
const LLVolumeTriangle* tri = *(branch->getData().begin());
|
||||
|
||||
//initialize min/max to first available vertex
|
||||
min = *(tri->mV[0]);
|
||||
max = *(tri->mV[0]);
|
||||
|
||||
for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter =
|
||||
branch->getData().begin(); iter != branch->getData().end(); ++iter)
|
||||
{ //for each triangle in node
|
||||
|
||||
//stretch by triangles in node
|
||||
tri = *iter;
|
||||
|
||||
min.setMin(min, *tri->mV[0]);
|
||||
min.setMin(min, *tri->mV[1]);
|
||||
min.setMin(min, *tri->mV[2]);
|
||||
|
||||
max.setMax(max, *tri->mV[0]);
|
||||
max.setMax(max, *tri->mV[1]);
|
||||
max.setMax(max, *tri->mV[2]);
|
||||
}
|
||||
}
|
||||
else if (!branch->getChildren().empty())
|
||||
{ //no data, but child nodes exist
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0);
|
||||
|
||||
//initialize min/max to extents of first child
|
||||
min = child->mExtents[0];
|
||||
max = child->mExtents[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "Empty leaf" << llendl;
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < branch->getChildCount(); ++i)
|
||||
{ //stretch by child extents
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0);
|
||||
min.setMin(min, child->mExtents[0]);
|
||||
max.setMax(max, child->mExtents[1]);
|
||||
}
|
||||
|
||||
node->mBounds[0].setAdd(min, max);
|
||||
node->mBounds[0].mul(0.5f);
|
||||
|
||||
node->mBounds[1].setSub(max,min);
|
||||
node->mBounds[1].mul(0.5f);
|
||||
}
|
||||
};*/
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// statics
|
||||
@@ -2199,7 +2335,7 @@ void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32
|
||||
ratio = (F32) width / (F32) height;
|
||||
|
||||
|
||||
s = (S32)fsqrtf(((F32)vertices / ratio));
|
||||
s = (S32)(F32) sqrt(((F32)vertices / ratio));
|
||||
|
||||
s = llmax(s, 4); // no degenerate sizes, please
|
||||
t = vertices / s;
|
||||
@@ -3396,13 +3532,22 @@ S32 LLVolume::getNumTriangleIndices() const
|
||||
void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
std::vector<LLVector3> &normals,
|
||||
std::vector<S32> &segments,
|
||||
const LLVector3& obj_cam_vec,
|
||||
const LLMatrix4& mat,
|
||||
const LLMatrix3& norm_mat,
|
||||
const LLVector3& obj_cam_vec_in,
|
||||
const LLMatrix4& mat_in,
|
||||
const LLMatrix3& norm_mat_in,
|
||||
S32 face_mask)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_VOLUME);
|
||||
|
||||
|
||||
LLMatrix4a mat;
|
||||
mat.loadu(mat_in);
|
||||
|
||||
LLMatrix4a norm_mat;
|
||||
norm_mat.loadu(norm_mat_in);
|
||||
|
||||
LLVector4a obj_cam_vec;
|
||||
obj_cam_vec.load3(obj_cam_vec_in.mV);
|
||||
|
||||
vertices.clear();
|
||||
normals.clear();
|
||||
segments.clear();
|
||||
@@ -3414,10 +3559,12 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
{
|
||||
const LLVolumeFace& face = *iter;
|
||||
|
||||
if (!(face_mask & (0x1 << cur_index++)))
|
||||
if (!(face_mask & (0x1 << cur_index++)) ||
|
||||
face.mIndices.empty() || face.mEdge.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
|
||||
|
||||
}
|
||||
@@ -3517,18 +3664,30 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
S32 v2 = face.mIndices[j*3+1];
|
||||
S32 v3 = face.mIndices[j*3+2];
|
||||
|
||||
LLVector3 norm = (face.mVertices[v1].mPosition - face.mVertices[v2].mPosition) %
|
||||
(face.mVertices[v2].mPosition - face.mVertices[v3].mPosition);
|
||||
|
||||
if (norm.magVecSquared() < 0.00000001f)
|
||||
//ew. Face verts arent aligned yet.
|
||||
LLVector4a va1,va3;
|
||||
va1.load3(face.mVertices[v1].mPosition.mV);
|
||||
va3.load3(face.mVertices[v3].mPosition.mV);
|
||||
|
||||
LLVector4a c1,c2;
|
||||
c2.load3(face.mVertices[v2].mPosition.mV);
|
||||
c1.setSub(va1,c2);
|
||||
c2.sub(va3);
|
||||
|
||||
LLVector4a norm;
|
||||
|
||||
norm.setCross3(c1, c2);
|
||||
|
||||
if (norm.dot3(norm) < 0.00000001f)
|
||||
{
|
||||
fFacing[j] = AWAY | TOWARDS;
|
||||
}
|
||||
else
|
||||
{
|
||||
//get view vector
|
||||
LLVector3 view = (obj_cam_vec-face.mVertices[v1].mPosition);
|
||||
bool away = view * norm > 0.0f;
|
||||
LLVector4a view;
|
||||
view.setSub(obj_cam_vec, va1);
|
||||
bool away = view.dot3(norm) > 0.0f;
|
||||
if (away)
|
||||
{
|
||||
fFacing[j] = AWAY;
|
||||
@@ -3574,13 +3733,13 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
S32 v1 = face.mIndices[j*3+k];
|
||||
S32 v2 = face.mIndices[j*3+((k+1)%3)];
|
||||
|
||||
vertices.push_back(face.mVertices[v1].mPosition*mat);
|
||||
LLVector3 norm1 = face.mVertices[v1].mNormal * norm_mat;
|
||||
vertices.push_back(face.mVertices[v1].mPosition*mat_in);
|
||||
LLVector3 norm1 = face.mVertices[v1].mNormal * norm_mat_in;
|
||||
norm1.normVec();
|
||||
normals.push_back(norm1);
|
||||
|
||||
vertices.push_back(face.mVertices[v2].mPosition*mat);
|
||||
LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat;
|
||||
vertices.push_back(face.mVertices[v2].mPosition*mat_in);
|
||||
LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat_in;
|
||||
norm2.normVec();
|
||||
normals.push_back(norm2);
|
||||
|
||||
@@ -3596,6 +3755,19 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
||||
S32 face,
|
||||
LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
|
||||
{
|
||||
LLVector4a starta, enda;
|
||||
starta.load3(start.mV);
|
||||
enda.load3(end.mV);
|
||||
|
||||
return lineSegmentIntersect(starta, enda, face, intersection, tex_coord, normal, bi_normal);
|
||||
|
||||
}
|
||||
|
||||
|
||||
S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
S32 face,
|
||||
LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
|
||||
{
|
||||
S32 hit_face = -1;
|
||||
|
||||
@@ -3613,7 +3785,8 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
||||
end_face = face;
|
||||
}
|
||||
|
||||
LLVector3 dir = end - start;
|
||||
LLVector4a dir;
|
||||
dir.setSub(end, start);
|
||||
|
||||
F32 closest_t = 2.f; // must be larger than 1
|
||||
|
||||
@@ -3621,8 +3794,12 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
||||
{
|
||||
const LLVolumeFace &face = getVolumeFace((U32)i);
|
||||
|
||||
LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f;
|
||||
LLVector3 box_size = face.mExtents[1] - face.mExtents[0];
|
||||
LLVector4a box_center;
|
||||
box_center.setAdd(face.mExtents[0], face.mExtents[1]);
|
||||
box_center.mul(0.5f);
|
||||
|
||||
LLVector4a box_size;
|
||||
box_size.setSub(face.mExtents[1], face.mExtents[0]);
|
||||
|
||||
if (LLLineSegmentBoxIntersect(start, end, box_center, box_size))
|
||||
{
|
||||
@@ -3638,11 +3815,15 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
||||
S32 index3 = face.mIndices[tri*3+2];
|
||||
|
||||
F32 a, b, t;
|
||||
|
||||
if (LLTriangleRayIntersect(face.mVertices[index1].mPosition,
|
||||
face.mVertices[index2].mPosition,
|
||||
face.mVertices[index3].mPosition,
|
||||
start, dir, &a, &b, &t, FALSE))
|
||||
|
||||
LLVector4a pos[3];
|
||||
pos[0].load3(face.mVertices[index1].mPosition.mV);
|
||||
pos[1].load3(face.mVertices[index2].mPosition.mV);
|
||||
pos[2].load3(face.mVertices[index2].mPosition.mV);
|
||||
if (LLTriangleRayIntersect(pos[0],
|
||||
pos[1],
|
||||
pos[2],
|
||||
start, dir, a, b, t))
|
||||
{
|
||||
if ((t >= 0.f) && // if hit is after start
|
||||
(t <= 1.f) && // and before end
|
||||
@@ -3653,7 +3834,10 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
*intersection = start + dir * closest_t;
|
||||
LLVector4a v;
|
||||
v.setMul(dir,closest_t);
|
||||
v.add(start);
|
||||
intersection->set(v.getF32ptr());
|
||||
}
|
||||
|
||||
if (tex_coord != NULL)
|
||||
@@ -4421,7 +4605,69 @@ std::ostream& operator<<(std::ostream &s, const LLVolume *volumep)
|
||||
return s;
|
||||
}
|
||||
|
||||
LLVolumeFace::LLVolumeFace() :
|
||||
mID(0),
|
||||
mTypeMask(0),
|
||||
mHasBinormals(FALSE),
|
||||
mBeginS(0),
|
||||
mBeginT(0),
|
||||
mNumS(0),
|
||||
mNumT(0)
|
||||
{
|
||||
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
|
||||
mExtents[0].splat(-0.5f);
|
||||
mExtents[1].splat(0.5f);
|
||||
mCenter = mExtents+2;
|
||||
}
|
||||
|
||||
LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
|
||||
: mID(0),
|
||||
mTypeMask(0),
|
||||
mHasBinormals(FALSE),
|
||||
mBeginS(0),
|
||||
mBeginT(0),
|
||||
mNumS(0),
|
||||
mNumT(0)
|
||||
{
|
||||
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
|
||||
mCenter = mExtents+2;
|
||||
*this = src;
|
||||
}
|
||||
|
||||
LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
||||
{
|
||||
if (&src == this)
|
||||
{ //self assignment, do nothing
|
||||
return *this;
|
||||
}
|
||||
|
||||
mID = src.mID;
|
||||
mTypeMask = src.mTypeMask;
|
||||
mHasBinormals = src.mHasBinormals,
|
||||
mBeginS = src.mBeginS;
|
||||
mBeginT = src.mBeginT;
|
||||
mNumS = src.mNumS;
|
||||
mNumT = src.mNumT;
|
||||
|
||||
mExtents[0] = src.mExtents[0];
|
||||
mExtents[1] = src.mExtents[1];
|
||||
*mCenter = *src.mCenter;
|
||||
|
||||
|
||||
|
||||
LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a));
|
||||
|
||||
mVertices = src.mVertices;
|
||||
mIndices = src.mIndices;
|
||||
mEdge = src.mEdge;
|
||||
return *this;
|
||||
}
|
||||
LLVolumeFace::~LLVolumeFace()
|
||||
{
|
||||
ll_aligned_free_16(mExtents);
|
||||
mExtents = NULL;
|
||||
|
||||
}
|
||||
BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
|
||||
{
|
||||
BOOL ret = FALSE ;
|
||||
@@ -4504,78 +4750,99 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
|
||||
num_vertices = (grid_size+1)*(grid_size+1);
|
||||
num_indices = quad_count * 4;
|
||||
|
||||
LLVector3& min = mExtents[0];
|
||||
LLVector3& max = mExtents[1];
|
||||
LLVector4a& min = mExtents[0];
|
||||
LLVector4a& max = mExtents[1];
|
||||
|
||||
S32 offset = 0;
|
||||
if (mTypeMask & TOP_MASK)
|
||||
offset = (max_t-1) * max_s;
|
||||
else
|
||||
offset = mBeginS;
|
||||
|
||||
VertexData corners[4];
|
||||
VertexData baseVert;
|
||||
for(int t = 0; t < 4; t++){
|
||||
corners[t].mPosition = mesh[offset + (grid_size*t)].mPos;
|
||||
corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f;
|
||||
corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1];
|
||||
}
|
||||
baseVert.mNormal =
|
||||
((corners[1].mPosition-corners[0].mPosition) %
|
||||
(corners[2].mPosition-corners[1].mPosition));
|
||||
baseVert.mNormal.normVec();
|
||||
if(!(mTypeMask & TOP_MASK)){
|
||||
baseVert.mNormal *= -1.0f;
|
||||
}else{
|
||||
//Swap the UVs on the U(X) axis for top face
|
||||
LLVector2 swap;
|
||||
swap = corners[0].mTexCoord;
|
||||
corners[0].mTexCoord=corners[3].mTexCoord;
|
||||
corners[3].mTexCoord=swap;
|
||||
swap = corners[1].mTexCoord;
|
||||
corners[1].mTexCoord=corners[2].mTexCoord;
|
||||
corners[2].mTexCoord=swap;
|
||||
}
|
||||
baseVert.mBinormal = calc_binormal_from_triangle(
|
||||
corners[0].mPosition, corners[0].mTexCoord,
|
||||
corners[1].mPosition, corners[1].mTexCoord,
|
||||
corners[2].mPosition, corners[2].mTexCoord);
|
||||
for(int t = 0; t < 4; t++){
|
||||
corners[t].mBinormal = baseVert.mBinormal;
|
||||
corners[t].mNormal = baseVert.mNormal;
|
||||
}
|
||||
mHasBinormals = TRUE;
|
||||
|
||||
if (partial_build)
|
||||
{
|
||||
mVertices.clear();
|
||||
offset = (max_t-1) * max_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = mBeginS;
|
||||
}
|
||||
|
||||
S32 vtop = mVertices.size();
|
||||
for(int gx = 0;gx<grid_size+1;gx++){
|
||||
for(int gy = 0;gy<grid_size+1;gy++){
|
||||
VertexData newVert;
|
||||
LerpPlanarVertex(
|
||||
corners[0],
|
||||
corners[1],
|
||||
corners[3],
|
||||
newVert,
|
||||
(F32)gx/(F32)grid_size,
|
||||
(F32)gy/(F32)grid_size);
|
||||
mVertices.push_back(newVert);
|
||||
S32 vtop;
|
||||
{
|
||||
VertexData corners[4];
|
||||
VertexData baseVert;
|
||||
for(S32 t = 0; t < 4; t++){
|
||||
corners[t].mPosition = mesh[offset + (grid_size*t)].mPos;
|
||||
corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f;
|
||||
corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1];
|
||||
}
|
||||
|
||||
if (gx == 0 && gy == 0)
|
||||
{
|
||||
baseVert.mNormal =
|
||||
((corners[1].mPosition-corners[0].mPosition) %
|
||||
(corners[2].mPosition-corners[1].mPosition));
|
||||
baseVert.mNormal.normalize();
|
||||
}
|
||||
|
||||
if(!(mTypeMask & TOP_MASK))
|
||||
{
|
||||
baseVert.mNormal *= -.1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Swap the UVs on the U(X) axis for top face
|
||||
LLVector2 swap;
|
||||
swap = corners[0].mTexCoord;
|
||||
corners[0].mTexCoord=corners[3].mTexCoord;
|
||||
corners[3].mTexCoord=swap;
|
||||
swap = corners[1].mTexCoord;
|
||||
corners[1].mTexCoord=corners[2].mTexCoord;
|
||||
corners[2].mTexCoord=swap;
|
||||
}
|
||||
baseVert.mBinormal = calc_binormal_from_triangle(
|
||||
corners[0].mPosition, corners[0].mTexCoord,
|
||||
corners[1].mPosition, corners[1].mTexCoord,
|
||||
corners[2].mPosition, corners[2].mTexCoord);
|
||||
for(int t = 0; t < 4; t++){
|
||||
corners[t].mBinormal = baseVert.mBinormal;
|
||||
corners[t].mNormal = baseVert.mNormal;
|
||||
}
|
||||
mHasBinormals = TRUE;
|
||||
|
||||
if (partial_build)
|
||||
{
|
||||
mVertices.clear();
|
||||
}
|
||||
|
||||
vtop = mVertices.size();
|
||||
|
||||
for(int gx = 0;gx<grid_size+1;gx++)
|
||||
{
|
||||
for(int gy = 0;gy<grid_size+1;gy++)
|
||||
{
|
||||
min = max = newVert.mPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
update_min_max(min,max,newVert.mPosition);
|
||||
VertexData newVert;
|
||||
LerpPlanarVertex(
|
||||
corners[0],
|
||||
corners[1],
|
||||
corners[3],
|
||||
newVert,
|
||||
(F32)gx/(F32)grid_size,
|
||||
(F32)gy/(F32)grid_size);
|
||||
mVertices.push_back(newVert);
|
||||
|
||||
if (gx == 0 && gy == 0)
|
||||
{
|
||||
max.load3(newVert.mPosition.mV);
|
||||
min = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVector4a pos;
|
||||
pos.load3(newVert.mPosition.mV);
|
||||
update_min_max(min,max,pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCenter = (min + max) * 0.5f;
|
||||
mCenter->setAdd(min, max);
|
||||
mCenter->mul(0.5f);
|
||||
}
|
||||
|
||||
if (!partial_build)
|
||||
{
|
||||
@@ -4640,7 +4907,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
|
||||
S32 max_s = volume->getProfile().getTotal();
|
||||
S32 max_t = volume->getPath().mPath.size();
|
||||
|
||||
mCenter.clearVec();
|
||||
mCenter->clear();
|
||||
|
||||
S32 offset = 0;
|
||||
if (mTypeMask & TOP_MASK)
|
||||
@@ -4658,8 +4925,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
|
||||
LLVector2 cuv;
|
||||
LLVector2 min_uv, max_uv;
|
||||
|
||||
LLVector3& min = mExtents[0];
|
||||
LLVector3& max = mExtents[1];
|
||||
LLVector4a& min = mExtents[0];
|
||||
LLVector4a& max = mExtents[1];
|
||||
|
||||
// Copy the vertices into the array
|
||||
for (S32 i = 0; i < num_vertices; i++)
|
||||
@@ -4680,38 +4947,54 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
min = max = mVertices[i].mPosition;
|
||||
max.load3(mVertices[i].mPosition.mV);
|
||||
min = max;
|
||||
min_uv = max_uv = mVertices[i].mTexCoord;
|
||||
}
|
||||
else
|
||||
{
|
||||
update_min_max(min,max, mVertices[i].mPosition);
|
||||
LLVector4a pos;
|
||||
pos.load3(mVertices[i].mPosition.mV);
|
||||
update_min_max(min,max, pos);
|
||||
update_min_max(min_uv, max_uv, mVertices[i].mTexCoord);
|
||||
}
|
||||
}
|
||||
|
||||
mCenter = (min+max)*0.5f;
|
||||
mCenter->setAdd(min, max);
|
||||
mCenter->mul(0.5f);
|
||||
|
||||
cuv = (min_uv + max_uv)*0.5f;
|
||||
|
||||
LLVector3 binormal = calc_binormal_from_triangle(
|
||||
mCenter, cuv,
|
||||
LLVector3 binormal = calc_binormal_from_triangle(
|
||||
LLVector3(mCenter->getF32ptr()), cuv,
|
||||
mVertices[0].mPosition, mVertices[0].mTexCoord,
|
||||
mVertices[1].mPosition, mVertices[1].mTexCoord);
|
||||
binormal.normVec();
|
||||
|
||||
LLVector3 d0;
|
||||
LLVector3 d1;
|
||||
LLVector3 normal;
|
||||
LLVector4a pos[2];
|
||||
pos[0].load3(mVertices[0].mPosition.mV);
|
||||
pos[1].load3(mVertices[0].mPosition.mV);
|
||||
LLVector4a normal;
|
||||
LLVector4a d0, d1;
|
||||
|
||||
|
||||
d0 = mCenter-mVertices[0].mPosition;
|
||||
d1 = mCenter-mVertices[1].mPosition;
|
||||
d0.setSub(*mCenter, pos[0]);
|
||||
d1.setSub(*mCenter, pos[1]);
|
||||
|
||||
normal = (mTypeMask & TOP_MASK) ? (d0%d1) : (d1%d0);
|
||||
normal.normVec();
|
||||
if (mTypeMask & TOP_MASK)
|
||||
{
|
||||
normal.setCross3(d0, d1);
|
||||
}
|
||||
else
|
||||
{
|
||||
normal.setCross3(d1, d0);
|
||||
}
|
||||
|
||||
normal.normalize3fast();
|
||||
|
||||
VertexData vd;
|
||||
vd.mPosition = mCenter;
|
||||
vd.mNormal = normal;
|
||||
vd.mPosition.set(mCenter->getF32ptr());
|
||||
vd.mNormal.set(normal.getF32ptr());
|
||||
vd.mBinormal = binormal;
|
||||
vd.mTexCoord = cuv;
|
||||
|
||||
@@ -4729,7 +5012,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
|
||||
for (S32 i = 0; i < num_vertices; i++)
|
||||
{
|
||||
mVertices[i].mBinormal = binormal;
|
||||
mVertices[i].mNormal = normal;
|
||||
mVertices[i].mNormal.set(normal.getF32ptr());
|
||||
}
|
||||
|
||||
mHasBinormals = TRUE;
|
||||
@@ -5146,17 +5429,21 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
|
||||
|
||||
|
||||
//get bounding box for this side
|
||||
LLVector3& face_min = mExtents[0];
|
||||
LLVector3& face_max = mExtents[1];
|
||||
mCenter.clearVec();
|
||||
LLVector4a& face_min = mExtents[0];
|
||||
LLVector4a& face_max = mExtents[1];
|
||||
mCenter->clear();
|
||||
|
||||
face_min = face_max = mVertices[0].mPosition;
|
||||
face_max.load3(mVertices[0].mPosition.mV);
|
||||
face_min = face_max;
|
||||
for (U32 i = 1; i < mVertices.size(); ++i)
|
||||
{
|
||||
update_min_max(face_min, face_max, mVertices[i].mPosition);
|
||||
LLVector4a pos;
|
||||
pos.load3(mVertices[i].mPosition.mV);
|
||||
update_min_max(face_min, face_max, pos);
|
||||
}
|
||||
|
||||
mCenter = (face_min + face_max) * 0.5f;
|
||||
mCenter->setAdd(face_min, face_max);
|
||||
mCenter->mul(0.5f);
|
||||
|
||||
S32 cur_index = 0;
|
||||
S32 cur_edge = 0;
|
||||
|
||||
@@ -49,6 +49,8 @@ class LLVolume;
|
||||
//#include "vmath.h"
|
||||
#include "v2math.h"
|
||||
#include "v3math.h"
|
||||
#include "v3dmath.h"
|
||||
#include "v4math.h"
|
||||
#include "llquaternion.h"
|
||||
#include "llstrider.h"
|
||||
#include "v4coloru.h"
|
||||
@@ -786,20 +788,6 @@ public:
|
||||
class LLVolumeFace
|
||||
{
|
||||
public:
|
||||
LLVolumeFace() :
|
||||
mID(0),
|
||||
mTypeMask(0),
|
||||
mHasBinormals(FALSE),
|
||||
mBeginS(0),
|
||||
mBeginT(0),
|
||||
mNumS(0),
|
||||
mNumT(0)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
|
||||
void createBinormals();
|
||||
|
||||
class VertexData
|
||||
{
|
||||
public:
|
||||
@@ -808,6 +796,14 @@ public:
|
||||
LLVector3 mBinormal;
|
||||
LLVector2 mTexCoord;
|
||||
};
|
||||
LLVolumeFace();
|
||||
LLVolumeFace(const LLVolumeFace& src);
|
||||
LLVolumeFace& operator=(const LLVolumeFace& rhs);
|
||||
|
||||
~LLVolumeFace();
|
||||
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
|
||||
void createBinormals();
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -827,7 +823,6 @@ public:
|
||||
public:
|
||||
S32 mID;
|
||||
U32 mTypeMask;
|
||||
LLVector3 mCenter;
|
||||
BOOL mHasBinormals;
|
||||
|
||||
// Only used for INNER/OUTER faces
|
||||
@@ -836,8 +831,9 @@ public:
|
||||
S32 mNumS;
|
||||
S32 mNumT;
|
||||
|
||||
LLVector3 mExtents[2]; //minimum and maximum point of face
|
||||
LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
|
||||
LLVector4a* mExtents; //minimum and maximum point of face
|
||||
LLVector4a* mCenter;
|
||||
LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
|
||||
|
||||
std::vector<VertexData> mVertices;
|
||||
std::vector<U16> mIndices;
|
||||
@@ -898,6 +894,7 @@ public:
|
||||
BOOL isUnique() const { return mUnique; }
|
||||
|
||||
S32 getSculptLevel() const { return mSculptLevel; }
|
||||
void setSculptLevel(S32 level) { mSculptLevel = level; }
|
||||
|
||||
S32 *getTriangleIndices(U32 &num_indices) const;
|
||||
|
||||
@@ -922,6 +919,13 @@ public:
|
||||
LLVector3* normal = NULL, // return the surface normal at the intersection point
|
||||
LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point
|
||||
);
|
||||
|
||||
S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
S32 face = 1,
|
||||
LLVector3* intersection = NULL,
|
||||
LLVector2* tex_coord = NULL,
|
||||
LLVector3* normal = NULL,
|
||||
LLVector3* bi_normal = NULL);
|
||||
|
||||
// The following cleans up vertices and triangles,
|
||||
// getting rid of degenerate triangles and duplicate vertices,
|
||||
@@ -986,8 +990,15 @@ LLVector3 calc_binormal_from_triangle(
|
||||
|
||||
BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
|
||||
BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
|
||||
BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size);
|
||||
|
||||
BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
|
||||
F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided);
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided);
|
||||
|
||||
BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t);
|
||||
BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
|
||||
F32& intersection_a, F32& intersection_b, F32& intersection_t);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
|
||||
{
|
||||
llassert_always(mLODRefs[i] > 0);
|
||||
mLODRefs[i]--;
|
||||
#if 1 // SJB: Possible opt: keep other lods around
|
||||
#if 0 // SJB: Possible opt: keep other lods around
|
||||
if (!mLODRefs[i])
|
||||
{
|
||||
mVolumeLODs[i] = NULL;
|
||||
@@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
|
||||
return mDetailScales[detail];
|
||||
}
|
||||
|
||||
S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail)
|
||||
{
|
||||
for (S32 i = 1; i < 4; i++)
|
||||
{
|
||||
if (mDetailScales[i] > detail)
|
||||
{
|
||||
return i-1;
|
||||
}
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
F32 LLVolumeLODGroup::dump()
|
||||
{
|
||||
F32 usage = 0.f;
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
static S32 getDetailFromTan(const F32 tan_angle);
|
||||
static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher);
|
||||
static F32 getVolumeScaleFromDetail(const S32 detail);
|
||||
static S32 getVolumeDetailFromScale(F32 scale);
|
||||
|
||||
LLVolume* refLOD(const S32 detail);
|
||||
BOOL derefLOD(LLVolume *volumep);
|
||||
@@ -92,8 +93,8 @@ public:
|
||||
// whatever calls getVolume() never owns the LLVolume* and
|
||||
// cannot keep references for long since it may be deleted
|
||||
// later. For best results hold it in an LLPointer<LLVolume>.
|
||||
LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
|
||||
void unrefVolume(LLVolume *volumep);
|
||||
virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
|
||||
virtual void unrefVolume(LLVolume *volumep);
|
||||
|
||||
void dump();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user