Merge branch 'master' of git://github.com/Shyotl/SingularityViewer into ManagedMarketplace

This commit is contained in:
Lirusaito
2019-03-17 00:22:55 -04:00
33 changed files with 1043 additions and 380 deletions

View File

@@ -22,6 +22,7 @@ set(llmath_SOURCE_FILES
llperlin.cpp
llquaternion.cpp
llrect.cpp
llrigginginfo.cpp
llsdutil_math.cpp
llsphere.cpp
llvector4a.cpp
@@ -67,6 +68,7 @@ set(llmath_HEADER_FILES
llquaternion2.h
llquaternion2.inl
llrect.h
llrigginginfo.h
llsdutil_math.h
llsimdmath.h
llsimdtypes.h

View File

@@ -700,4 +700,12 @@ public:
}
} LL_ALIGN_POSTFIX(16);
inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m)
{
s << "[" << m.getF32ptr()[0] << ", " << m.getF32ptr()[1] << ", " << m.getF32ptr()[2] << ", " << m.getF32ptr()[3] << "]";
return s;
}
void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents);
#endif

View File

@@ -0,0 +1,159 @@
/**
* @file llrigginginfo.cpp
* @brief Functions for tracking rigged box extents
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llmath.h"
#include "llrigginginfo.h"
//-----------------------------------------------------------------------------
// LLJointRiggingInfo
//-----------------------------------------------------------------------------
LLJointRiggingInfo::LLJointRiggingInfo()
{
mRiggedExtents[0].clear();
mRiggedExtents[1].clear();
mIsRiggedTo = false;
}
bool LLJointRiggingInfo::isRiggedTo() const
{
return mIsRiggedTo;
}
void LLJointRiggingInfo::setIsRiggedTo(bool val)
{
mIsRiggedTo = val;
}
LLVector4a *LLJointRiggingInfo::getRiggedExtents()
{
return mRiggedExtents;
}
const LLVector4a *LLJointRiggingInfo::getRiggedExtents() const
{
return mRiggedExtents;
}
// Combine two rigging info states.
// - isRiggedTo if either of the source infos are rigged to
// - box is union of the two sources
void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other)
{
if (other.mIsRiggedTo)
{
if (mIsRiggedTo)
{
// Combine existing boxes
update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[0]);
update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[1]);
}
else
{
// Initialize box
mIsRiggedTo = true;
mRiggedExtents[0] = other.mRiggedExtents[0];
mRiggedExtents[1] = other.mRiggedExtents[1];
}
}
}
LLJointRiggingInfoTab::LLJointRiggingInfoTab():
mRigInfoPtr(NULL),
mSize(0),
mNeedsUpdate(true)
{
}
LLJointRiggingInfoTab::~LLJointRiggingInfoTab()
{
clear();
}
// This doesn't preserve data if the size changes. In practice
// this doesn't matter because the size is always either
// LL_CHARACTER_MAX_ANIMATED_JOINTS or 0.
void LLJointRiggingInfoTab::resize(S32 size)
{
if (size != mSize)
{
clear();
if (size > 0)
{
mRigInfoPtr = new LLJointRiggingInfo[size];
mSize = size;
}
}
}
void LLJointRiggingInfoTab::clear()
{
if (mRigInfoPtr)
{
delete[](mRigInfoPtr);
mRigInfoPtr = NULL;
mSize = 0;
}
}
void showDetails(const LLJointRiggingInfoTab& src, const std::string& str)
{
S32 count_rigged = 0;
S32 count_box = 0;
LLVector4a zero_vec;
zero_vec.clear();
for (S32 i=0; i<src.size(); i++)
{
if (src[i].isRiggedTo())
{
count_rigged++;
if ((!src[i].getRiggedExtents()[0].equals3(zero_vec)) ||
(!src[i].getRiggedExtents()[1].equals3(zero_vec)))
{
count_box++;
}
}
}
LL_DEBUGS("RigSpammish") << "details: " << str << " has " << count_rigged << " rigged joints, of which " << count_box << " are non-empty" << LL_ENDL;
}
void LLJointRiggingInfoTab::merge(const LLJointRiggingInfoTab& src)
{
//showDetails(*this, "input this");
// Size should be either LL_CHARACTER_MAX_ANIMATED_JOINTS, or 0 if
// no data. Not necessarily the same for both inputs.
if (src.size() > size())
{
resize(src.size());
}
S32 min_size = llmin(size(), src.size());
for (S32 i=0; i<min_size; i++)
{
(*this)[i].merge(src[i]);
}
//showDetails(src, "input src");
//showDetails(*this, "output this");
}

View File

@@ -0,0 +1,100 @@
/**
* @file llrigginginfo.h
* @brief Functions for tracking rigged box extents
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Stores information related to associated rigged mesh vertices
// This lives in llmath because llvolume lives in llmath.
#ifndef LL_LLRIGGINGINFO_H
#define LL_LLRIGGINGINFO_H
#include "llvector4a.h"
// Extents are in joint space
// isRiggedTo is based on the state of all currently associated rigged meshes
LL_ALIGN_PREFIX(16)
class LLJointRiggingInfo
{
public:
LLJointRiggingInfo();
bool isRiggedTo() const;
void setIsRiggedTo(bool val);
LLVector4a *getRiggedExtents();
const LLVector4a *getRiggedExtents() const;
void merge(const LLJointRiggingInfo& other);
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}
void* operator new[](size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete[](void* ptr)
{
ll_aligned_free_16(ptr);
}
private:
LL_ALIGN_16(LLVector4a mRiggedExtents[2]);
bool mIsRiggedTo;
} LL_ALIGN_POSTFIX(16);
// For storing all the rigging info associated with a given avatar or
// object, keyed by joint_num.
// Using direct memory management instead of std::vector<> to avoid alignment issues.
class LLJointRiggingInfoTab
{
public:
LLJointRiggingInfoTab();
~LLJointRiggingInfoTab();
void resize(S32 size);
void clear();
S32 size() const { return mSize; }
void merge(const LLJointRiggingInfoTab& src);
LLJointRiggingInfo& operator[](S32 i) { return mRigInfoPtr[i]; }
const LLJointRiggingInfo& operator[](S32 i) const { return mRigInfoPtr[i]; };
bool needsUpdate() { return mNeedsUpdate; }
void setNeedsUpdate(bool val) { mNeedsUpdate = val; }
private:
// Not implemented
LLJointRiggingInfoTab& operator=(const LLJointRiggingInfoTab& src);
LLJointRiggingInfoTab(const LLJointRiggingInfoTab& src);
LLJointRiggingInfo *mRigInfoPtr;
S32 mSize;
bool mNeedsUpdate;
};
#endif

View File

@@ -336,4 +336,9 @@ inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p
max.setMax(max, p);
}
inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v)
{
s << "(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")";
return s;
}
#endif

View File

@@ -1301,7 +1301,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
F32 revolutions = params.getRevolutions();
F32 skew = params.getSkew();
@@ -1599,6 +1599,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
if (is_sculpted)
sides = llmax(sculpt_size, 1);
if (0 < sides)
genNGon(params, sides);
}
break;
@@ -2081,6 +2082,7 @@ void LLVolume::resizePath(S32 length)
{
mPathp->resizePath(length);
mVolumeFaces.clear();
setDirty();
}
void LLVolume::regen()
@@ -2138,19 +2140,22 @@ BOOL LLVolume::generate()
F32 profile_detail = mDetail;
F32 path_detail = mDetail;
U8 path_type = mParams.getPathParams().getCurveType();
U8 profile_type = mParams.getProfileParams().getCurveType();
if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
{ //cylinders don't care about Z-Axis
mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
{
U8 path_type = mParams.getPathParams().getCurveType();
U8 profile_type = mParams.getProfileParams().getCurveType();
if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
{
//cylinders don't care about Z-Axis
mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
}
else if (path_type == LL_PCODE_PATH_CIRCLE)
{
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
}
}
else if (path_type == LL_PCODE_PATH_CIRCLE)
{
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
}
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
@@ -2906,15 +2911,41 @@ F32 LLVolume::sculptGetSurfaceArea()
return area;
}
// create placeholder shape
void LLVolume::sculptGeneratePlaceholder()
// create empty placeholder shape
void LLVolume::sculptGenerateEmptyPlaceholder()
{
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
S32 line = 0;
for (S32 s = 0; s < sizeS; s++)
{
for (S32 t = 0; t < sizeT; t++)
{
S32 i = t + line;
LLVector4a& pt = mMesh[i];
F32* p = pt.getF32ptr();
p[0] = 0;
p[1] = 0;
p[2] = 0;
llassert(pt.isFinite3());
}
line += sizeT;
}
}
// create sphere placeholder shape
void LLVolume::sculptGenerateSpherePlaceholder()
{
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
S32 line = 0;
// for now, this is a sphere.
for (S32 s = 0; s < sizeS; s++)
{
for (S32 t = 0; t < sizeT; t++)
@@ -3123,7 +3154,7 @@ bool sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32
}
// sculpt replaces generate() for sculpted surfaces
void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder)
{
U8 sculpt_type = mParams.getSculptType();
@@ -3187,13 +3218,22 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
visible_placeholder = true;
}
}
}
if (data_is_empty)
{
sculptGeneratePlaceholder();
if (visible_placeholder)
{
// Object should be visible since there will be nothing else to display
sculptGenerateSpherePlaceholder();
}
else
{
sculptGenerateEmptyPlaceholder();
}
}
@@ -3723,10 +3763,46 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
continue;
}
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
if (face.mTypeMask & (LLVolumeFace::CAP_MASK))
{
LLVector4a* v = (LLVector4a*)face.mPositions;
LLVector4a* n = (LLVector4a*)face.mNormals;
for (U32 j = 0; j < (U32)face.mNumIndices / 3; j++)
{
for (S32 k = 0; k < 3; k++)
{
S32 index = face.mEdge[j * 3 + k];
if (index == -1)
{
// silhouette edge, currently only cubes, so no other conditions
S32 v1 = face.mIndices[j * 3 + k];
S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)];
LLVector4a t;
mat.affineTransform(v[v1], t);
vertices.push_back(LLVector3(t[0], t[1], t[2]));
norm_mat.rotate(n[v1], t);
t.normalize3fast();
normals.push_back(LLVector3(t[0], t[1], t[2]));
mat.affineTransform(v[v2], t);
vertices.push_back(LLVector3(t[0], t[1], t[2]));
norm_mat.rotate(n[v2], t);
t.normalize3fast();
normals.push_back(LLVector3(t[0], t[1], t[2]));
}
}
}
}
else {
else
{
//==============================================
//DEBUG draw edge map instead of silhouette edge
@@ -4709,6 +4785,7 @@ LLVolumeFace::~LLVolumeFace()
{
ll_aligned_free_16(mExtents);
mExtents = NULL;
mCenter = NULL;
freeData();
}
@@ -5556,10 +5633,17 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
if (!partial_build)
{
resizeIndices(grid_size*grid_size*6);
if (!volume->isMeshAssetLoaded())
{
mEdge.resize(grid_size*grid_size * 6);
}
U16* out = mIndices;
S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
int cur_edge = 0;
for(S32 gx = 0;gx<grid_size;gx++)
{
@@ -5570,7 +5654,49 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
for(S32 i=5;i>=0;i--)
{
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
}
}
S32 edge_value = grid_size * 2 * gy + gx * 2;
if (gx > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1; // Mark face to higlight it
}
if (gy < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
if (gx < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gy > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
}
else
{
@@ -5578,6 +5704,48 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
{
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
}
S32 edge_value = grid_size * 2 * gy + gx * 2;
if (gy > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gx < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
if (gy < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gx > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
}
}
}
@@ -6056,6 +6224,9 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
allocateTangents(0);
allocateVertices(num_verts);
mNumVertices = num_verts;
// Force update
mJointRiggingInfoTab.clear();
}
void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
@@ -6201,78 +6372,6 @@ void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v,
}
}
void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in)
{
U16 offset = mNumVertices;
S32 new_count = face.mNumVertices + mNumVertices;
if (new_count > 65536)
{
LL_ERRS() << "Cannot append face -- 16-bit overflow will occur." << LL_ENDL;
}
if (face.mNumVertices == 0)
{
LL_ERRS() << "Cannot append empty face." << LL_ENDL;
}
allocateVertices(new_count, true);
mNumVertices = new_count;
//get destination address of appended face
LLVector4a* dst_pos = mPositions+offset;
LLVector2* dst_tc = mTexCoords+offset;
LLVector4a* dst_norm = mNormals+offset;
//get source addresses of appended face
const LLVector4a* src_pos = face.mPositions;
const LLVector2* src_tc = face.mTexCoords;
const LLVector4a* src_norm = face.mNormals;
//load aligned matrices
LLMatrix4a mat, norm_mat;
mat.loadu(mat_in);
norm_mat.loadu(norm_mat_in);
for (U32 i = 0; i < (U32)face.mNumVertices; ++i)
{
//transform appended face position and store
mat.affineTransform(src_pos[i], dst_pos[i]);
//transform appended face normal and store
norm_mat.rotate(src_norm[i], dst_norm[i]);
dst_norm[i].normalize3fast();
//copy appended face texture coordinate
dst_tc[i] = src_tc[i];
if (offset == 0 && i == 0)
{ //initialize bounding box
mExtents[0] = mExtents[1] = dst_pos[i];
}
else
{
//stretch bounding box
update_min_max(mExtents[0], mExtents[1], dst_pos[i]);
}
}
new_count = mNumIndices + face.mNumIndices;
allocateIndices(mNumIndices + face.mNumIndices, true);
//get destination address into new index buffer
U16* dst_idx = mIndices+mNumIndices;
mNumIndices = new_count;
for (U32 i = 0; i < (U32)face.mNumIndices; ++i)
{ //copy indices, offsetting by old vertex count
dst_idx[i] = face.mIndices[i]+offset;
}
}
BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
{
BOOL flat = mTypeMask & FLAT_MASK;

View File

@@ -60,6 +60,7 @@ class LLVolumeTriangle;
#include "llpointer.h"
#include "llfile.h"
#include "llalignedarray.h"
#include "llrigginginfo.h"
//============================================================================
@@ -870,8 +871,6 @@ public:
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
void createTangents();
void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
void resizeVertices(S32 num_verts);
void allocateTangents(S32 num_verts);
@@ -961,6 +960,10 @@ public:
mutable BOOL mWeightsScrubbed;
// Which joints are rigged to, and the bounding box of any rigged
// vertices per joint.
LLJointRiggingInfoTab mJointRiggingInfoTab;
LLOctreeNode<LLVolumeTriangle>* mOctree;
//whether or not face has been cache optimized
@@ -1059,7 +1062,7 @@ public:
U32 mFaceMask; // bit array of which faces exist in this volume
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder);
void copyVolumeFaces(const LLVolume* volume);
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
@@ -1068,7 +1071,8 @@ public:
private:
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
F32 sculptGetSurfaceArea();
void sculptGeneratePlaceholder();
void sculptGenerateEmptyPlaceholder();
void sculptGenerateSpherePlaceholder();
void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);