Merge
commit
ac4e4607b8
|
|
@ -2143,56 +2143,6 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs
|
|||
return retval;
|
||||
}
|
||||
|
||||
BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name)
|
||||
{
|
||||
std::ifstream is;
|
||||
|
||||
is.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
|
||||
BOOL success = createVolumeFacesFromStream(is);
|
||||
|
||||
is.close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)
|
||||
{
|
||||
mSculptLevel = -1; // default is an error occured
|
||||
|
||||
LLSD header;
|
||||
{
|
||||
if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
|
||||
{
|
||||
llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string nm[] =
|
||||
{
|
||||
"lowest_lod",
|
||||
"low_lod",
|
||||
"medium_lod",
|
||||
"high_lod",
|
||||
"physics_shape",
|
||||
};
|
||||
|
||||
const S32 MODEL_LODS = 5;
|
||||
|
||||
S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
|
||||
|
||||
if (header[nm[lod]]["offset"].asInteger() == -1 ||
|
||||
header[nm[lod]]["size"].asInteger() == 0 )
|
||||
{ //cannot load requested LOD
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
|
||||
|
||||
return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger());
|
||||
}
|
||||
|
||||
bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
{
|
||||
//input stream is now pointing at a zlib compressed block of LLSD
|
||||
|
|
|
|||
|
|
@ -1048,8 +1048,6 @@ protected:
|
|||
BOOL generate();
|
||||
void createVolumeFaces();
|
||||
public:
|
||||
virtual BOOL createVolumeFacesFromFile(const std::string& file_name);
|
||||
virtual BOOL createVolumeFacesFromStream(std::istream& is);
|
||||
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
|
||||
|
||||
virtual void makeTetrahedron();
|
||||
|
|
|
|||
|
|
@ -775,43 +775,6 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLModel::createVolumeFacesFromFile(const std::string& file_name)
|
||||
{
|
||||
DAE dae;
|
||||
domCOLLADA* dom = dae.open(file_name);
|
||||
if (dom)
|
||||
{
|
||||
daeDatabase* db = dae.getDatabase();
|
||||
|
||||
daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
|
||||
|
||||
mVolumeFaces.clear();
|
||||
mMaterialList.clear();
|
||||
|
||||
for (daeInt idx = 0; idx < count; ++idx)
|
||||
{
|
||||
domMesh* mesh = NULL;
|
||||
|
||||
db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
|
||||
|
||||
if (mesh)
|
||||
{
|
||||
addVolumeFacesFromDomMesh(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (getNumVolumeFaces() > 0)
|
||||
{
|
||||
optimizeVolumeFaces();
|
||||
normalizeVolumeFaces();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
||||
{
|
||||
LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
|
||||
|
|
@ -1351,16 +1314,6 @@ std::string LLModel::getElementLabel(daeElement *element)
|
|||
return std::string("object");
|
||||
}
|
||||
|
||||
//static
|
||||
LLModel* LLModel::loadModelFromDae(std::string filename)
|
||||
{
|
||||
LLVolumeParams volume_params;
|
||||
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
|
||||
LLModel* ret = new LLModel(volume_params, 0.f);
|
||||
ret->createVolumeFacesFromFile(filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static
|
||||
LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
|
||||
{
|
||||
|
|
@ -1473,49 +1426,7 @@ LLSD LLModel::writeModel(
|
|||
|
||||
if (skinning)
|
||||
{ //write skinning block
|
||||
if (high->mJointList.size() != high->mInvBindMatrix.size())
|
||||
{
|
||||
llerrs << "WTF?" << llendl;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < high->mJointList.size(); ++i)
|
||||
{
|
||||
mdl["skin"]["joint_names"][i] = high->mJointList[i];
|
||||
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mdl["skin"]["inverse_bind_matrix"][i][j*4+k] = high->mInvBindMatrix[i].mMatrix[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
mdl["skin"]["bind_shape_matrix"][i*4+j] = high->mBindShapeMatrix.mMatrix[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( upload_joints && high->mAlternateBindMatrix.size() > 0 )
|
||||
{
|
||||
for (U32 i = 0; i < high->mJointList.size(); ++i)
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mdl["skin"]["alt_inverse_bind_matrix"][i][j*4+k] = high->mAlternateBindMatrix[i].mMatrix[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mdl["skin"]["pelvis_offset"] = high->mPelvisOffset;
|
||||
}
|
||||
|
||||
mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints);
|
||||
}
|
||||
|
||||
if (!decomp.empty() || !base_hull.empty())
|
||||
|
|
@ -1897,12 +1808,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
|
|||
return header;
|
||||
}
|
||||
|
||||
//static
|
||||
LLModel* LLModel::loadModelFromAsset(std::string filename, S32 lod)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
||||
{
|
||||
weight_map::iterator iter = mSkinWeights.find(pos);
|
||||
|
|
@ -1976,27 +1881,380 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
|||
void LLModel::setConvexHullDecomposition(
|
||||
const LLModel::convex_hull_decomposition& decomp)
|
||||
{
|
||||
mConvexHullDecomp = decomp;
|
||||
mPhysics.mHull = decomp;
|
||||
mPhysics.mMesh.clear();
|
||||
updateHullCenters();
|
||||
}
|
||||
|
||||
mHullCenter.resize(mConvexHullDecomp.size());
|
||||
void LLModel::updateHullCenters()
|
||||
{
|
||||
mHullCenter.resize(mPhysics.mHull.size());
|
||||
mHullPoints = 0;
|
||||
mCenterOfHullCenters.clear();
|
||||
|
||||
for (U32 i = 0; i < decomp.size(); ++i)
|
||||
for (U32 i = 0; i < mPhysics.mHull.size(); ++i)
|
||||
{
|
||||
LLVector3 cur_center;
|
||||
|
||||
for (U32 j = 0; j < decomp[i].size(); ++j)
|
||||
for (U32 j = 0; j < mPhysics.mHull[i].size(); ++j)
|
||||
{
|
||||
cur_center += decomp[i][j];
|
||||
cur_center += mPhysics.mHull[i][j];
|
||||
}
|
||||
mCenterOfHullCenters += cur_center;
|
||||
cur_center *= 1.f/decomp[i].size();
|
||||
cur_center *= 1.f/mPhysics.mHull[i].size();
|
||||
mHullCenter[i] = cur_center;
|
||||
mHullPoints += decomp[i].size();
|
||||
mHullPoints += mPhysics.mHull[i].size();
|
||||
}
|
||||
|
||||
mCenterOfHullCenters *= 1.f / mHullPoints;
|
||||
}
|
||||
|
||||
bool LLModel::loadModel(std::istream& is)
|
||||
{
|
||||
mSculptLevel = -1; // default is an error occured
|
||||
|
||||
LLSD header;
|
||||
{
|
||||
if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
|
||||
{
|
||||
llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string nm[] =
|
||||
{
|
||||
"lowest_lod",
|
||||
"low_lod",
|
||||
"medium_lod",
|
||||
"high_lod",
|
||||
"physics_shape",
|
||||
};
|
||||
|
||||
const S32 MODEL_LODS = 5;
|
||||
|
||||
S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
|
||||
|
||||
if (header[nm[lod]]["offset"].asInteger() == -1 ||
|
||||
header[nm[lod]]["size"].asInteger() == 0 )
|
||||
{ //cannot load requested LOD
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_skin = header["skin"]["offset"].asInteger() >=0 &&
|
||||
header["skin"]["size"].asInteger() > 0;
|
||||
|
||||
if (lod == LLModel::LOD_HIGH)
|
||||
{ //try to load skin info and decomp info
|
||||
std::ios::pos_type cur_pos = is.tellg();
|
||||
loadSkinInfo(header, is);
|
||||
is.seekg(cur_pos);
|
||||
}
|
||||
|
||||
if (lod == LLModel::LOD_PHYSICS)
|
||||
{
|
||||
std::ios::pos_type cur_pos = is.tellg();
|
||||
loadDecomposition(header, is);
|
||||
is.seekg(cur_pos);
|
||||
}
|
||||
|
||||
is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
|
||||
|
||||
if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()))
|
||||
{
|
||||
if (has_skin)
|
||||
{
|
||||
//build out mSkinWeight from face info
|
||||
for (S32 i = 0; i < getNumVolumeFaces(); ++i)
|
||||
{
|
||||
const LLVolumeFace& face = getVolumeFace(i);
|
||||
|
||||
if (face.mWeights)
|
||||
{
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector4a& w = face.mWeights[j];
|
||||
|
||||
std::vector<JointWeight> wght;
|
||||
|
||||
for (S32 k = 0; k < 4; ++k)
|
||||
{
|
||||
S32 idx = (S32) w[k];
|
||||
F32 f = w[k] - idx;
|
||||
if (f > 0.f)
|
||||
{
|
||||
wght.push_back(JointWeight(idx, f));
|
||||
}
|
||||
}
|
||||
|
||||
if (!wght.empty())
|
||||
{
|
||||
LLVector3 pos(face.mPositions[j].getF32ptr());
|
||||
mSkinWeights[pos] = wght;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
|
||||
{
|
||||
S32 offset = header["skin"]["offset"].asInteger();
|
||||
S32 size = header["skin"]["size"].asInteger();
|
||||
|
||||
if (offset >= 0 && size > 0)
|
||||
{
|
||||
is.seekg(offset, std::ios_base::cur);
|
||||
|
||||
LLSD skin_data;
|
||||
|
||||
if (unzip_llsd(skin_data, is, size))
|
||||
{
|
||||
mSkinInfo.fromLLSD(skin_data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
|
||||
{
|
||||
S32 offset = header["decomposition"]["offset"].asInteger();
|
||||
S32 size = header["decomposition"]["size"].asInteger();
|
||||
|
||||
if (offset >= 0 && size > 0)
|
||||
{
|
||||
is.seekg(offset, std::ios_base::cur);
|
||||
|
||||
LLSD data;
|
||||
|
||||
if (unzip_llsd(data, is, size))
|
||||
{
|
||||
mPhysics.fromLLSD(data);
|
||||
updateHullCenters();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin)
|
||||
{
|
||||
fromLLSD(skin);
|
||||
}
|
||||
|
||||
void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
{
|
||||
if (skin.has("joint_names"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["joint_names"].size(); ++i)
|
||||
{
|
||||
mJointNames.push_back(skin["joint_names"][i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
|
||||
mInvBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("bind_shape_matrix"))
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("alt_inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
|
||||
mAlternateBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("pelvis_offset"))
|
||||
{
|
||||
mPelvisOffset = skin["pelvis_offset"].asReal();
|
||||
}
|
||||
}
|
||||
|
||||
LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const
|
||||
{
|
||||
LLSD ret;
|
||||
|
||||
for (U32 i = 0; i < mJointNames.size(); ++i)
|
||||
{
|
||||
ret["joint_names"][i] = mJointNames[i];
|
||||
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
ret["bind_shape_matrix"][i*4+j] = mBindShapeMatrix.mMatrix[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
if ( include_joints && mAlternateBindMatrix.size() > 0 )
|
||||
{
|
||||
for (U32 i = 0; i < mJointNames.size(); ++i)
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret["pelvis_offset"] = mPelvisOffset;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLModel::Decomposition::Decomposition(LLSD& data)
|
||||
{
|
||||
fromLLSD(data);
|
||||
}
|
||||
|
||||
void LLModel::Decomposition::fromLLSD(LLSD& decomp)
|
||||
{
|
||||
if (decomp.has("HullList"))
|
||||
{
|
||||
// updated for const-correctness. gcc is picky about this type of thing - Nyx
|
||||
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
|
||||
const LLSD::Binary& position = decomp["Position"].asBinary();
|
||||
|
||||
U16* p = (U16*) &position[0];
|
||||
|
||||
mHull.resize(hulls.size());
|
||||
|
||||
LLVector3 min;
|
||||
LLVector3 max;
|
||||
LLVector3 range;
|
||||
|
||||
min.setValue(decomp["Min"]);
|
||||
max.setValue(decomp["Max"]);
|
||||
range = max-min;
|
||||
|
||||
for (U32 i = 0; i < hulls.size(); ++i)
|
||||
{
|
||||
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
|
||||
|
||||
for (U32 j = 0; j < count; ++j)
|
||||
{
|
||||
mHull[i].push_back(LLVector3(
|
||||
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
|
||||
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
|
||||
(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
|
||||
p += 3;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (decomp.has("Hull"))
|
||||
{
|
||||
const LLSD::Binary& position = decomp["Hull"].asBinary();
|
||||
|
||||
U16* p = (U16*) &position[0];
|
||||
|
||||
LLVector3 min;
|
||||
LLVector3 max;
|
||||
LLVector3 range;
|
||||
|
||||
min.setValue(decomp["Min"]);
|
||||
max.setValue(decomp["Max"]);
|
||||
range = max-min;
|
||||
|
||||
U16 count = position.size()/6;
|
||||
|
||||
for (U32 j = 0; j < count; ++j)
|
||||
{
|
||||
mBaseHull.push_back(LLVector3(
|
||||
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
|
||||
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
|
||||
(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//empty base hull mesh to indicate decomposition has been loaded
|
||||
//but contains no base hull
|
||||
mBaseHullMesh.clear();;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
|
||||
{
|
||||
if (!rhs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMeshID != rhs->mMeshID)
|
||||
{
|
||||
llerrs << "Attempted to merge with decomposition of some other mesh." << llendl;
|
||||
}
|
||||
|
||||
if (mBaseHull.empty())
|
||||
{ //take base hull and decomposition from rhs
|
||||
mHull = rhs->mHull;
|
||||
mBaseHull = rhs->mBaseHull;
|
||||
mMesh = rhs->mMesh;
|
||||
mBaseHullMesh = rhs->mBaseHullMesh;
|
||||
}
|
||||
|
||||
if (mPhysicsShapeMesh.empty())
|
||||
{ //take physics shape mesh from rhs
|
||||
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef LL_LLMODEL_H
|
||||
#define LL_LLMODEL_H
|
||||
|
||||
#include "llpointer.h"
|
||||
#include "llvolume.h"
|
||||
#include "v4math.h"
|
||||
#include "m4math.h"
|
||||
|
|
@ -36,6 +37,24 @@ class domMesh;
|
|||
|
||||
#define MAX_MODEL_FACES 8
|
||||
|
||||
|
||||
class LLMeshSkinInfo
|
||||
{
|
||||
public:
|
||||
LLUUID mMeshID;
|
||||
std::vector<std::string> mJointNames;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
std::map<std::string, U32> mJointMap;
|
||||
|
||||
LLMeshSkinInfo() { }
|
||||
LLMeshSkinInfo(LLSD& data);
|
||||
void fromLLSD(LLSD& data);
|
||||
LLSD asLLSD(bool include_joints) const;
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
float mPelvisOffset;
|
||||
};
|
||||
|
||||
class LLModel : public LLVolume
|
||||
{
|
||||
public:
|
||||
|
|
@ -58,6 +77,9 @@ public:
|
|||
LLModel(LLVolumeParams& params, F32 detail);
|
||||
~LLModel();
|
||||
|
||||
bool loadModel(std::istream& is);
|
||||
bool loadSkinInfo(LLSD& header, std::istream& is);
|
||||
bool loadDecomposition(LLSD& header, std::istream& is);
|
||||
static LLSD writeModel(
|
||||
std::string filename,
|
||||
LLModel* physics,
|
||||
|
|
@ -98,8 +120,6 @@ public:
|
|||
LLSD& mdl,
|
||||
BOOL nowrite = FALSE);
|
||||
|
||||
static LLModel* loadModelFromAsset(std::string filename, S32 lod);
|
||||
static LLModel* loadModelFromDae(std::string filename);
|
||||
static LLModel* loadModelFromDomMesh(domMesh* mesh);
|
||||
static std::string getElementLabel(daeElement* element);
|
||||
std::string getName() const;
|
||||
|
|
@ -177,17 +197,8 @@ public:
|
|||
//get list of weight influences closest to given position
|
||||
weight_list& getJointInfluences(const LLVector3& pos);
|
||||
|
||||
//should always be true that mJointList[mJointMap["foo"]] == "foo"
|
||||
|
||||
//map of joint names to joint index
|
||||
std::map<std::string, U32> mJointMap;
|
||||
|
||||
//list of joint names
|
||||
std::vector<std::string> mJointList;
|
||||
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
LLMeshSkinInfo mSkinInfo;
|
||||
|
||||
std::string mRequestedLabel; // name requested in UI, if any.
|
||||
std::string mLabel; // name computed from dae.
|
||||
|
||||
|
|
@ -197,9 +208,10 @@ public:
|
|||
float mPelvisOffset;
|
||||
// convex hull decomposition
|
||||
S32 mDecompID;
|
||||
convex_hull_decomposition mConvexHullDecomp;
|
||||
|
||||
void setConvexHullDecomposition(
|
||||
const convex_hull_decomposition& decomp);
|
||||
void updateHullCenters();
|
||||
|
||||
LLVector3 mCenterOfHullCenters;
|
||||
std::vector<LLVector3> mHullCenter;
|
||||
|
|
@ -208,9 +220,46 @@ public:
|
|||
//ID for storing this model in a .slm file
|
||||
S32 mLocalID;
|
||||
|
||||
class PhysicsMesh
|
||||
{
|
||||
public:
|
||||
std::vector<LLVector3> mPositions;
|
||||
std::vector<LLVector3> mNormals;
|
||||
|
||||
void clear()
|
||||
{
|
||||
mPositions.clear();
|
||||
mNormals.clear();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return mPositions.empty();
|
||||
}
|
||||
};
|
||||
|
||||
class Decomposition
|
||||
{
|
||||
public:
|
||||
Decomposition() { }
|
||||
Decomposition(LLSD& data);
|
||||
void fromLLSD(LLSD& data);
|
||||
|
||||
void merge(const Decomposition* rhs);
|
||||
|
||||
LLUUID mMeshID;
|
||||
LLModel::convex_hull_decomposition mHull;
|
||||
LLModel::hull mBaseHull;
|
||||
|
||||
std::vector<LLModel::PhysicsMesh> mMesh;
|
||||
LLModel::PhysicsMesh mBaseHullMesh;
|
||||
LLModel::PhysicsMesh mPhysicsShapeMesh;
|
||||
};
|
||||
|
||||
Decomposition mPhysics;
|
||||
|
||||
protected:
|
||||
void addVolumeFacesFromDomMesh(domMesh* mesh);
|
||||
virtual BOOL createVolumeFacesFromFile(const std::string& file_name);
|
||||
virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -236,6 +236,22 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
|
|||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm)
|
||||
{
|
||||
U32 count = pos.size();
|
||||
llassert(norm.size() >= pos.size());
|
||||
|
||||
unbind();
|
||||
|
||||
setupClientArrays(MAP_VERTEX | MAP_NORMAL);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, pos[0].mV);
|
||||
glNormalPointer(GL_FLOAT, 0, norm[0].mV);
|
||||
|
||||
glDrawArrays(sGLMode[mode], 0, count);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
|
||||
{
|
||||
if (start >= (U32) mRequestedNumVerts ||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ public:
|
|||
static void initClass(bool use_vbo, bool no_vbo_mapping);
|
||||
static void cleanupClass();
|
||||
static void setupClientArrays(U32 data_mask);
|
||||
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
|
||||
|
||||
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
|
||||
static void unbind(); //unbind any bound vertex buffer
|
||||
|
||||
|
|
|
|||
|
|
@ -389,7 +389,11 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
|
|||
gAgentAvatarp->resetJointPositions();
|
||||
}
|
||||
|
||||
|
||||
if ( mModelPreview )
|
||||
{
|
||||
delete mModelPreview;
|
||||
}
|
||||
|
||||
if (mGLName)
|
||||
{
|
||||
|
|
@ -1326,17 +1330,19 @@ bool LLModelLoader::doLoadModel()
|
|||
{ //get bind shape matrix
|
||||
domFloat4x4& dom_value = bind_mat->getValue();
|
||||
|
||||
LLMeshSkinInfo& skin_info = model->mSkinInfo;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for(int j = 0; j < 4; j++)
|
||||
{
|
||||
model->mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
|
||||
skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
|
||||
}
|
||||
}
|
||||
|
||||
LLMatrix4 trans = normalized_transformation;
|
||||
trans *= model->mBindShapeMatrix;
|
||||
model->mBindShapeMatrix = trans;
|
||||
trans *= skin_info.mBindShapeMatrix;
|
||||
skin_info.mBindShapeMatrix = trans;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1475,7 +1481,7 @@ bool LLModelLoader::doLoadModel()
|
|||
xsNMTOKEN semantic = input->getSemantic();
|
||||
|
||||
if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0)
|
||||
{ //found joint source, fill model->mJointMap and model->mJointList
|
||||
{ //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames
|
||||
daeElement* elem = input->getSource().getElement();
|
||||
|
||||
domSource* source = daeSafeCast<domSource>(elem);
|
||||
|
|
@ -1496,8 +1502,8 @@ bool LLModelLoader::doLoadModel()
|
|||
{
|
||||
name = mJointMap[name];
|
||||
}
|
||||
model->mJointList.push_back(name);
|
||||
model->mJointMap[name] = j;
|
||||
model->mSkinInfo.mJointNames.push_back(name);
|
||||
model->mSkinInfo.mJointMap[name] = j;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1514,8 +1520,8 @@ bool LLModelLoader::doLoadModel()
|
|||
{
|
||||
name = mJointMap[name];
|
||||
}
|
||||
model->mJointList.push_back(name);
|
||||
model->mJointMap[name] = j;
|
||||
model->mSkinInfo.mJointNames.push_back(name);
|
||||
model->mSkinInfo.mJointMap[name] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1544,7 +1550,7 @@ bool LLModelLoader::doLoadModel()
|
|||
}
|
||||
}
|
||||
|
||||
model->mInvBindMatrix.push_back(mat);
|
||||
model->mSkinInfo.mInvBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1555,8 +1561,8 @@ bool LLModelLoader::doLoadModel()
|
|||
//(which means we have all the joints that are required for an avatar versus
|
||||
//a skinned asset attached to a node in a file that contains an entire skeleton,
|
||||
//but does not use the skeleton).
|
||||
mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mJointList ) );
|
||||
if ( !skeletonWithNoRootNode && !model->mJointList.empty() && mPreview->isRigValid() )
|
||||
mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mSkinInfo.mJointNames ) );
|
||||
if ( !skeletonWithNoRootNode && !model->mSkinInfo.mJointNames.empty() && mPreview->isRigValid() )
|
||||
{
|
||||
mResetJoints = true;
|
||||
}
|
||||
|
|
@ -1596,8 +1602,8 @@ bool LLModelLoader::doLoadModel()
|
|||
//in the same order as they were stored in the joint buffer. The joints associated
|
||||
//with the skeleton are not stored in the same order as they are in the exported joint buffer.
|
||||
//This remaps the skeletal joints to be in the same order as the joints stored in the model.
|
||||
std::vector<std::string> :: const_iterator jointIt = model->mJointList.begin();
|
||||
const int jointCnt = model->mJointList.size();
|
||||
std::vector<std::string> :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin();
|
||||
const int jointCnt = model->mSkinInfo.mJointNames.size();
|
||||
for ( int i=0; i<jointCnt; ++i, ++jointIt )
|
||||
{
|
||||
std::string lookingForJoint = (*jointIt).c_str();
|
||||
|
|
@ -1606,9 +1612,9 @@ bool LLModelLoader::doLoadModel()
|
|||
if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
|
||||
{
|
||||
LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
|
||||
LLMatrix4 newInverse = model->mInvBindMatrix[i];
|
||||
LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
|
||||
newInverse.setTranslation( jointTransforms[lookingForJoint].getTranslation() );
|
||||
model->mAlternateBindMatrix.push_back( newInverse );
|
||||
model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1813,10 +1819,15 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
|
|||
{
|
||||
std::stringstream str(mesh[i].asString());
|
||||
LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod);
|
||||
if (loaded_model->createVolumeFacesFromStream(str))
|
||||
if (loaded_model->loadModel(str))
|
||||
{
|
||||
loaded_model->mLocalID = i;
|
||||
model[lod].push_back(loaded_model);
|
||||
|
||||
if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty())
|
||||
{ //check to see if rig is valid
|
||||
mPreview->setRigValid( doesJointArrayContainACompleteRig( loaded_model->mSkinInfo.mJointNames ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1878,8 +1889,6 @@ void LLModelLoader::loadModelCallback()
|
|||
{ //wait until this thread is stopped before deleting self
|
||||
apr_sleep(100);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void LLModelLoader::handlePivotPoint( daeElement* pRoot )
|
||||
|
|
@ -2455,6 +2464,7 @@ LLModelPreview::~LLModelPreview()
|
|||
{
|
||||
if (mModelLoader)
|
||||
{
|
||||
delete mModelLoader;
|
||||
mModelLoader->mPreview = NULL;
|
||||
}
|
||||
//*HACK : *TODO : turn this back on when we understand why this crashes
|
||||
|
|
@ -2510,8 +2520,8 @@ U32 LLModelPreview::calcResourceCost()
|
|||
|
||||
LLModel::convex_hull_decomposition& decomp =
|
||||
instance.mLOD[LLModel::LOD_PHYSICS] ?
|
||||
instance.mLOD[LLModel::LOD_PHYSICS]->mConvexHullDecomp :
|
||||
instance.mModel->mConvexHullDecomp;
|
||||
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics.mHull :
|
||||
instance.mModel->mPhysics.mHull;
|
||||
|
||||
LLSD ret = LLModel::writeModel(
|
||||
"",
|
||||
|
|
@ -2729,8 +2739,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
|
|||
|
||||
LLModel::convex_hull_decomposition& decomp =
|
||||
instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
|
||||
instance.mLOD[LLModel::LOD_PHYSICS]->mConvexHullDecomp :
|
||||
instance.mModel->mConvexHullDecomp;
|
||||
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics.mHull :
|
||||
instance.mModel->mPhysics.mHull;
|
||||
|
||||
LLModel::writeModel(str,
|
||||
instance.mLOD[LLModel::LOD_PHYSICS],
|
||||
|
|
@ -2901,6 +2911,9 @@ void LLModelPreview::loadModelCallback(S32 lod)
|
|||
mBaseModel.clear();
|
||||
mBaseScene.clear();
|
||||
|
||||
bool skin_weights = false;
|
||||
bool joint_positions = false;
|
||||
|
||||
for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
|
||||
{ //for each LoD
|
||||
|
||||
|
|
@ -2934,11 +2947,39 @@ void LLModelPreview::loadModelCallback(S32 lod)
|
|||
}
|
||||
|
||||
mModel[lod][idx] = list_iter->mModel;
|
||||
if (!list_iter->mModel->mSkinWeights.empty())
|
||||
{
|
||||
skin_weights = true;
|
||||
|
||||
if (!list_iter->mModel->mSkinInfo.mAlternateBindMatrix.empty())
|
||||
{
|
||||
joint_positions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mFMP)
|
||||
{
|
||||
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP;
|
||||
|
||||
if (skin_weights)
|
||||
{ //enable uploading/previewing of skin weights if present in .slm file
|
||||
fmp->enableViewOption("show_skin_weight");
|
||||
mViewOption["show_skin_weight"] = true;
|
||||
fmp->childSetValue("upload_skin", true);
|
||||
}
|
||||
|
||||
if (joint_positions)
|
||||
{
|
||||
fmp->enableViewOption("show_joint_positions");
|
||||
mViewOption["show_joint_positions"] = true;
|
||||
fmp->childSetValue("upload_joints", true);
|
||||
}
|
||||
}
|
||||
|
||||
//copy high lod to base scene for LoD generation
|
||||
mBaseScene = mScene[LLModel::LOD_HIGH];
|
||||
mBaseModel = mModel[LLModel::LOD_HIGH];
|
||||
|
|
@ -2952,14 +2993,8 @@ void LLModelPreview::loadModelCallback(S32 lod)
|
|||
mScene[lod] = mModelLoader->mScene;
|
||||
mVertexBuffer[lod].clear();
|
||||
|
||||
if (lod == LLModel::LOD_PHYSICS)
|
||||
{
|
||||
mPhysicsMesh.clear();
|
||||
}
|
||||
|
||||
setPreviewLOD(lod);
|
||||
|
||||
|
||||
if (lod == LLModel::LOD_HIGH)
|
||||
{ //save a copy of the highest LOD for automatic LOD manipulation
|
||||
if (mBaseModel.empty())
|
||||
|
|
@ -3082,11 +3117,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
|
|||
return;
|
||||
}
|
||||
|
||||
if (which_lod == LLModel::LOD_PHYSICS)
|
||||
{ //clear physics mesh map
|
||||
mPhysicsMesh.clear();
|
||||
}
|
||||
|
||||
LLVertexBuffer::unbind();
|
||||
|
||||
stop_gloderror();
|
||||
|
|
@ -3415,11 +3445,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
|
|||
//of an open problem).
|
||||
target_model->mPosition = base->mPosition;
|
||||
target_model->mSkinWeights = base->mSkinWeights;
|
||||
target_model->mJointMap = base->mJointMap;
|
||||
target_model->mJointList = base->mJointList;
|
||||
target_model->mInvBindMatrix = base->mInvBindMatrix;
|
||||
target_model->mBindShapeMatrix = base->mBindShapeMatrix;
|
||||
target_model->mAlternateBindMatrix = base->mAlternateBindMatrix;
|
||||
target_model->mSkinInfo = base->mSkinInfo;
|
||||
//copy material list
|
||||
target_model->mMaterialList = base->mMaterialList;
|
||||
|
||||
|
|
@ -3639,7 +3665,7 @@ void LLModelPreview::updateStatusMessages()
|
|||
LLModel* model = mModel[LLModel::LOD_PHYSICS][i];
|
||||
S32 cur_submeshes = model->getNumVolumeFaces();
|
||||
|
||||
LLModel::convex_hull_decomposition& decomp = model->mConvexHullDecomp;
|
||||
LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull;
|
||||
|
||||
if (!decomp.empty())
|
||||
{
|
||||
|
|
@ -4276,12 +4302,17 @@ BOOL LLModelPreview::render()
|
|||
{
|
||||
LLMutexLock(decomp->mMutex);
|
||||
|
||||
std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > >::iterator iter =
|
||||
mPhysicsMesh.find(model);
|
||||
if (iter != mPhysicsMesh.end())
|
||||
LLModel::Decomposition& physics = model->mPhysics;
|
||||
|
||||
if (physics.mMesh.empty())
|
||||
{ //build vertex buffer for physics mesh
|
||||
gMeshRepo.buildPhysicsMesh(physics);
|
||||
}
|
||||
|
||||
if (!physics.mMesh.empty())
|
||||
{ //render hull instead of mesh
|
||||
render_mesh = false;
|
||||
for (U32 i = 0; i < iter->second.size(); ++i)
|
||||
for (U32 i = 0; i < physics.mMesh.size(); ++i)
|
||||
{
|
||||
if (explode > 0.f)
|
||||
{
|
||||
|
|
@ -4300,14 +4331,8 @@ BOOL LLModelPreview::render()
|
|||
hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
|
||||
}
|
||||
|
||||
LLVertexBuffer* buff = iter->second[i];
|
||||
if (buff)
|
||||
{
|
||||
buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);
|
||||
|
||||
glColor4ubv(hull_colors[i].mV);
|
||||
buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
|
||||
}
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
|
||||
|
||||
if (explode > 0.f)
|
||||
{
|
||||
|
|
@ -4391,12 +4416,12 @@ BOOL LLModelPreview::render()
|
|||
|
||||
//build matrix palette
|
||||
LLMatrix4 mat[64];
|
||||
for (U32 j = 0; j < model->mJointList.size(); ++j)
|
||||
for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j)
|
||||
{
|
||||
LLJoint* joint = avatar->getJoint(model->mJointList[j]);
|
||||
LLJoint* joint = avatar->getJoint(model->mSkinInfo.mJointNames[j]);
|
||||
if (joint)
|
||||
{
|
||||
mat[j] = model->mInvBindMatrix[j];
|
||||
mat[j] = model->mSkinInfo.mInvBindMatrix[j];
|
||||
mat[j] *= joint->getWorldMatrix();
|
||||
}
|
||||
}
|
||||
|
|
@ -4437,7 +4462,7 @@ BOOL LLModelPreview::render()
|
|||
//VECTORIZE THIS
|
||||
LLVector3 v(face.mPositions[j].getF32ptr());
|
||||
|
||||
v = v * model->mBindShapeMatrix;
|
||||
v = v * model->mSkinInfo.mBindShapeMatrix;
|
||||
v = v * final_mat;
|
||||
|
||||
position[j] = v;
|
||||
|
|
@ -4687,7 +4712,6 @@ void LLFloaterModelPreview::DecompRequest::completed()
|
|||
{
|
||||
if (sInstance->mModelPreview)
|
||||
{
|
||||
sInstance->mModelPreview->mPhysicsMesh[mModel] = mHullMesh;
|
||||
sInstance->mModelPreview->mDirty = true;
|
||||
LLFloaterModelPreview::sInstance->mModelPreview->refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,8 +358,7 @@ public:
|
|||
U32 mGroup;
|
||||
std::map<LLPointer<LLModel>, U32> mObject;
|
||||
U32 mMaxTriangleLimit;
|
||||
std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > > mPhysicsMesh;
|
||||
|
||||
|
||||
LLMeshUploadThread::instance_list mUploadData;
|
||||
std::set<LLViewerFetchedTexture* > mTextureSet;
|
||||
|
||||
|
|
|
|||
|
|
@ -485,7 +485,6 @@ void LLFloaterModelWizard::DecompRequest::completed()
|
|||
{
|
||||
if (sInstance->mModelPreview)
|
||||
{
|
||||
sInstance->mModelPreview->mPhysicsMesh[mModel] = mHullMesh;
|
||||
sInstance->mModelPreview->mDirty = true;
|
||||
LLFloaterModelWizard::sInstance->mModelPreview->refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,19 +108,13 @@ U32 get_volume_memory_size(const LLVolume* volume)
|
|||
return indices*2+vertices*11+sizeof(LLVolume)+sizeof(LLVolumeFace)*volume->getNumVolumeFaces();
|
||||
}
|
||||
|
||||
LLVertexBuffer* get_vertex_buffer_from_mesh(LLCDMeshData& mesh, F32 scale = 1.f)
|
||||
void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, F32 scale = 1.f)
|
||||
{
|
||||
LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0);
|
||||
buff->allocateBuffer(mesh.mNumTriangles*3, 0, true);
|
||||
|
||||
LLStrider<LLVector3> pos;
|
||||
LLStrider<LLVector3> norm;
|
||||
res.mPositions.clear();
|
||||
res.mNormals.clear();
|
||||
|
||||
buff->getVertexStrider(pos);
|
||||
buff->getNormalStrider(norm);
|
||||
|
||||
const F32* v = mesh.mVertexBase;
|
||||
|
||||
|
||||
if (mesh.mIndexType == LLCDMeshData::INT_16)
|
||||
{
|
||||
U16* idx = (U16*) mesh.mIndexBase;
|
||||
|
|
@ -139,13 +133,13 @@ LLVertexBuffer* get_vertex_buffer_from_mesh(LLCDMeshData& mesh, F32 scale = 1.f)
|
|||
LLVector3 n = (v1-v0)%(v2-v0);
|
||||
n.normalize();
|
||||
|
||||
*pos++ = v0*scale;
|
||||
*pos++ = v1*scale;
|
||||
*pos++ = v2*scale;
|
||||
res.mPositions.push_back(v0*scale);
|
||||
res.mPositions.push_back(v1*scale);
|
||||
res.mPositions.push_back(v2*scale);
|
||||
|
||||
*norm++ = n;
|
||||
*norm++ = n;
|
||||
*norm++ = n;
|
||||
res.mNormals.push_back(n);
|
||||
res.mNormals.push_back(n);
|
||||
res.mNormals.push_back(n);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -166,17 +160,15 @@ LLVertexBuffer* get_vertex_buffer_from_mesh(LLCDMeshData& mesh, F32 scale = 1.f)
|
|||
LLVector3 n = (v1-v0)%(v2-v0);
|
||||
n.normalize();
|
||||
|
||||
*(pos++) = v0*scale;
|
||||
*(pos++) = v1*scale;
|
||||
*(pos++) = v2*scale;
|
||||
res.mPositions.push_back(v0*scale);
|
||||
res.mPositions.push_back(v1*scale);
|
||||
res.mPositions.push_back(v2*scale);
|
||||
|
||||
*(norm++) = n;
|
||||
*(norm++) = n;
|
||||
*(norm++) = n;
|
||||
res.mNormals.push_back(n);
|
||||
res.mNormals.push_back(n);
|
||||
res.mNormals.push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
|
|
@ -1111,66 +1103,9 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
|
|||
}
|
||||
|
||||
{
|
||||
LLMeshSkinInfo info;
|
||||
LLMeshSkinInfo info(skin);
|
||||
info.mMeshID = mesh_id;
|
||||
|
||||
if (skin.has("joint_names"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["joint_names"].size(); ++i)
|
||||
{
|
||||
info.mJointNames.push_back(skin["joint_names"][i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
|
||||
info.mInvBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("bind_shape_matrix"))
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
info.mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("alt_inverse_bind_matrix"))
|
||||
{
|
||||
for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
{
|
||||
mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal();
|
||||
}
|
||||
}
|
||||
|
||||
info.mAlternateBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
if (skin.has("pelvis_offset"))
|
||||
{
|
||||
info.mPelvisOffset = skin["pelvis_offset"].asReal();
|
||||
}
|
||||
//llinfos<<"info pelvis offset"<<info.mPelvisOffset<<llendl;
|
||||
mSkinInfoQ.push(info);
|
||||
}
|
||||
|
|
@ -1196,119 +1131,8 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
|
|||
}
|
||||
|
||||
{
|
||||
LLMeshDecomposition* d = new LLMeshDecomposition();
|
||||
LLModel::Decomposition* d = new LLModel::Decomposition(decomp);
|
||||
d->mMeshID = mesh_id;
|
||||
|
||||
if (decomp.has("HullList"))
|
||||
{
|
||||
// updated for const-correctness. gcc is picky about this type of thing - Nyx
|
||||
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
|
||||
const LLSD::Binary& position = decomp["Position"].asBinary();
|
||||
|
||||
U16* p = (U16*) &position[0];
|
||||
|
||||
d->mHull.resize(hulls.size());
|
||||
|
||||
LLVector3 min;
|
||||
LLVector3 max;
|
||||
LLVector3 range;
|
||||
|
||||
min.setValue(decomp["Min"]);
|
||||
max.setValue(decomp["Max"]);
|
||||
range = max-min;
|
||||
|
||||
for (U32 i = 0; i < hulls.size(); ++i)
|
||||
{
|
||||
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
|
||||
|
||||
for (U32 j = 0; j < count; ++j)
|
||||
{
|
||||
d->mHull[i].push_back(LLVector3(
|
||||
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
|
||||
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
|
||||
(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
|
||||
p += 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//get mesh for decomposition
|
||||
for (U32 i = 0; i < d->mHull.size(); ++i)
|
||||
{
|
||||
LLCDHull hull;
|
||||
hull.mNumVertices = d->mHull[i].size();
|
||||
hull.mVertexBase = d->mHull[i][0].mV;
|
||||
hull.mVertexStrideBytes = 12;
|
||||
|
||||
LLCDMeshData mesh;
|
||||
LLCDResult res = LLCD_OK;
|
||||
if (LLConvexDecomposition::getInstance() != NULL)
|
||||
{
|
||||
res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh);
|
||||
}
|
||||
if (res != LLCD_OK)
|
||||
{
|
||||
llwarns << "could not get mesh from hull from convex decomposition lib." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
d->mMesh.push_back(get_vertex_buffer_from_mesh(mesh));
|
||||
}
|
||||
}
|
||||
|
||||
if (decomp.has("Hull"))
|
||||
{
|
||||
const LLSD::Binary& position = decomp["Hull"].asBinary();
|
||||
|
||||
U16* p = (U16*) &position[0];
|
||||
|
||||
LLVector3 min;
|
||||
LLVector3 max;
|
||||
LLVector3 range;
|
||||
|
||||
min.setValue(decomp["Min"]);
|
||||
max.setValue(decomp["Max"]);
|
||||
range = max-min;
|
||||
|
||||
U16 count = position.size()/6;
|
||||
|
||||
for (U32 j = 0; j < count; ++j)
|
||||
{
|
||||
d->mBaseHull.push_back(LLVector3(
|
||||
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
|
||||
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
|
||||
(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
|
||||
p += 3;
|
||||
}
|
||||
|
||||
//get mesh for decomposition
|
||||
LLCDHull hull;
|
||||
hull.mNumVertices = d->mBaseHull.size();
|
||||
hull.mVertexBase = d->mBaseHull[0].mV;
|
||||
hull.mVertexStrideBytes = 12;
|
||||
|
||||
LLCDMeshData mesh;
|
||||
LLCDResult res = LLCD_OK;
|
||||
if (LLConvexDecomposition::getInstance() != NULL)
|
||||
{
|
||||
res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh);
|
||||
}
|
||||
if (res != LLCD_OK)
|
||||
{
|
||||
llwarns << "could not get mesh from hull from convex decomposition lib." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
d->mBaseHullMesh = get_vertex_buffer_from_mesh(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
//empty vertex buffer to indicate decomposition has been fetched
|
||||
//but contains no base hull
|
||||
d->mBaseHullMesh = new LLVertexBuffer(0, 0);
|
||||
}
|
||||
|
||||
mDecompositionQ.push(d);
|
||||
}
|
||||
|
||||
|
|
@ -1319,12 +1143,12 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
|
|||
{
|
||||
LLSD physics_shape;
|
||||
|
||||
LLMeshDecomposition* d = new LLMeshDecomposition();
|
||||
LLModel::Decomposition* d = new LLModel::Decomposition();
|
||||
d->mMeshID = mesh_id;
|
||||
|
||||
if (data == NULL)
|
||||
{ //no data, no physics shape exists
|
||||
d->mPhysicsShapeMesh = new LLVertexBuffer(0,0);
|
||||
d->mPhysicsShapeMesh.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1348,33 +1172,22 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
|
|||
index_count += face.mNumIndices;
|
||||
}
|
||||
|
||||
d->mPhysicsShapeMesh = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
|
||||
d->mPhysicsShapeMesh.clear();
|
||||
|
||||
d->mPhysicsShapeMesh->allocateBuffer(vertex_count, index_count, true);
|
||||
std::vector<LLVector3>& pos = d->mPhysicsShapeMesh.mPositions;
|
||||
std::vector<LLVector3>& norm = d->mPhysicsShapeMesh.mNormals;
|
||||
|
||||
LLStrider<LLVector3> pos;
|
||||
LLStrider<U16> idx;
|
||||
|
||||
d->mPhysicsShapeMesh->getVertexStrider(pos);
|
||||
d->mPhysicsShapeMesh->getIndexStrider(idx);
|
||||
|
||||
S32 idx_offset = 0;
|
||||
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
|
||||
{
|
||||
const LLVolumeFace& face = volume->getVolumeFace(i);
|
||||
if (idx_offset + face.mNumIndices > 65535)
|
||||
{ //avoid 16-bit index overflow
|
||||
continue;
|
||||
}
|
||||
|
||||
LLVector4a::memcpyNonAliased16(pos[idx_offset].mV, face.mPositions[0].getF32ptr(), face.mNumVertices*sizeof(LLVector4a));
|
||||
|
||||
for (S32 i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
*idx++ = face.mIndices[i] + idx_offset;
|
||||
}
|
||||
U16 idx = face.mIndices[i];
|
||||
|
||||
idx_offset += face.mNumVertices;
|
||||
pos.push_back(LLVector3(face.mPositions[idx].getF32ptr()));
|
||||
norm.push_back(LLVector3(face.mNormals[idx].getF32ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2485,33 +2298,7 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
|
|||
mLoadingSkins.erase(info.mMeshID);
|
||||
}
|
||||
|
||||
void LLMeshDecomposition::merge(const LLMeshDecomposition* rhs)
|
||||
{
|
||||
if (!rhs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMeshID != rhs->mMeshID)
|
||||
{
|
||||
llerrs << "Attempted to merge with decomposition of some other mesh." << llendl;
|
||||
}
|
||||
|
||||
if (mBaseHull.empty())
|
||||
{ //take base hull and decomposition from rhs
|
||||
mHull = rhs->mHull;
|
||||
mBaseHull = rhs->mBaseHull;
|
||||
mMesh = rhs->mMesh;
|
||||
mBaseHullMesh = rhs->mBaseHullMesh;
|
||||
}
|
||||
|
||||
if (mPhysicsShapeMesh.isNull())
|
||||
{ //take physics shape mesh from rhs
|
||||
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
|
||||
}
|
||||
}
|
||||
|
||||
void LLMeshRepository::notifyDecompositionReceived(LLMeshDecomposition* decomp)
|
||||
void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp)
|
||||
{
|
||||
decomposition_map::iterator iter = mDecompositionMap.find(decomp->mMeshID);
|
||||
if (iter == mDecompositionMap.end())
|
||||
|
|
@ -2653,7 +2440,7 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
|
|||
{
|
||||
if (mesh_id.notNull())
|
||||
{
|
||||
LLMeshDecomposition* decomp = NULL;
|
||||
LLModel::Decomposition* decomp = NULL;
|
||||
decomposition_map::iterator iter = mDecompositionMap.find(mesh_id);
|
||||
if (iter != mDecompositionMap.end())
|
||||
{
|
||||
|
|
@ -2661,7 +2448,7 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
|
|||
}
|
||||
|
||||
//decomposition block hasn't been fetched yet
|
||||
if (!decomp || decomp->mPhysicsShapeMesh.isNull())
|
||||
if (!decomp || decomp->mPhysicsShapeMesh.empty())
|
||||
{
|
||||
LLMutexLock lock(mMeshMutex);
|
||||
//add volume to list of loading meshes
|
||||
|
|
@ -2676,9 +2463,9 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
|
|||
|
||||
}
|
||||
|
||||
const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id)
|
||||
LLModel::Decomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id)
|
||||
{
|
||||
LLMeshDecomposition* ret = NULL;
|
||||
LLModel::Decomposition* ret = NULL;
|
||||
|
||||
if (mesh_id.notNull())
|
||||
{
|
||||
|
|
@ -2689,7 +2476,7 @@ const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh
|
|||
}
|
||||
|
||||
//decomposition block hasn't been fetched yet
|
||||
if (!ret || ret->mBaseHullMesh.isNull())
|
||||
if (!ret || ret->mBaseHullMesh.empty())
|
||||
{
|
||||
LLMutexLock lock(mMeshMutex);
|
||||
//add volume to list of loading meshes
|
||||
|
|
@ -2792,8 +2579,8 @@ void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
|
|||
|
||||
LLModel::convex_hull_decomposition& decomp =
|
||||
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
|
||||
data.mModel[LLModel::LOD_PHYSICS]->mConvexHullDecomp :
|
||||
data.mBaseModel->mConvexHullDecomp;
|
||||
data.mModel[LLModel::LOD_PHYSICS]->mPhysics.mHull :
|
||||
data.mBaseModel->mPhysics.mHull;
|
||||
|
||||
LLModel::hull dummy_hull;
|
||||
|
||||
|
|
@ -2893,8 +2680,8 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
|
|||
|
||||
LLModel::convex_hull_decomposition& decomp =
|
||||
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
|
||||
data.mModel[LLModel::LOD_PHYSICS]->mConvexHullDecomp :
|
||||
data.mBaseModel->mConvexHullDecomp;
|
||||
data.mModel[LLModel::LOD_PHYSICS]->mPhysics.mHull :
|
||||
data.mBaseModel->mPhysics.mHull;
|
||||
|
||||
LLModel::writeModel(
|
||||
ostr,
|
||||
|
|
@ -3412,7 +3199,7 @@ void LLPhysicsDecomp::doDecomposition()
|
|||
// if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
|
||||
LLConvexDecomposition::getInstance()->getMeshFromStage(stage, i, &mesh);
|
||||
|
||||
mCurRequest->mHullMesh[i] = get_vertex_buffer_from_mesh(mesh);
|
||||
get_vertex_buffer_from_mesh(mesh, mCurRequest->mHullMesh[i]);
|
||||
|
||||
mMutex->lock();
|
||||
mCurRequest->mHull[i] = p;
|
||||
|
|
@ -3685,3 +3472,46 @@ LLSD LLImportMaterial::asLLSD()
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
|
||||
{
|
||||
decomp.mMesh.resize(decomp.mHull.size());
|
||||
|
||||
for (U32 i = 0; i < decomp.mHull.size(); ++i)
|
||||
{
|
||||
LLCDHull hull;
|
||||
hull.mNumVertices = decomp.mHull[i].size();
|
||||
hull.mVertexBase = decomp.mHull[i][0].mV;
|
||||
hull.mVertexStrideBytes = 12;
|
||||
|
||||
LLCDMeshData mesh;
|
||||
LLCDResult res = LLCD_OK;
|
||||
if (LLConvexDecomposition::getInstance() != NULL)
|
||||
{
|
||||
res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh);
|
||||
}
|
||||
if (res == LLCD_OK)
|
||||
{
|
||||
get_vertex_buffer_from_mesh(mesh, decomp.mMesh[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!decomp.mBaseHull.empty() && decomp.mBaseHullMesh.empty())
|
||||
{ //get mesh for base hull
|
||||
LLCDHull hull;
|
||||
hull.mNumVertices = decomp.mBaseHull.size();
|
||||
hull.mVertexBase = decomp.mBaseHull[0].mV;
|
||||
hull.mVertexStrideBytes = 12;
|
||||
|
||||
LLCDMeshData mesh;
|
||||
LLCDResult res = LLCD_OK;
|
||||
if (LLConvexDecomposition::getInstance() != NULL)
|
||||
{
|
||||
res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh);
|
||||
}
|
||||
if (res == LLCD_OK)
|
||||
{
|
||||
get_vertex_buffer_from_mesh(mesh, decomp.mBaseHullMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,34 +132,6 @@ public:
|
|||
LLSD asLLSD();
|
||||
};
|
||||
|
||||
class LLMeshSkinInfo
|
||||
{
|
||||
public:
|
||||
LLUUID mMeshID;
|
||||
std::vector<std::string> mJointNames;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
float mPelvisOffset;
|
||||
};
|
||||
|
||||
class LLMeshDecomposition
|
||||
{
|
||||
public:
|
||||
LLMeshDecomposition() { }
|
||||
|
||||
void merge(const LLMeshDecomposition* rhs);
|
||||
|
||||
LLUUID mMeshID;
|
||||
LLModel::convex_hull_decomposition mHull;
|
||||
LLModel::hull mBaseHull;
|
||||
|
||||
std::vector<LLPointer<LLVertexBuffer> > mMesh;
|
||||
LLPointer<LLVertexBuffer> mBaseHullMesh;
|
||||
LLPointer<LLVertexBuffer> mPhysicsShapeMesh;
|
||||
};
|
||||
|
||||
class LLPhysicsDecomp : public LLThread
|
||||
{
|
||||
public:
|
||||
|
|
@ -178,7 +150,7 @@ public:
|
|||
|
||||
//output state
|
||||
std::string mStatusMessage;
|
||||
std::vector<LLPointer<LLVertexBuffer> > mHullMesh;
|
||||
std::vector<LLModel::PhysicsMesh> mHullMesh;
|
||||
LLModel::convex_hull_decomposition mHull;
|
||||
|
||||
//status message callback, called from decomposition thread
|
||||
|
|
@ -313,7 +285,7 @@ public:
|
|||
std::set<LLUUID> mPhysicsShapeRequests;
|
||||
|
||||
//queue of completed Decomposition info requests
|
||||
std::queue<LLMeshDecomposition*> mDecompositionQ;
|
||||
std::queue<LLModel::Decomposition*> mDecompositionQ;
|
||||
|
||||
//queue of requested headers
|
||||
std::queue<HeaderRequest> mHeaderReqQ;
|
||||
|
|
@ -477,17 +449,19 @@ public:
|
|||
void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
|
||||
void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
|
||||
void notifySkinInfoReceived(LLMeshSkinInfo& info);
|
||||
void notifyDecompositionReceived(LLMeshDecomposition* info);
|
||||
void notifyDecompositionReceived(LLModel::Decomposition* info);
|
||||
|
||||
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||
U32 calcResourceCost(LLSD& header);
|
||||
U32 getResourceCost(const LLUUID& mesh_params);
|
||||
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
|
||||
const LLMeshDecomposition* getDecomposition(const LLUUID& mesh_id);
|
||||
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
|
||||
void fetchPhysicsShape(const LLUUID& mesh_id);
|
||||
bool hasPhysicsShape(const LLUUID& mesh_id);
|
||||
|
||||
void buildHull(const LLVolumeParams& params, S32 detail);
|
||||
void buildPhysicsMesh(LLModel::Decomposition& decomp);
|
||||
|
||||
const LLSD& getMeshHeader(const LLUUID& mesh_id);
|
||||
|
||||
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
|
||||
|
|
@ -501,7 +475,7 @@ public:
|
|||
typedef std::map<LLUUID, LLMeshSkinInfo> skin_map;
|
||||
skin_map mSkinMap;
|
||||
|
||||
typedef std::map<LLUUID, LLMeshDecomposition*> decomposition_map;
|
||||
typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
|
||||
decomposition_map mDecompositionMap;
|
||||
|
||||
LLMutex* mMeshMutex;
|
||||
|
|
|
|||
|
|
@ -2961,31 +2961,21 @@ S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& sca
|
|||
void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color)
|
||||
{
|
||||
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
|
||||
const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
|
||||
const LLVector3 center(0,0,0);
|
||||
const LLVector3 size(0.25f,0.25f,0.25f);
|
||||
|
||||
if (decomp)
|
||||
{
|
||||
LLVertexBuffer* buff = decomp->mBaseHullMesh;
|
||||
|
||||
if (buff && buff->getNumVerts() > 0)
|
||||
if (!decomp->mBaseHullMesh.empty())
|
||||
{
|
||||
buff->setBuffer(data_mask);
|
||||
|
||||
/* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glColor4fv(line_color.mV);
|
||||
buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);*/
|
||||
|
||||
{
|
||||
glColor4fv(color.mV);
|
||||
buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
|
||||
}
|
||||
glColor4fv(color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals);
|
||||
}
|
||||
else
|
||||
{
|
||||
gMeshRepo.buildPhysicsMesh(*decomp);
|
||||
gGL.color3f(0,1,1);
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
|
|
@ -2998,19 +2988,16 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo
|
|||
}
|
||||
}
|
||||
|
||||
void render_hull(LLVertexBuffer* buff, U32 data_mask, const LLColor4& color, const LLColor4& line_color)
|
||||
void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color)
|
||||
{
|
||||
buff->setBuffer(data_mask);
|
||||
|
||||
glColor4fv(color.mV);
|
||||
buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
|
||||
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals);
|
||||
LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonOffset(3.f, 3.f);
|
||||
glLineWidth(3.f);
|
||||
glColor4fv(line_color.mV);
|
||||
buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals);
|
||||
glLineWidth(1.f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
|
@ -3075,7 +3062,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
|
|||
if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH)
|
||||
{
|
||||
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
|
||||
const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
|
||||
if (decomp)
|
||||
{ //render a physics based mesh
|
||||
|
|
@ -3084,27 +3071,33 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
|
|||
|
||||
if (!decomp->mHull.empty())
|
||||
{ //decomposition exists, use that
|
||||
for (U32 i = 0; i < decomp->mHull.size(); ++i)
|
||||
|
||||
if (decomp->mMesh.empty())
|
||||
{
|
||||
gMeshRepo.buildPhysicsMesh(*decomp);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < decomp->mMesh.size(); ++i)
|
||||
{
|
||||
render_hull(decomp->mMesh[i], data_mask, color, line_color);
|
||||
render_hull(decomp->mMesh[i], color, line_color);
|
||||
}
|
||||
}
|
||||
else if (decomp->mPhysicsShapeMesh.notNull() && decomp->mPhysicsShapeMesh->getNumVerts() > 0)
|
||||
else if (!decomp->mPhysicsShapeMesh.empty())
|
||||
{
|
||||
//decomp has physics mesh, render that mesh
|
||||
glColor4fv(color.mV);
|
||||
pushBufferVerts(decomp->mPhysicsShapeMesh, data_mask);
|
||||
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glColor4fv(line_color.mV);
|
||||
pushBufferVerts(decomp->mPhysicsShapeMesh, data_mask);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
else
|
||||
{ //no mesh or decomposition, render base hull
|
||||
renderMeshBaseHull(volume, data_mask, color, line_color);
|
||||
|
||||
if (decomp->mPhysicsShapeMesh.isNull())
|
||||
if (decomp->mPhysicsShapeMesh.empty())
|
||||
{
|
||||
//attempt to fetch physics shape mesh if available
|
||||
gMeshRepo.fetchPhysicsShape(mesh_id);
|
||||
|
|
|
|||
|
|
@ -762,6 +762,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
|
||||
mLastPelvisToFoot = 0.0f;
|
||||
mPelvisFixup = 0.0f;
|
||||
mLastPelvisFixup = 0.0f;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -3805,6 +3806,7 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
|
|||
//Store off last pelvis to foot value
|
||||
mLastPelvisToFoot = mPelvisToFoot;
|
||||
mPelvisOffset = offsetAmount;
|
||||
mLastPelvisFixup = mPelvisFixup;
|
||||
mPelvisFixup = pelvisFixup;
|
||||
}
|
||||
}
|
||||
|
|
@ -3825,6 +3827,7 @@ void LLVOAvatar::postPelvisSetRecalc( void )
|
|||
void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
|
||||
{
|
||||
mHasPelvisOffset = true;
|
||||
mLastPelvisFixup = mPelvisFixup;
|
||||
mPelvisFixup = pelvisFixupAmount;
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -4965,6 +4968,7 @@ void LLVOAvatar::resetJointPositions( void )
|
|||
mSkeleton[i].setId( LLUUID::null );
|
||||
}
|
||||
mHasPelvisOffset = false;
|
||||
mPelvisFixup = mLastPelvisFixup;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetSpecificJointPosition
|
||||
|
|
@ -5024,6 +5028,7 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
|
|||
}
|
||||
//make sure we don't apply the joint offset
|
||||
mHasPelvisOffset = false;
|
||||
mPelvisFixup = mLastPelvisFixup;
|
||||
postPelvisSetRecalc();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ public:
|
|||
LLVector3 mPelvisOffset;
|
||||
F32 mLastPelvisToFoot;
|
||||
F32 mPelvisFixup;
|
||||
F32 mLastPelvisFixup;
|
||||
|
||||
LLVector3 mHeadOffset; // current head position
|
||||
LLViewerJoint mRoot;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<toggleable_menu name="Gear Menu">
|
||||
<toggleable_menu name="Self Pie">
|
||||
<menu_item_call label="Hinsetzen" name="Sit Down Here"/>
|
||||
<menu_item_call label="Aufstehen" name="Stand Up"/>
|
||||
<menu_item_call label="Meine Freunde" name="Friends..."/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<toggleable_menu name="Gear Menu">
|
||||
<toggleable_menu name="Self Pie">
|
||||
<menu_item_call label="Sentarme" name="Sit Down Here"/>
|
||||
<menu_item_call label="Levantarme" name="Stand Up"/>
|
||||
<menu_item_call label="Mis amigos" name="Friends..."/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<toggleable_menu name="Gear Menu">
|
||||
<toggleable_menu name="Self Pie">
|
||||
<menu_item_call label="M'asseoir" name="Sit Down Here"/>
|
||||
<menu_item_call label="Me lever" name="Stand Up"/>
|
||||
<menu_item_call label="Mes amis" name="Friends..."/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<toggleable_menu name="Gear Menu">
|
||||
<toggleable_menu name="Self Pie">
|
||||
<menu_item_call label="Sentar" name="Sit Down Here"/>
|
||||
<menu_item_call label="Ficar de pé" name="Stand Up"/>
|
||||
<menu_item_call label="Meus amigos" name="Friends..."/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue