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"> | 
