summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/cmake/Variables.cmake1
-rw-r--r--indra/llcharacter/CMakeLists.txt14
-rw-r--r--indra/llinventory/CMakeLists.txt21
-rw-r--r--indra/llmath/llvolume.cpp19
-rw-r--r--indra/llmath/llvolume.h10
-rw-r--r--indra/llplugin/CMakeLists.txt26
-rw-r--r--indra/llprimitive/CMakeLists.txt12
-rw-r--r--indra/llprimitive/llprimitive.h1
-rw-r--r--indra/llui/CMakeLists.txt14
-rw-r--r--indra/llvfs/CMakeLists.txt24
-rw-r--r--indra/llxml/CMakeLists.txt39
-rw-r--r--indra/newview/CMakeLists.txt24
-rw-r--r--indra/newview/app_settings/settings_crash_behavior.xml2
-rw-r--r--indra/newview/llfloatermodelpreview.cpp37
-rw-r--r--indra/newview/llmeshrepository.cpp5
-rw-r--r--indra/newview/llmeshrepository.h1
-rw-r--r--indra/newview/llphysicsshapebuilderutil.cpp206
-rw-r--r--indra/newview/llphysicsshapebuilderutil.h134
-rw-r--r--indra/newview/llspatialpartition.cpp172
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml2
20 files changed, 642 insertions, 122 deletions
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 02fb4ea459..bc517cde49 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -25,6 +25,7 @@ set(SERVER_PREFIX)
set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
+set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")
set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX})
set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX})
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt
index 85e3f97092..6eb154458d 100644
--- a/indra/llcharacter/CMakeLists.txt
+++ b/indra/llcharacter/CMakeLists.txt
@@ -78,10 +78,12 @@ add_library (llcharacter ${llcharacter_SOURCE_FILES})
# Add tests
-include(LLAddBuildTest)
-# UNIT TESTS
-SET(llcharacter_TEST_SOURCE_FILES
- lljoint.cpp
- )
-LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llcharacter_TEST_SOURCE_FILES
+ lljoint.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
+endif (LL_TESTS)
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index a563db901a..35a764b111 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -61,14 +61,15 @@ add_library (llinventory ${llinventory_SOURCE_FILES})
#add unit tests
-INCLUDE(LLAddBuildTest)
-SET(llinventory_TEST_SOURCE_FILES
- # no real unit tests yet!
- )
-LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
-
-#set(TEST_DEBUG on)
-set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
-LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
-LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
+if (LL_TESTS)
+ INCLUDE(LLAddBuildTest)
+ SET(llinventory_TEST_SOURCE_FILES
+ # no real unit tests yet!
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
+ #set(TEST_DEBUG on)
+ set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+ LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 1f15d5465c..3da9c9ca79 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1828,6 +1828,10 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mSculptLevel = -2;
mIsTetrahedron = FALSE;
mLODScaleBias.setVec(1,1,1);
+ mHullPoints = NULL;
+ mHullIndices = NULL;
+ mNumHullPoints = 0;
+ mNumHullIndices = 0;
// set defaults
if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
@@ -1879,6 +1883,11 @@ LLVolume::~LLVolume()
mPathp = NULL;
mProfilep = NULL;
mVolumeFaces.clear();
+
+ free(mHullPoints);
+ mHullPoints = NULL;
+ free(mHullIndices);
+ mHullIndices = NULL;
}
BOOL LLVolume::generate()
@@ -3044,6 +3053,16 @@ BOOL LLVolume::isFlat(S32 face)
}
+bool LLVolumeParams::isSculpt() const
+{
+ return mSculptID.notNull();
+}
+
+bool LLVolumeParams::isMeshSculpt() const
+{
+ return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH);
+}
+
bool LLVolumeParams::operator==(const LLVolumeParams &params) const
{
return ( (getPathParams() == params.getPathParams()) &&
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index b4b59fd402..6e080f4877 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -646,6 +646,8 @@ public:
const F32& getSkew() const { return mPathParams.getSkew(); }
const LLUUID& getSculptID() const { return mSculptID; }
const U8& getSculptType() const { return mSculptType; }
+ bool isSculpt() const;
+ bool isMeshSculpt() const;
BOOL isConvex() const;
// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
@@ -1066,10 +1068,16 @@ public:
LLPath *mPathp;
LLProfile *mProfilep;
std::vector<Point> mMesh;
-
+
BOOL mGenerateSingleFace;
typedef std::vector<LLVolumeFace> face_list_t;
face_list_t mVolumeFaces;
+
+public:
+ LLVector4a* mHullPoints;
+ U16* mHullIndices;
+ S32 mNumHullPoints;
+ S32 mNumHullIndices;
};
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 441becbae0..e4449a0427 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -58,17 +58,19 @@ add_library (llplugin ${llplugin_SOURCE_FILES})
add_subdirectory(slplugin)
# Add tests
-include(LLAddBuildTest)
-# UNIT TESTS
-SET(llplugin_TEST_SOURCE_FILES
- llplugincookiestore.cpp
- )
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llplugin_TEST_SOURCE_FILES
+ llplugincookiestore.cpp
+ )
-# llplugincookiestore has a dependency on curl, so we need to link the curl library into the test.
-set_source_files_properties(
- llplugincookiestore.cpp
- PROPERTIES
- LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}"
- )
+ # llplugincookiestore has a dependency on curl, so we need to link the curl library into the test.
+ set_source_files_properties(
+ llplugincookiestore.cpp
+ PROPERTIES
+ LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}"
+ )
-LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}")
+ LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}")
+endif (LL_TESTS)
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index af78ed7936..97e1ebde47 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -58,8 +58,10 @@ list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES})
add_library (llprimitive ${llprimitive_SOURCE_FILES})
#add unit tests
-INCLUDE(LLAddBuildTest)
-SET(llprimitive_TEST_SOURCE_FILES
- llmediaentry.cpp
- )
-LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
+if (LL_TESTS)
+ INCLUDE(LLAddBuildTest)
+ SET(llprimitive_TEST_SOURCE_FILES
+ llmediaentry.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
+endif (LL_TESTS)
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index a44b9a6c1f..c906d98324 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -450,6 +450,7 @@ protected:
U8 mNumTEs; // # of faces on the primitve
U32 mMiscFlags; // home for misc bools
+public:
static LLVolumeMgr* sVolumeManager;
};
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index c59ef7819c..2c68f8cf75 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -242,9 +242,11 @@ target_link_libraries(llui
)
# Add tests
-include(LLAddBuildTest)
-SET(llui_TEST_SOURCE_FILES
- llurlmatch.cpp
- llurlentry.cpp
- )
-LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ SET(llui_TEST_SOURCE_FILES
+ llurlmatch.cpp
+ llurlentry.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+endif (LL_TESTS) \ No newline at end of file
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index 05c7c7860c..569674ecf0 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -68,14 +68,16 @@ endif (DARWIN)
# Add tests
-include(LLAddBuildTest)
-# UNIT TESTS
-SET(llvfs_TEST_SOURCE_FILES
- # none so far
- )
-LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
-
-# INTEGRATION TESTS
-set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
-# TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
-LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llvfs_TEST_SOURCE_FILES
+ # none so far
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
+
+ # INTEGRATION TESTS
+ set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+ # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+ LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index fbcfade383..21cdf5f926 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -47,22 +47,23 @@ target_link_libraries( llxml
# tests
-# unit tests
-
-SET(llxml_TEST_SOURCE_FILES
- # none yet!
- )
-LL_ADD_PROJECT_UNIT_TESTS(llxml "${llxml_TEST_SOURCE_FILES}")
-
-# integration tests
-
-# set(TEST_DEBUG on)
-set(test_libs
- ${LLXML_LIBRARIES}
- ${WINDOWS_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- )
-
-LL_ADD_INTEGRATION_TEST(llcontrol "" "${test_libs}")
-
+if (LL_TESTS)
+ # unit tests
+
+ SET(llxml_TEST_SOURCE_FILES
+ # none yet!
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llxml "${llxml_TEST_SOURCE_FILES}")
+
+ # integration tests
+
+ # set(TEST_DEBUG on)
+ set(test_libs
+ ${LLXML_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+
+ LL_ADD_INTEGRATION_TEST(llcontrol "" "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1194e558f1..55a2fb7630 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -383,6 +383,7 @@ set(viewer_SOURCE_FILES
llparcelselection.cpp
llparticipantlist.cpp
llpatchvertexarray.cpp
+ llphysicsshapebuilderutil.cpp
llplacesinventorybridge.cpp
llplacesinventorypanel.cpp
llpopupview.cpp
@@ -912,6 +913,7 @@ set(viewer_HEADER_FILES
llparcelselection.h
llparticipantlist.h
llpatchvertexarray.h
+ llphysicsshapebuilderutil.h
llplacesinventorybridge.h
llplacesinventorypanel.h
llpolymesh.h
@@ -1436,12 +1438,22 @@ if (WINDOWS)
set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map")
endif(MSVC71)
- set_target_properties(${VIEWER_BINARY_NAME}
- PROPERTIES
- LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:__tcmalloc"
- LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
- LINK_FLAGS_RELEASE ${release_flags}
- )
+ if (INCREMENTAL_LINK)
+ set_target_properties(${VIEWER_BINARY_NAME}
+ PROPERTIES
+ LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCREMENTAL /INCLUDE:__tcmalloc"
+ LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
+ LINK_FLAGS_RELEASE ${release_flags}
+ )
+ else(INCREMENTAL_LINK)
+ set_target_properties(${VIEWER_BINARY_NAME}
+ PROPERTIES
+ LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /INCLUDE:__tcmalloc"
+ LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
+ LINK_FLAGS_RELEASE ${release_flags}
+ )
+ endif(INCREMENTAL_LINK)
+
if(USE_PRECOMPILED_HEADERS)
set_target_properties(
${VIEWER_BINARY_NAME}
diff --git a/indra/newview/app_settings/settings_crash_behavior.xml b/indra/newview/app_settings/settings_crash_behavior.xml
index cc7f5ac88b..97651ff4ca 100644
--- a/indra/newview/app_settings/settings_crash_behavior.xml
+++ b/indra/newview/app_settings/settings_crash_behavior.xml
@@ -9,7 +9,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
</map>
</llsd>
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 6e051c66a9..d89d3e5c0a 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -2961,50 +2961,21 @@ void LLModelPreview::updateStatusMessages()
if (lod != lod_high)
{
- if (total_submeshes[lod] == 0)
- { //no model loaded for this lod, see if one is required
- for (U32 i = 0; i < verts[lod_high].size(); ++i)
- {
- const F32 ratio = 0.5f;
- const S32 required_verts = 128;
-
- F32 scaler = powf(ratio, lod_high-lod);
- S32 max_verts = (S32)(verts[lod_high][i]*scaler);
-
- if (max_verts > required_verts)
- { //some model in this slot might have more than 128 vertices
-
- //if any model higher up the chain has more than 128 vertices,
- // lod is required here
- for (S32 j = lod+1; j <= LLModel::LOD_HIGH; ++j)
- {
- if (verts[j].size() > i && verts[j][i] > 128)
- {
- message = "required";
- upload_message = "missing_lod";
- }
- }
- }
- }
- }
- else if (total_submeshes[lod] != total_submeshes[lod_high])
+ if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
{
message = "mesh_mismatch";
upload_message = "bad_lod";
}
- else if (tris[lod].size() != tris[lod_high].size())
+ else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size())
{
message = "model_mismatch";
upload_message = "bad_lod";
}
- else
+ else if (!verts[lod].empty())
{
for (U32 i = 0; i < verts[lod].size(); ++i)
{
- const F32 ratio = 0.5f;
-
- F32 scaler = powf(ratio, lod_high-lod);
- S32 max_verts = (S32)(verts[lod_high][i]*scaler);
+ S32 max_verts = verts[lod+1][i];
if (verts[lod][i] > max_verts)
{
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 757497060a..9aba84acb4 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -2130,6 +2130,11 @@ const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh
return NULL;
}
+void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
+{
+
+}
+
const LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
{
return mThread->getMeshHeader(mesh_id);
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 736d236e2e..0bc63a8469 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -407,6 +407,7 @@ public:
U32 getResourceCost(const LLUUID& mesh_params);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
const LLMeshDecomposition* getDecomposition(const LLUUID& mesh_id);
+ void buildHull(const LLVolumeParams& params, S32 detail);
const LLSD& getMeshHeader(const LLUUID& mesh_id);
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp
new file mode 100644
index 0000000000..54d54bfcb9
--- /dev/null
+++ b/indra/newview/llphysicsshapebuilderutil.cpp
@@ -0,0 +1,206 @@
+/**
+* @file llphysicsshapebuilder.cpp
+* @brief Generic system to convert LL(Physics)VolumeParams to physics shapes
+* @author falcon@lindenlab.com
+*
+* $LicenseInfo:firstyear=2010&license=internal$
+*
+* Copyright (c) 2010, Linden Research, Inc.
+*
+* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+* this source code is governed by the Linden Lab Source Code Disclosure
+* Agreement ("Agreement") previously entered between you and Linden
+* Lab. By accessing, using, copying, modifying or distributing this
+* software, you acknowledge that you have been informed of your
+* obligations under the Agreement and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llphysicsshapebuilderutil.h"
+
+/* static */
+void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut )
+{
+ const LLProfileParams& profile_params = volume_params.getProfileParams();
+ const LLPathParams& path_params = volume_params.getPathParams();
+
+ specOut.mScale = scale;
+
+ const F32 avgScale = ( scale[VX] + scale[VY] + scale[VZ] )/3.0f;
+
+ // count the scale elements that are small
+ S32 min_size_counts = 0;
+ for (S32 i = 0; i < 3; ++i)
+ {
+ if (scale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE)
+ {
+ ++min_size_counts;
+ }
+ }
+
+ const bool profile_complete = ( profile_params.getBegin() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale ) &&
+ ( profile_params.getEnd() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) );
+
+ const bool path_complete = ( path_params.getBegin() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale ) &&
+ ( path_params.getEnd() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) );
+
+ const bool simple_params = ( volume_params.getHollow() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW/avgScale )
+ && ( fabs(path_params.getShearX()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR/avgScale )
+ && ( fabs(path_params.getShearY()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR/avgScale )
+ && ( !volume_params.isMeshSculpt() && !volume_params.isSculpt() );
+
+ if (simple_params && profile_complete)
+ {
+ // Try to create an implicit shape or convexified
+ bool no_taper = ( fabs(path_params.getScaleX() - 1.0f) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale )
+ && ( fabs(path_params.getScaleY() - 1.0f) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale );
+
+ bool no_twist = ( fabs(path_params.getTwistBegin()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST/avgScale )
+ && ( fabs(path_params.getTwistEnd()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST/avgScale);
+
+ // Box
+ if(
+ ( profile_params.getCurveType() == LL_PCODE_PROFILE_SQUARE )
+ && ( path_params.getCurveType() == LL_PCODE_PATH_LINE )
+ && no_taper
+ && no_twist
+ )
+ {
+ specOut.mType = PhysicsShapeSpecification::BOX;
+ if ( path_complete )
+ {
+ return;
+ }
+ else
+ {
+ // Side lengths
+ specOut.mScale[VX] = llmax( scale[VX], SHAPE_BUILDER_MIN_GEOMETRY_SIZE );
+ specOut.mScale[VY] = llmax( scale[VY], SHAPE_BUILDER_MIN_GEOMETRY_SIZE );
+ specOut.mScale[VZ] = llmax( scale[VZ] * (path_params.getEnd() - path_params.getBegin()), SHAPE_BUILDER_MIN_GEOMETRY_SIZE );
+
+ specOut.mCenter.set( 0.f, 0.f, 0.5f * scale[VZ] * ( path_params.getEnd() + path_params.getBegin() - 1.0f ) );
+ return;
+ }
+ }
+
+ // Sphere
+ if( path_complete
+ && ( profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE_HALF )
+ && ( path_params.getCurveType() == LL_PCODE_PATH_CIRCLE )
+ && ( fabs(volume_params.getTaper()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale )
+ && no_twist
+ )
+ {
+ if ( ( scale[VX] == scale[VZ] )
+ && ( scale[VY] == scale[VZ] ) )
+ {
+ // perfect sphere
+ specOut.mType = PhysicsShapeSpecification::SPHERE;
+ specOut.mScale = scale;
+ return;
+ }
+ else if (min_size_counts > 1)
+ {
+ // small or narrow sphere -- we can boxify
+ for (S32 i=0; i<3; ++i)
+ {
+ if (specOut.mScale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE)
+ {
+ // reduce each small dimension size to split the approximation errors
+ specOut.mScale[i] *= 0.75f;
+ }
+ }
+ specOut.mType = PhysicsShapeSpecification::BOX;
+ return;
+ }
+ }
+
+ // Cylinder
+ if( (scale[VX] == scale[VY])
+ && ( profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE )
+ && ( path_params.getCurveType() == LL_PCODE_PATH_LINE )
+ && ( volume_params.getBeginS() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale )
+ && ( volume_params.getEndS() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) )
+ && no_taper
+ )
+ {
+ if (min_size_counts > 1)
+ {
+ // small or narrow sphere -- we can boxify
+ for (S32 i=0; i<3; ++i)
+ {
+ if (specOut.mScale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE)
+ {
+ // reduce each small dimension size to split the approximation errors
+ specOut.mScale[i] *= 0.75f;
+ }
+ }
+
+ specOut.mType = PhysicsShapeSpecification::BOX;
+ }
+ else
+ {
+ specOut.mType = PhysicsShapeSpecification::CYLINDER;
+ F32 length = (volume_params.getPathParams().getEnd() - volume_params.getPathParams().getBegin()) * scale[VZ];
+
+ specOut.mScale[VY] = specOut.mScale[VX];
+ specOut.mScale[VZ] = length;
+ // The minus one below fixes the fact that begin and end range from 0 to 1 not -1 to 1.
+ specOut.mCenter.set( 0.f, 0.f, 0.5f * (volume_params.getPathParams().getBegin() + volume_params.getPathParams().getEnd() - 1.f) * scale[VZ] );
+ }
+
+ return;
+ }
+ }
+
+ if ( (min_size_counts == 3 )
+ // Possible dead code here--who wants to take it out?
+ || (path_complete
+ && profile_complete
+ && ( path_params.getCurveType() == LL_PCODE_PATH_LINE )
+ && (min_size_counts > 1 ) )
+ )
+ {
+ // it isn't simple but
+ // we might be able to convexify this shape if the path and profile are complete
+ // or the path is linear and both path and profile are complete --> we can boxify it
+ specOut.mType = PhysicsShapeSpecification::BOX;
+ specOut.mScale = scale;
+ return;
+ }
+
+ // Special case for big, very thin objects - bump the small dimensions up to the COLLISION_TOLERANCE
+ if (min_size_counts == 1 // One dimension is small
+ && avgScale > 3.f) // ... but others are fairly large
+ {
+ for (S32 i = 0; i < 3; ++i)
+ {
+ specOut.mScale[i] = llmax( specOut.mScale[i], COLLISION_TOLERANCE );
+ }
+ }
+
+ if ( volume_params.shouldForceConvex() )
+ {
+ specOut.mType = PhysicsShapeSpecification::USER_CONVEX;
+ }
+ // Make a simpler convex shape if we can.
+ else if (volume_params.isConvex() // is convex
+ || min_size_counts > 1 ) // two or more small dimensions
+ {
+ specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX;
+ }
+ else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy)
+ {
+ specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT;
+ }
+ else // Resort to mesh
+ {
+ specOut.mType = PhysicsShapeSpecification::PRIM_MESH;
+ }
+}
diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h
new file mode 100644
index 0000000000..3de9afcb25
--- /dev/null
+++ b/indra/newview/llphysicsshapebuilderutil.h
@@ -0,0 +1,134 @@
+/**
+ * @file llphysicsshapebuilder.h
+ * @author falcon@lindenlab.com
+ * @brief Generic system to convert LL(Physics)VolumeParams to physics shapes
+ *
+ * $LicenseInfo:firstyear=2010&license=internal$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PHYSICS_SHAPE_BUILDER_H
+#define LL_PHYSICS_SHAPE_BUILDER_H
+
+#include "indra_constants.h"
+#include "llvolume.h"
+
+#define USE_SHAPE_QUANTIZATION 0
+
+#define SHAPE_BUILDER_DEFAULT_VOLUME_DETAIL 1
+
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW 0.10f
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW_SPHERES 0.90f
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT 0.05f
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER 0.05f
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST 0.09f
+#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR 0.05f
+
+const F32 SHAPE_BUILDER_ENTRY_SNAP_SCALE_BIN_SIZE = 0.15f;
+const F32 SHAPE_BUILDER_ENTRY_SNAP_PARAMETER_BIN_SIZE = 0.010f;
+const F32 SHAPE_BUILDER_CONVEXIFICATION_SIZE = 2.f * COLLISION_TOLERANCE;
+const F32 SHAPE_BUILDER_MIN_GEOMETRY_SIZE = 0.5f * COLLISION_TOLERANCE;
+
+class LLPhysicsVolumeParams : public LLVolumeParams
+{
+public:
+
+ LLPhysicsVolumeParams( const LLVolumeParams& params, bool forceConvex ) :
+ LLVolumeParams( params ),
+ mForceConvex(forceConvex) {}
+
+ bool operator==(const LLPhysicsVolumeParams &params) const
+ {
+ return ( LLVolumeParams::operator==(params) && (mForceConvex == params.mForceConvex) );
+ }
+
+ bool operator!=(const LLPhysicsVolumeParams &params) const
+ {
+ return !operator==(params);
+ }
+
+ bool operator<(const LLPhysicsVolumeParams &params) const
+ {
+ if ( LLVolumeParams::operator!=(params) )
+ {
+ return LLVolumeParams::operator<(params);
+ }
+ return (params.mForceConvex == false) && (mForceConvex == true);
+ }
+
+ bool shouldForceConvex() const { return mForceConvex; }
+
+private:
+ bool mForceConvex;
+};
+
+
+class LLPhysicsShapeBuilderUtil
+{
+public:
+
+ class PhysicsShapeSpecification
+ {
+ public:
+ enum ShapeType
+ {
+ // Primitive types
+ BOX,
+ SPHERE,
+ CYLINDER,
+
+ USER_CONVEX, // User specified they wanted the convex hull of the volume
+
+ PRIM_CONVEX, // Either a volume that is inherently convex but not a primitive type, or a shape
+ // with dimensions such that will convexify it anyway.
+
+ SCULPT, // Special case for traditional sculpts--they are the convex hull of a single particular set of volume params
+
+ USER_MESH, // A user mesh. May or may not contain a convex decomposition.
+
+ PRIM_MESH, // A non-convex volume which we have to represent accurately
+
+ INVALID
+ };
+
+ PhysicsShapeSpecification() :
+ mType( INVALID ),
+ mScale( 0.f, 0.f, 0.f ),
+ mCenter( 0.f, 0.f, 0.f ) {}
+
+ bool isConvex() { return (mType != USER_MESH && mType != PRIM_MESH && mType != INVALID); }
+ bool isMesh() { return (mType == USER_MESH) || (mType == PRIM_MESH); }
+
+ ShapeType getType() { return mType; }
+ const LLVector3& getScale() { return mScale; }
+ const LLVector3& getCenter() { return mCenter; }
+
+ private:
+ friend class LLPhysicsShapeBuilderUtil;
+
+ ShapeType mType;
+
+ // Dimensions of an AABB around the shape
+ LLVector3 mScale;
+
+ // Offset of shape from origin of primitive's reference frame
+ LLVector3 mCenter;
+ };
+
+ static void determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut );
+};
+
+#endif //LL_PHYSICS_SHAPE_BUILDER_H
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 56be8af599..148c222014 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -48,7 +48,9 @@
#include "llmeshrepository.h"
#include "llrender.h"
#include "lloctree.h"
+#include "llphysicsshapebuilderutil.h"
#include "llvoavatar.h"
+#include "llvolumemgr.h"
#include "lltextureatlas.h"
static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
@@ -2341,6 +2343,17 @@ void pushVerts(LLDrawable* drawable, U32 mask)
}
}
+void pushVerts(LLVolume* volume)
+{
+ LLVertexBuffer::unbind();
+ for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& face = volume->getVolumeFace(i);
+ glVertexPointer(3, GL_FLOAT, 16, face.mPositions);
+ glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
+ }
+}
+
void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
{
if (buffer)
@@ -2766,8 +2779,36 @@ void renderNormals(LLDrawable* drawablep)
}
}
+S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale)
+{
+ const S32 DEFAULT_DETAIL = 1;
+ const F32 LARGE_THRESHOLD = 5.f;
+ const F32 MEGA_THRESHOLD = 25.f;
+
+ S32 detail = DEFAULT_DETAIL;
+ F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f;
+
+ if (avg_scale > LARGE_THRESHOLD)
+ {
+ detail += 1;
+ if (avg_scale > MEGA_THRESHOLD)
+ {
+ detail += 1;
+ }
+ }
+
+ return detail;
+}
+
void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
{
+ U8 physics_type = volume->getPhysicsShapeType();
+
+ if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE)
+ {
+ return;
+ }
+
F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold");
F32 cost = volume->getObjectCost();
@@ -2789,10 +2830,21 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
U32 data_mask = LLVertexBuffer::MAP_VERTEX;
- if (volume->isMesh())
- {
+ LLVolumeParams volume_params = volume->getVolume()->getParams();
+
+ LLPhysicsVolumeParams physics_params(volume->getVolume()->getParams(),
+ physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+
+ LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec;
+ LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec);
+
+ U32 type = physics_spec.getType();
+
+ if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH)
+ {
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
+
if (decomp)
{
gGL.pushMatrix();
@@ -2821,18 +2873,112 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
}
gGL.popMatrix();
+ }
+ }
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX)
+ {
+ gGL.pushMatrix();
+ glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);
+ LLVector3 center = physics_spec.getCenter();
+ LLVector3 scale = physics_spec.getScale();
+ LLVector3 vscale = volume->getScale()*2.f;
+ scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]);
+
+ gGL.color4fv(color.mV);
+ drawBox(center, scale);
+ gGL.popMatrix();
+ }
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE)
+ {
+ LLVolumeParams volume_params;
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
+
+ gGL.pushMatrix();
+ glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);
+ glColor4fv(color.mV);
+ pushVerts(sphere);
+ gGL.popMatrix();
+ LLPrimitive::sVolumeManager->unrefVolume(sphere);
+ }
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER)
+ {
+ LLVolumeParams volume_params;
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
+
+ gGL.pushMatrix();
+ glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);
+ glColor4fv(color.mV);
+ pushVerts(cylinder);
+ gGL.popMatrix();
+ LLPrimitive::sVolumeManager->unrefVolume(cylinder);
+ }
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH)
+ {
+ LLVolumeParams volume_params = volume->getVolume()->getParams();
+ S32 detail = get_physics_detail(volume_params, volume->getScale());
- return;
+ LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail);
+ gGL.pushMatrix();
+ glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glColor3fv(color.mV);
+ pushVerts(phys_volume);
+
+ glColor4fv(color.mV);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ pushVerts(phys_volume);
+ gGL.popMatrix();
+ LLPrimitive::sVolumeManager->unrefVolume(phys_volume);
+ }
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX)
+ {
+ LLVolumeParams volume_params = volume->getVolume()->getParams();
+ S32 detail = get_physics_detail(volume_params, volume->getScale());
+
+ LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail);
+
+ if (phys_volume->mHullPoints && phys_volume->mHullIndices)
+ {
+ gGL.pushMatrix();
+ glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ LLVertexBuffer::unbind();
+ glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints);
+ glColor3fv(color.mV);
+ glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
+
+ glColor4fv(color.mV);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
+ gGL.popMatrix();
}
+ else
+ {
+ gMeshRepo.buildHull(volume_params, detail);
+ }
+ LLPrimitive::sVolumeManager->unrefVolume(phys_volume);
}
-
- //push faces
- glColor3fv(color.mV);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- pushVerts(drawable, data_mask);
- glColor4fv(color.mV);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- pushVerts(drawable, data_mask);
+
+ /*{ //analytical shape, just push visual rep.
+ glColor3fv(color.mV);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ pushVerts(drawable, data_mask);
+ glColor4fv(color.mV);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ pushVerts(drawable, data_mask);
+ }*/
}
void renderPhysicsShapes(LLSpatialGroup* group)
@@ -2840,6 +2986,10 @@ void renderPhysicsShapes(LLSpatialGroup* group)
LLGLEnable blend(GL_BLEND);
LLGLDepthTest test(GL_TRUE, GL_FALSE);
+ LLGLEnable offset_fill(GL_POLYGON_OFFSET_FILL);
+ LLGLEnable offset_line(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(-1.f, -1.f);
+
for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
LLDrawable* drawable = *i;
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index e7c2a8bc6f..6512548441 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -175,7 +175,7 @@
<text bottom_delta="20" left="15" follows="top|left" height="15" name="description_label" text_color="1 0.82 0.46 1">
(No charge for upload during First Look)
</text>
- <text bottom_delta="20" left="15" follows="top|left" height="15" name="upload_message">
+ <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="upload_message">
[MESSAGE]
</text>
<text bottom_delta="45" left="15" follows="top|left" height="15" name="debug section">