summaryrefslogtreecommitdiff
path: root/indra/llprimitive/llmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llprimitive/llmodel.cpp')
-rw-r--r--indra/llprimitive/llmodel.cpp252
1 files changed, 203 insertions, 49 deletions
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index ae17996956..7fa72d82e1 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -2,30 +2,25 @@
* @file llmodel.cpp
* @brief Model handling implementation
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,7 +36,6 @@
#include "dom/domMesh.h"
#include "zlib/zlib.h"
-#if LL_MESH_ENABLED
std::string model_names[] =
{
@@ -956,13 +950,14 @@ void LLModel::setNumVolumeFaces(S32 count)
mVolumeFaces.resize(count);
}
-void LLModel::setVolumeFaceData(S32 f,
- LLStrider<LLVector3> pos,
- LLStrider<LLVector3> norm,
- LLStrider<LLVector2> tc,
- LLStrider<U16> ind,
- U32 num_verts,
- U32 num_indices)
+void LLModel::setVolumeFaceData(
+ S32 f,
+ LLStrider<LLVector3> pos,
+ LLStrider<LLVector3> norm,
+ LLStrider<LLVector2> tc,
+ LLStrider<U16> ind,
+ U32 num_verts,
+ U32 num_indices)
{
LLVolumeFace& face = mVolumeFaces[f];
@@ -1289,11 +1284,63 @@ LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
}
//static
-LLSD LLModel::writeModel(std::string filename, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, BOOL nowrite)
+LLSD LLModel::writeModel(
+ std::string filename,
+ LLModel* physics,
+ LLModel* high,
+ LLModel* medium,
+ LLModel* low,
+ LLModel* impostor,
+ const convex_hull_decomposition& decomp,
+ BOOL upload_skin,
+ BOOL upload_joints,
+ BOOL nowrite)
+{
+ LLModel::hull dummy_hull;
+ return writeModel(
+ filename,
+ physics,
+ high,
+ medium,
+ low,
+ impostor,
+ decomp,
+ dummy_hull,
+ upload_skin,
+ upload_joints,
+ nowrite);
+}
+
+//static
+LLSD LLModel::writeModel(
+ std::string filename,
+ LLModel* physics,
+ LLModel* high,
+ LLModel* medium,
+ LLModel* low,
+ LLModel* impostor,
+ const convex_hull_decomposition& decomp,
+ const hull& base_hull,
+ BOOL upload_skin,
+ BOOL upload_joints,
+ BOOL nowrite)
{
- std::ofstream os(filename.c_str(), std::ofstream::out | std::ofstream::binary);
+ std::ofstream os(
+ filename.c_str(),
+ std::ofstream::out | std::ofstream::binary);
- LLSD header = writeModel(os, physics, high, medium, low, impostor, decomp, nowrite);
+ LLSD header = writeModel(
+ os,
+ physics,
+ high,
+ medium,
+ low,
+ impostor,
+ decomp,
+ base_hull,
+ upload_skin,
+ upload_joints,
+ nowrite);
os.close();
@@ -1301,7 +1348,18 @@ LLSD LLModel::writeModel(std::string filename, LLModel* physics, LLModel* high,
}
//static
-LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, BOOL nowrite)
+LLSD LLModel::writeModel(
+ std::ostream& ostr,
+ LLModel* physics,
+ LLModel* high,
+ LLModel* medium,
+ LLModel* low,
+ LLModel* impostor,
+ const convex_hull_decomposition& decomp,
+ const hull& base_hull,
+ BOOL upload_skin,
+ BOOL upload_joints,
+ BOOL nowrite)
{
LLSD mdl;
@@ -1314,7 +1372,7 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
physics
};
- bool skinning = high && !high->mSkinWeights.empty();
+ bool skinning = upload_skin && high && !high->mSkinWeights.empty();
if (skinning)
{ //write skinning block
@@ -1343,17 +1401,44 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
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];
+ }
+ }
+ }
+ }
+
}
- if (!decomp.empty())
+ if (!decomp.empty() || !base_hull.empty())
{
//write decomposition block
// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
// ["decomposition"]["PositionDomain"]["Min"/"Max"]
// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
-
+ // ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
+
+
//get minimum and maximum
- LLVector3 min = decomp[0][0];
+ LLVector3 min;
+
+ if (decomp.empty())
+ {
+ min = base_hull[0];
+ }
+ else
+ {
+ min = decomp[0][0];
+ }
+
LLVector3 max = min;
LLSD::Binary hulls(decomp.size());
@@ -1364,31 +1449,75 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
{
U32 size = decomp[i].size();
total += size;
- hulls[i] = (U8) size;
+ // The valid range of sizes is actually 3-256 verts. We need this to fit into a U8,
+ // So we just subtract 1
+ hulls[i] = (U8) (size - 1);
for (U32 j = 0; j < decomp[i].size(); ++j)
{
update_min_max(min, max, decomp[i][j]);
}
+
+ }
+
+ for (U32 i = 0; i < base_hull.size(); ++i)
+ {
+ update_min_max(min, max, base_hull[i]);
}
mdl["decomposition"]["Min"] = min.getValue();
mdl["decomposition"]["Max"] = max.getValue();
- mdl["decomposition"]["HullList"] = hulls;
-
- LLSD::Binary p(total*3*2);
- LLVector3 range = max-min;
+ if (!hulls.empty())
+ {
+ mdl["decomposition"]["HullList"] = hulls;
+ }
- U32 vert_idx = 0;
- for (U32 i = 0; i < decomp.size(); ++i)
+ if (total > 0)
{
- for (U32 j = 0; j < decomp[i].size(); ++j)
+ LLSD::Binary p(total*3*2);
+
+ LLVector3 range = max-min;
+
+ U32 vert_idx = 0;
+ for (U32 i = 0; i < decomp.size(); ++i)
+ {
+ for (U32 j = 0; j < decomp[i].size(); ++j)
+ {
+ for (U32 k = 0; k < 3; k++)
+ {
+ //convert to 16-bit normalized across domain
+ U16 val = (U16) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+
+ U8* buff = (U8*) &val;
+ //write to binary buffer
+ p[vert_idx++] = buff[0];
+ p[vert_idx++] = buff[1];
+
+ if (vert_idx > p.size())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+ }
+ }
+ }
+
+ mdl["decomposition"]["Position"] = p;
+ }
+
+ if (!base_hull.empty())
+ {
+ LLSD::Binary p(base_hull.size()*3*2);
+
+ LLVector3 range = max-min;
+
+ U32 vert_idx = 0;
+ for (U32 j = 0; j < base_hull.size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
- U16 val = (U16) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+ U16 val = (U16) (((base_hull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
@@ -1401,9 +1530,9 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
}
}
}
+
+ mdl["decomposition"]["Hull"] = p;
}
-
- mdl["decomposition"]["Position"] = p;
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@@ -1646,7 +1775,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!nowrite)
{
- LLSDSerialize::serialize(header, ostr, LLSDSerialize::LLSD_BINARY);
+ LLSDSerialize::toBinary(header, ostr);
if (!skin.empty())
{ //write skin block
@@ -1710,5 +1839,30 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
}
}
-#endif
+void LLModel::setConvexHullDecomposition(
+ const LLModel::convex_hull_decomposition& decomp)
+{
+ mConvexHullDecomp = decomp;
+
+ mHullCenter.resize(mConvexHullDecomp.size());
+ mHullPoints = 0;
+ mCenterOfHullCenters.clear();
+
+ for (U32 i = 0; i < decomp.size(); ++i)
+ {
+ LLVector3 cur_center;
+
+ for (U32 j = 0; j < decomp[i].size(); ++j)
+ {
+ cur_center += decomp[i][j];
+ }
+ mCenterOfHullCenters += cur_center;
+ cur_center *= 1.f/decomp[i].size();
+ mHullCenter[i] = cur_center;
+ mHullPoints += decomp[i].size();
+ }
+
+ mCenterOfHullCenters *= 1.f / mHullPoints;
+}
+