diff options
-rw-r--r-- | indra/cmake/Variables.cmake | 1 | ||||
-rw-r--r-- | indra/llcharacter/CMakeLists.txt | 14 | ||||
-rw-r--r-- | indra/llinventory/CMakeLists.txt | 21 | ||||
-rw-r--r-- | indra/llmath/llvolume.cpp | 19 | ||||
-rw-r--r-- | indra/llmath/llvolume.h | 10 | ||||
-rw-r--r-- | indra/llplugin/CMakeLists.txt | 26 | ||||
-rw-r--r-- | indra/llprimitive/CMakeLists.txt | 12 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.h | 1 | ||||
-rw-r--r-- | indra/llui/CMakeLists.txt | 14 | ||||
-rw-r--r-- | indra/llvfs/CMakeLists.txt | 24 | ||||
-rw-r--r-- | indra/llxml/CMakeLists.txt | 39 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 24 | ||||
-rw-r--r-- | indra/newview/app_settings/settings_crash_behavior.xml | 2 | ||||
-rw-r--r-- | indra/newview/llfloatermodelpreview.cpp | 37 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.cpp | 5 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.h | 1 | ||||
-rw-r--r-- | indra/newview/llphysicsshapebuilderutil.cpp | 206 | ||||
-rw-r--r-- | indra/newview/llphysicsshapebuilderutil.h | 134 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.cpp | 172 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 2 |
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 ¶ms, 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 ¶ms) 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 ¶ms) const
+ {
+ return ( LLVolumeParams::operator==(params) && (mForceConvex == params.mForceConvex) );
+ }
+
+ bool operator!=(const LLPhysicsVolumeParams ¶ms) const
+ {
+ return !operator==(params);
+ }
+
+ bool operator<(const LLPhysicsVolumeParams ¶ms) 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"> |