diff options
| -rw-r--r-- | indra/llcommon/llthread.cpp | 4 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.cpp | 4 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.h | 2 | ||||
| -rw-r--r-- | indra/newview/llfloatermodelpreview.cpp | 1333 | ||||
| -rw-r--r-- | indra/newview/llfloatermodelpreview.h | 56 | ||||
| -rw-r--r-- | indra/newview/skins/default/colors.xml | 6 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 371 | 
7 files changed, 998 insertions, 778 deletions
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 59e28948f5..84da54f26d 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -145,7 +145,7 @@ void LLThread::shutdown()  			// First, set the flag that indicates that we're ready to die  			setQuitting(); -			llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl; +			//llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;  			// Now wait a bit for the thread to exit  			// It's unclear whether I should even bother doing this - this destructor  			// should netver get called unless we're already stopped, really... @@ -167,7 +167,7 @@ void LLThread::shutdown()  		if (!isStopped())  		{  			// This thread just wouldn't stop, even though we gave it time -			llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl; +			//llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;  			return;  		}  		mAPRThreadp = NULL; diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index f7eafb2fff..eacf2377fe 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1056,9 +1056,9 @@ void LLModel::addFace(const LLVolumeFace& face)  } -void LLModel::smoothNormals(F32 angle_cutoff) +void LLModel::generateNormals(F32 angle_cutoff)  { -	//smooth normals for all faces by: +	//generate normals for all faces by:  	// 1 - Create faceted copy of face with no texture coordinates  	// 2 - Weld vertices in faceted copy that are shared between triangles with less than "angle_cutoff" difference between normals  	// 3 - Generate smoothed set of normals based on welding results diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index b45bca626a..b81bc662a0 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -114,7 +114,7 @@ public:  		U32 num_verts,   		U32 num_indices); -	void smoothNormals(F32 angle_cutoff); +	void generateNormals(F32 angle_cutoff);  	void addFace(const LLVolumeFace& face); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 142767529e..ddc8774ea9 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -105,28 +105,54 @@ const S32 PREVIEW_TEXTURE_HEIGHT = 300;  void drawBoxOutline(const LLVector3& pos, const LLVector3& size); -std::string limit_name[] = + +std::string lod_name[] =   { -	"lowest limit", -	"low limit", -	"medium limit", -	"high limit", -	"physics limit", +	"lowest", +	"low", +	"medium", +	"high", +	"I went off the end of the lod_name array.  Me so smart." +}; -	"I went off the end of the limit_name array.  Me so smart." +std::string lod_triangles_name[] = +{ +	"lowest_triangles", +	"low_triangles", +	"medium_triangles", +	"high_triangles", +	"I went off the end of the lod_triangles_name array.  Me so smart."  }; -std::string info_name[] = +std::string lod_vertices_name[] =  { -	"lowest info", -	"low info", -	"medium info", -	"high info", -	"physics info", +	"lowest_vertices", +	"low_vertices", +	"medium_vertices", +	"high_vertices", +	"I went off the end of the lod_vertices_name array.  Me so smart." +}; -	"I went off the end of the info_name array.  Me so smart." +std::string lod_status_name[] = +{ +	"lowest_status", +	"low_status", +	"medium_status", +	"high_status", +	"I went off the end of the lod_status_name array.  Me so smart." +}; + +std::string lod_label_name[] = +{ +	"lowest_label", +	"low_label", +	"medium_label", +	"high_label", +	"I went off the end of the lod_label_name array.  Me so smart."  }; + +  bool validate_face(const LLVolumeFace& face)  {  	for (U32 i = 0; i < face.mNumIndices; ++i) @@ -185,20 +211,6 @@ BOOL stop_gloderror()  	return FALSE;  } -LLPhysicsDecompFloater::LLPhysicsDecompFloater(LLSD& key) -: LLFloater(key) -{ -	 -} - -LLPhysicsDecompFloater::~LLPhysicsDecompFloater() -{ -	if (LLFloaterModelPreview::sInstance && LLFloaterModelPreview::sInstance->mDecompFloater) -	{ -		LLFloaterModelPreview::sInstance->mDecompFloater = NULL; -	} -} -  class LLMeshFilePicker : public LLFilePickerThread  {  public: @@ -230,7 +242,6 @@ LLFloater(key)  	mLastMouseY = 0;  	mGLName = 0;  	mLoading = FALSE; -	mDecompFloater = NULL;  }  //----------------------------------------------------------------------------- @@ -243,75 +254,73 @@ BOOL LLFloaterModelPreview::postBuild()  		return FALSE;  	} -	childSetCommitCallback("high detail combo", onHighLODCommit, this); -	childSetCommitCallback("medium detail combo", onMediumLODCommit, this); -	childSetCommitCallback("low detail combo", onLowLODCommit, this); -	childSetCommitCallback("lowest detail combo", onLowestLODCommit, this); -	childSetCommitCallback("physics detail combo", onPhysicsLODCommit, this); -	 +	childSetAction("lod_browse", onBrowseLOD, this); +	childSetCommitCallback("lod_triangle_limit", onTriangleLimitCommit, this); -	childSetCommitCallback("high limit", onHighLimitCommit, this); -	childSetCommitCallback("medium limit", onMediumLimitCommit, this); -	childSetCommitCallback("low limit", onLowLimitCommit, this); -	childSetCommitCallback("lowest limit", onLowestLimitCommit, this); -	childSetCommitCallback("physics limit", onPhysicsLimitCommit, this); -	 -	childSetCommitCallback("smooth normals", onSmoothNormalsCommit, this); +	childSetCommitCallback("crease_angle", onGenerateNormalsCommit, this); +	childSetCommitCallback("generate_normals", onGenerateNormalsCommit, this);  	childSetCommitCallback("show edges", onShowEdgesCommit, this); -	childSetCommitCallback("auto fill", onAutoFillCommit, this); +	childSetCommitCallback("lod_generate", onAutoFillCommit, this);  	childSetTextArg("status", "[STATUS]", getString("status_idle")); -	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) -	{ -		if (lod == LLModel::LOD_PHYSICS) -		{ -			childSetTextArg(info_name[lod], "[TRIANGLES]", std::string("0")); -			childSetTextArg(info_name[lod], "[HULLS]", std::string("0")); -			childSetTextArg(info_name[lod], "[POINTS]", std::string("0")); -		} -		else -		{ -			childSetTextArg(info_name[lod], "[TRIANGLES]", std::string("0")); -			childSetTextArg(info_name[lod], "[VERTICES]", std::string("0")); -			childSetTextArg(info_name[lod], "[SUBMESHES]", std::string("0")); -			std::string msg = getString("required"); -			childSetTextArg(info_name[lod], "[MESSAGE]", msg); -		} -		 -		childSetVisible(limit_name[lod], FALSE); -	} -	  	//childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));  	childSetAction("ok_btn", onUpload, this);  	childSetAction("consolidate", onConsolidate, this); -	childSetAction("scrub materials", onScrubMaterials, this); -	 -	childSetAction("decompose_btn", onDecompose, this); +	childSetAction("clear_materials", onClearMaterials, this);  	childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);  	childSetCommitCallback("upload_skin", onUploadSkinCommit, this);  	childSetCommitCallback("upload_joints", onUploadJointsCommit, this); -	childSetCommitCallback("debug scale", onDebugScaleCommit, this); +	childSetCommitCallback("import_scale", onImportScaleCommit, this); + +	childSetCommitCallback("lod_file_or_limit", refresh, this); +	childSetCommitCallback("physics_load_radio", refresh, this);  	childDisable("upload_skin");  	childDisable("upload_joints"); -	const U32 width = 512; -	const U32 height = 512; +	initDecompControls(); -	mPreviewRect.set(getRect().getWidth()-PREVIEW_HPAD-width, -					 PREVIEW_HPAD+height, -					 getRect().getWidth()-PREVIEW_HPAD, -					 PREVIEW_HPAD); +	LLView* preview_panel = getChild<LLView>("preview_panel"); + +	mPreviewRect = preview_panel->getRect();  	mModelPreview = new LLModelPreview(512, 512, this);  	mModelPreview->setPreviewTarget(16.f); +	//set callbacks for left click on line editor rows +	for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) +	{ +		LLTextBox* text = getChild<LLTextBox>(lod_label_name[i]); +		if (text) +		{ +			text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i)); +		} + +		text = getChild<LLTextBox>(lod_triangles_name[i]); +		if (text) +		{ +			text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i)); +		} + +		text = getChild<LLTextBox>(lod_vertices_name[i]); +		if (text) +		{ +			text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i)); +		} + +		text = getChild<LLTextBox>(lod_status_name[i]); +		if (text) +		{ +			text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i)); +		} +	} +	  	return TRUE;  } @@ -333,12 +342,6 @@ LLFloaterModelPreview::~LLFloaterModelPreview()  	{  		LLImageGL::deleteTextures(1, &mGLName );  	} -	 -	if (mDecompFloater) -	{ -		mDecompFloater->closeFloater(); -		mDecompFloater = NULL; -	}	  }  void LLFloaterModelPreview::loadModel(S32 lod) @@ -348,58 +351,6 @@ void LLFloaterModelPreview::loadModel(S32 lod)  	(new LLMeshFilePicker(this, lod))->getFile();  } -void LLFloaterModelPreview::setLODMode(S32 lod, S32 mode) -{ -	if (mode == 0) -	{ -		if (lod != LLModel::LOD_PHYSICS) -		{ -			for (S32 i = lod; i >= 0; i--) -			{ -				mModelPreview->clearModel(i); -			} -		} -		else -		{ -			mModelPreview->clearModel(lod); -		} -		 -		mModelPreview->refresh(); -		mModelPreview->calcResourceCost(); -	} -	else if (mode == 1) -	{ -		loadModel(lod); -	} -	else if (mode != mModelPreview->mLODMode[lod]) -	{ -		mModelPreview->mLODMode[lod] = mode; -		mModelPreview->genLODs(lod); -	} -	 -	mModelPreview->setPreviewLOD(lod); -	 -	 -	LLSpinCtrl* lim = getChild<LLSpinCtrl>(limit_name[lod], TRUE); -	 -	if (mode == 2) //triangle count -	{ -		U32 tri_count = 0; -		for (LLModelLoader::model_list::iterator iter = mModelPreview->mBaseModel.begin(); -			 iter != mModelPreview->mBaseModel.end(); ++iter) -		{ -			tri_count += (*iter)->getNumTriangles(); -		} -		 -		lim->setMaxValue(tri_count); -		lim->setVisible(TRUE); -	} -	else -	{ -		lim->setVisible(FALSE); -	} -} -  void LLFloaterModelPreview::setLimit(S32 lod, S32 limit)  {  	if (limit != mModelPreview->mLimit[lod]) @@ -411,7 +362,7 @@ void LLFloaterModelPreview::setLimit(S32 lod, S32 limit)  }  //static  -void LLFloaterModelPreview::onDebugScaleCommit(LLUICtrl*,void* userdata) +void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)  {  	LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; @@ -421,6 +372,7 @@ void LLFloaterModelPreview::onDebugScaleCommit(LLUICtrl*,void* userdata)  	}  	fp->mModelPreview->calcResourceCost(); +	fp->mModelPreview->refresh();  }  //static  @@ -472,68 +424,6 @@ void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata)  }  //static  -void LLFloaterModelPreview::setLODMode(S32 lod, void* userdata) -{ -	LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; -	 -	if (!fp->mModelPreview) -	{ -		return; -	} -	 -	S32 which_mode = 0; -	 -	std::string combo_name[] = -	{ -		"lowest detail combo", -		"low detail combo", -		"medium detail combo", -		"high detail combo", -		"physics detail combo", -		 -		"I went off the end of the combo_name array.  Me so smart." -	}; -	 -	LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface(combo_name[lod]); -	if (iface) -	{ -		which_mode = iface->getFirstSelectedIndex(); -	} -	 -	fp->setLODMode(lod, which_mode); -} - -//static  -void LLFloaterModelPreview::onHighLODCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLODMode(3, userdata); -} - -//static  -void LLFloaterModelPreview::onMediumLODCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLODMode(2, userdata); -} - -//static  -void LLFloaterModelPreview::onLowLODCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLODMode(1, userdata); -} - -//static  -void LLFloaterModelPreview::onLowestLODCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLODMode(0, userdata); -} - -//static  -void LLFloaterModelPreview::onPhysicsLODCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLODMode(4, userdata); -} - -//static   void LLFloaterModelPreview::setLimit(S32 lod, void* userdata)  {  	LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; @@ -543,48 +433,26 @@ void LLFloaterModelPreview::setLimit(S32 lod, void* userdata)  		return;  	} -	S32 limit = fp->childGetValue(limit_name[lod]).asInteger(); +	S32 limit = fp->childGetValue("lod_triangle_limit").asInteger();  	fp->setLimit(lod, limit);  }  //static  -void LLFloaterModelPreview::onHighLimitCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLimit(3, userdata); -} - -//static  -void LLFloaterModelPreview::onMediumLimitCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLimit(2, userdata); -} - -//static  -void LLFloaterModelPreview::onLowLimitCommit(LLUICtrl* ctrl, void* userdata) +void LLFloaterModelPreview::onTriangleLimitCommit(LLUICtrl* ctrl, void* userdata)  { -	LLFloaterModelPreview::setLimit(1, userdata); -} +	LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; -//static  -void LLFloaterModelPreview::onLowestLimitCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLimit(0, userdata); -} - -//static  -void LLFloaterModelPreview::onPhysicsLimitCommit(LLUICtrl* ctrl, void* userdata) -{ -	LLFloaterModelPreview::setLimit(4, userdata); +	LLFloaterModelPreview::setLimit(fp->mModelPreview->mPreviewLOD, userdata);  }  //static -void LLFloaterModelPreview::onSmoothNormalsCommit(LLUICtrl* ctrl, void* userdata) +void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userdata)  {  	LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; -	fp->mModelPreview->smoothNormals(); +	fp->mModelPreview->generateNormals();  }  //static @@ -627,22 +495,14 @@ void LLFloaterModelPreview::draw()  		childSetTextArg("status", "[STATUS]", getString("status_idle"));  	} -	childSetTextArg("description_label", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost)); +	childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));  	childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); -	if (mDecompFloater) +	if (mCurRequest.notNull())  	{ -		if (mCurRequest.notNull()) -		{ -			mDecompFloater->childSetText("status", mCurRequest->mStatusMessage); -		} -		else -		{ -			const std::string idle("Idle."); -			mDecompFloater->childSetText("status", idle); -		} +		childSetTextArg("status", "[STATUS]", mCurRequest->mStatusMessage);  	} -	 +		  	U32 resource_cost = mModelPreview->mResourceCost*10;  	if (childGetValue("upload_textures").asBoolean()) @@ -658,6 +518,16 @@ void LLFloaterModelPreview::draw()  		gGL.getTexUnit(0)->bind(mModelPreview); + +		LLView* preview_panel = getChild<LLView>("preview_panel"); + +		LLRect rect = preview_panel->getRect(); +		if (rect != mPreviewRect) +		{ +			mModelPreview->refresh(); +			mPreviewRect = preview_panel->getRect(); +		} +		  		gGL.begin( LLRender::QUADS );  		{  			gGL.texCoord2f(0.f, 1.f); @@ -807,13 +677,10 @@ void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data)  		if (sInstance->mModelPreview)  		{ -			if (sInstance->mDecompFloater) +			S32 idx = sInstance->childGetValue("physics_layer").asInteger(); +			if (idx >= 0 && idx < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size())  			{ -				S32 idx = sInstance->mDecompFloater->childGetValue("model").asInteger(); -				if (idx >= 0 && idx < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size()) -				{ -					mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][idx]; -				} +				mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][idx];  			}  		}  	} @@ -823,276 +690,198 @@ void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data)  		sInstance->mCurRequest = new DecompRequest(stage->mName, mdl);  		gMeshRepo.mDecompThread->submitRequest(sInstance->mCurRequest);  	} + +	const std::string decompose("Decompose"); + +	if (decompose == stage->mName) +	{ //hide decompose panel and show simplify panel +		sInstance->childSetVisible("physics step 2", false); +		sInstance->childSetVisible("physics step 3", true); +	}  }  //static -void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data) +void LLFloaterModelPreview::onPhysicsOptimize(LLUICtrl* ctrl, void *data)  { -	if (sInstance && sInstance->mCurRequest.notNull()) -	{ -		sInstance->mCurRequest->mContinue = 0; -	} +	//hide step 1 panel and show step 2 panel + info +	sInstance->childSetVisible("physics step 1", false); +	sInstance->childSetVisible("physics step 2", true); +	sInstance->childSetVisible("physics info", true);  } -void LLFloaterModelPreview::showDecompFloater() +//static  +void LLFloaterModelPreview::onPhysicsBrowse(LLUICtrl* ctrl, void* userdata) +{ +	sInstance->loadModel(LLModel::LOD_PHYSICS); +} + +//static  +void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)  { -	if (!mDecompFloater) +	S32 which_mode = 3; +	LLCtrlSelectionInterface* iface = sInstance->childGetSelectionInterface("physics_lod_combo"); +	if (iface)  	{ -		LLSD key; -		mDecompFloater = new LLPhysicsDecompFloater(key); -		 -		S32 left = 20; -		S32 right = 320; -		 -		S32 cur_y = 30; +		which_mode = iface->getFirstSelectedIndex(); +	} -		{ -			//add status text -			LLTextBox::Params p; -			p.name("status"); -			p.rect(LLRect(left, cur_y, right-80, cur_y-20)); -			mDecompFloater->addChild(LLUICtrlFactory::create<LLTextBox>(p)); -		} +	sInstance->mModelPreview->setPhysicsFromLOD(which_mode); +} +//static  +void LLFloaterModelPreview::onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata) +{ +	//hide step 2 panel and info and show step 1 panel +	sInstance->childSetVisible("physics step 1", true); +	sInstance->childSetVisible("physics step 2", false); +	sInstance->childSetVisible("physics info", false); +} -		{ //add cancel button -			LLButton::Params p; -			p.name("Cancel"); -			p.label("Cancel"); -			p.rect(LLRect(right-80, cur_y, right, cur_y-20));		 -			LLButton* button = LLUICtrlFactory::create<LLButton>(p); -			button->setCommitCallback(onPhysicsStageCancel, NULL);		 -			mDecompFloater->addChild(button); -		} +//static  +void LLFloaterModelPreview::onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata) +{ +	//hide step 3 panel and show step 2 panel +	sInstance->childSetVisible("physics step 3", false); +	sInstance->childSetVisible("physics step 2", true); +} +	 +//static +void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data) +{ +	if (sInstance && sInstance->mCurRequest.notNull()) +	{ +		sInstance->mCurRequest->mContinue = 0; +	} +} -		cur_y += 30; +void LLFloaterModelPreview::initDecompControls() +{ +	LLSD key; +	childSetCommitCallback("cancel_btn", onPhysicsStageCancel, NULL); +	childSetCommitCallback("physics_lod_combo", onPhysicsUseLOD, NULL); +	childSetCommitCallback("physics_browse", onPhysicsBrowse, NULL); +	childSetCommitCallback("physics_optimize", onPhysicsOptimize, NULL); +	childSetCommitCallback("decompose_back", onPhysicsDecomposeBack, NULL); +	childSetCommitCallback("simplify_back", onPhysicsSimplifyBack, NULL); +	childSetCommitCallback("physics_layer", refresh, NULL); -		static const LLCDStageData* stage = NULL; -		static S32 stage_count = 0; +	static const LLCDStageData* stage = NULL; +	static S32 stage_count = 0; -		if (!stage && LLConvexDecomposition::getInstance() != NULL) -		{ -			stage_count = LLConvexDecomposition::getInstance()->getStages(&stage); -		} +	if (!stage && LLConvexDecomposition::getInstance() != NULL) +	{ +		stage_count = LLConvexDecomposition::getInstance()->getStages(&stage); +	} -		static const LLCDParam* param = NULL; -		static S32 param_count = 0; -		if (!param && LLConvexDecomposition::getInstance() != NULL) -		{ -			param_count = LLConvexDecomposition::getInstance()->getParameters(¶m); -		} +	static const LLCDParam* param = NULL; +	static S32 param_count = 0; +	if (!param && LLConvexDecomposition::getInstance() != NULL) +	{ +		param_count = LLConvexDecomposition::getInstance()->getParameters(¶m); +	} -		for (S32 j = stage_count-1; j >= 0; --j) +	for (S32 j = stage_count-1; j >= 0; --j) +	{ +		LLButton* button = getChild<LLButton>(stage[j].mName); +		if (button)  		{ -			LLButton::Params p; -			p.name(stage[j].mName); -			p.label(stage[j].mName); -			p.rect(LLRect(left, cur_y, right, cur_y-20));		 -			LLButton* button = LLUICtrlFactory::create<LLButton>(p);  			button->setCommitCallback(onPhysicsStageExecute, (void*) &stage[j]);		 -			mDecompFloater->addChild(button); -			gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j; -			cur_y += 30; -			// protected against stub by stage_count being 0 for stub above -			LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback); +		} + +		gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j; +		// protected against stub by stage_count being 0 for stub above +		LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback); -			llinfos << "Physics decomp stage " << stage[j].mName << " (" << j << ") parameters:" << llendl; -			llinfos << "------------------------------------" << llendl; +		//llinfos << "Physics decomp stage " << stage[j].mName << " (" << j << ") parameters:" << llendl; +		//llinfos << "------------------------------------" << llendl; -			for (S32 i = 0; i < param_count; ++i) +		for (S32 i = 0; i < param_count; ++i) +		{ +			if (param[i].mStage != j)  			{ -				if (param[i].mStage != j) -				{ -					continue; -				} +				continue; +			} -				std::string name(param[i].mName ? param[i].mName : ""); -				std::string description(param[i].mDescription ? param[i].mDescription : ""); +			std::string name(param[i].mName ? param[i].mName : ""); +			std::string description(param[i].mDescription ? param[i].mDescription : ""); -				std::string type = "unknown"; +			std::string type = "unknown"; -				llinfos << name << " - " << description << llendl; +			llinfos << name << " - " << description << llendl; -				if (param[i].mType == LLCDParam::LLCD_FLOAT) -				{ -					mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat); -					llinfos << "Type: float, Default: " << param[i].mDefault.mFloat << llendl; +			if (param[i].mType == LLCDParam::LLCD_FLOAT) +			{ +				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat); +				//llinfos << "Type: float, Default: " << param[i].mDefault.mFloat << llendl; -					LLSliderCtrl::Params p; -					p.name(name); -					p.label(name); -					p.rect(LLRect(left, cur_y, right, cur_y-20)); -					p.min_value(param[i].mDetails.mRange.mLow.mFloat); -					p.max_value(param[i].mDetails.mRange.mHigh.mFloat); -					p.increment(param[i].mDetails.mRange.mDelta.mFloat); -					p.tool_tip(description); -					p.decimal_digits(3); -					p.initial_value(param[i].mDefault.mFloat); -					LLSliderCtrl* slider = LLUICtrlFactory::create<LLSliderCtrl>(p); +				LLSliderCtrl* slider = getChild<LLSliderCtrl>(name); +				if (slider) +				{ +					slider->setMinValue(param[i].mDetails.mRange.mLow.mFloat); +					slider->setMaxValue(param[i].mDetails.mRange.mHigh.mFloat); +					slider->setIncrement(param[i].mDetails.mRange.mDelta.mFloat); +					slider->setValue(param[i].mDefault.mFloat);  					slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); -					mDecompFloater->addChild(slider); -					cur_y += 30;  				} -				else if (param[i].mType == LLCDParam::LLCD_INTEGER) +			} +			else if (param[i].mType == LLCDParam::LLCD_INTEGER) +			{ +				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); +				//llinfos << "Type: integer, Default: " << param[i].mDefault.mIntOrEnumValue << llendl; +				 +				LLSliderCtrl* slider = getChild<LLSliderCtrl>(name); +				if (slider)  				{ -					mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); -					llinfos << "Type: integer, Default: " << param[i].mDefault.mIntOrEnumValue << llendl; -					LLSliderCtrl::Params p; -					p.name(name); -					p.label(name); -					p.rect(LLRect(left, cur_y, right, cur_y-20)); -					p.min_value(param[i].mDetails.mRange.mLow.mIntOrEnumValue); -					p.max_value(param[i].mDetails.mRange.mHigh.mIntOrEnumValue); -					p.increment(param[i].mDetails.mRange.mDelta.mIntOrEnumValue); -					p.tool_tip(description); -					p.initial_value(param[i].mDefault.mIntOrEnumValue); -					LLSliderCtrl* slider = LLUICtrlFactory::create<LLSliderCtrl>(p); +					slider->setMinValue(param[i].mDetails.mRange.mLow.mIntOrEnumValue); +					slider->setMaxValue(param[i].mDetails.mRange.mHigh.mIntOrEnumValue); +					slider->setIncrement(param[i].mDetails.mRange.mDelta.mIntOrEnumValue); +					slider->setValue(param[i].mDefault.mIntOrEnumValue);  					slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); -					mDecompFloater->addChild(slider);	 -					cur_y += 30;  				} -				else if (param[i].mType == LLCDParam::LLCD_BOOLEAN) -				{ -					mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool); -					llinfos << "Type: boolean, Default: " << (param[i].mDefault.mBool ? "True" : "False") << llendl; +			} +			else if (param[i].mType == LLCDParam::LLCD_BOOLEAN) +			{ +				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool); +				//llinfos << "Type: boolean, Default: " << (param[i].mDefault.mBool ? "True" : "False") << llendl; -					LLCheckBoxCtrl::Params p; -					p.rect(LLRect(left, cur_y, right, cur_y-20)); -					p.name(name); -					p.label(name); -					p.initial_value(param[i].mDefault.mBool); -					p.tool_tip(description); -					LLCheckBoxCtrl* check_box = LLUICtrlFactory::create<LLCheckBoxCtrl>(p); +				LLCheckBoxCtrl* check_box = getChild<LLCheckBoxCtrl>(name); +				if (check_box) +				{ +					check_box->setValue(param[i].mDefault.mBool);  					check_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); -					mDecompFloater->addChild(check_box); -					cur_y += 30;  				} -				else if (param[i].mType == LLCDParam::LLCD_ENUM) -				{ -					S32 cur_x = left; -					mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); -					llinfos << "Type: enum, Default: " << param[i].mDefault.mIntOrEnumValue << llendl; +			} +			else if (param[i].mType == LLCDParam::LLCD_ENUM) +			{ +				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); +				//llinfos << "Type: enum, Default: " << param[i].mDefault.mIntOrEnumValue << llendl; -					{ //add label -						LLTextBox::Params p; -						const LLFontGL* font = (LLFontGL*) p.font(); -						 -						p.rect(LLRect(left, cur_y, left+font->getWidth(name), cur_y-20)); -						p.name(name); -						p.label(name); -						p.initial_value(name); -						LLTextBox* text_box = LLUICtrlFactory::create<LLTextBox>(p); -						mDecompFloater->addChild(text_box); -						cur_x += text_box->getRect().getWidth(); -					} +				{ //plug into combo box -					{ //add combo_box -						LLComboBox::Params p; -						p.rect(LLRect(cur_x, cur_y, right-right/4, cur_y-20)); -						p.name(name); -						p.label(name); -						p.tool_tip(description); -						 -						llinfos << "Accepted values: " << llendl; -						LLComboBox* combo_box = LLUICtrlFactory::create<LLComboBox>(p); -						for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k) -						{ -							llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue  -							<< " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl; +					//llinfos << "Accepted values: " << llendl; +					LLComboBox* combo_box = getChild<LLComboBox>(name); +					for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k) +					{ +						//llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue  +						//	<< " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl; -							combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName,  -										   LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue)); -						} -						combo_box->setValue(param[i].mDefault.mIntOrEnumValue); -						combo_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); -						mDecompFloater->addChild(combo_box); -						cur_y += 30; -						 +						combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName,  +							LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue));  					} -					 -					llinfos << "----" << llendl; +					combo_box->setValue(param[i].mDefault.mIntOrEnumValue); +					combo_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]);  				} -				llinfos << "-----------------------------" << llendl; -			} -		} -		cur_y += 30; -		//explode slider -		{ -			LLSliderCtrl::Params p; -			p.initial_value(0); -			p.min_value(0); -			p.max_value(1); -			p.decimal_digits(2); -			p.increment(0.05f); -			p.label("Explode"); -			p.name("explode"); -			p.rect(LLRect(left, cur_y, right, cur_y-20)); -			LLSliderCtrl* slider = LLUICtrlFactory::create<LLSliderCtrl>(p); -			 -			mDecompFloater->addChild(slider); -			cur_y += 30; -		} -		 -		//mesh render checkbox -		{ -			LLCheckBoxCtrl::Params p; -			p.label("Mesh: "); -			p.name("render_mesh"); -			p.rect(LLRect(left, cur_y, right/4, cur_y-20)); -			LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(p); -			check->setValue(true); -			mDecompFloater->addChild(check); -		} -		 -		//hull render checkbox -		{ -			LLCheckBoxCtrl::Params p; -			p.label("Hull: "); -			p.name("render_hull"); -			p.rect(LLRect(right/4, cur_y, right/2, cur_y-20)); -			LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(p); -			check->setValue(true); -			mDecompFloater->addChild(check); -		} -		 -		{ //submesh combo box label -			LLTextBox::Params p; -			p.label("Model"); -			p.name("model label"); -			p.rect(LLRect(right/2, cur_y, right-right/3, cur_y-20)); -			LLTextBox* text_box = LLUICtrlFactory::create<LLTextBox>(p); -			text_box->setValue("Model"); -			mDecompFloater->addChild(text_box); -		} -		 -		{ -			//add submesh combo box -			LLComboBox::Params p; -			p.rect(LLRect(right-right/2+p.font()->getWidth("Model"), cur_y, right, cur_y-20)); -			p.name("model"); -			LLComboBox* combo_box = LLUICtrlFactory::create<LLComboBox>(p); -			for (S32 i = 0; i < mModelPreview->mBaseModel.size(); ++i) -			{ -				LLModel* mdl = mModelPreview->mBaseModel[i]; -				combo_box->add(mdl->mLabel, i); +				//llinfos << "----" << llendl;  			} -			combo_box->setValue(0); -			mDecompFloater->addChild(combo_box); -			cur_y += 30; +			//llinfos << "-----------------------------" << llendl;  		} -		 -		mDecompFloater->childSetCommitCallback("model", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); -		mDecompFloater->childSetCommitCallback("render_mesh", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); -		mDecompFloater->childSetCommitCallback("render_hull", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); -		 -		mDecompFloater->setRect(LLRect(10, cur_y+20, right+20, 10));   	} -	 -	mDecompFloater->childSetCommitCallback("explode", LLFloaterModelPreview::onExplodeCommit, this); -	 -	mDecompFloater->openFloater(); +		 +	childSetCommitCallback("physics_layer", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); +	childSetCommitCallback("physics_explode", LLFloaterModelPreview::onExplodeCommit, this); +	childSetCommitCallback("show physics", LLFloaterModelPreview::refresh, this);  }  //----------------------------------------------------------------------------- @@ -2197,18 +1986,15 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloaterModelPreview* fmp  	mCameraPitch = 0.f;  	mCameraZoom = 1.f;  	mTextureName = 0; -	mPreviewLOD = 3; +	mPreviewLOD = 0;  	mModelLoader = NULL;  	mDirty = false;  	for (U32 i = 0; i < LLModel::NUM_LODS; i++)  	{ -		mLODMode[i] = 1;  		mLimit[i] = 0;  	} -	mLODMode[0] = 0; -	  	mFMP = fmp;  	glodInit(); @@ -2235,10 +2021,9 @@ U32 LLModelPreview::calcResourceCost()  	U32 num_points = 0;  	U32 num_hulls = 0; -	F32 debug_scale = mFMP->childGetValue("debug scale").asReal(); +	F32 debug_scale = mFMP->childGetValue("import_scale").asReal();  	F32 streaming_cost = 0.f; -	  	for (U32 i = 0; i < mUploadData.size(); ++i)  	{  		LLModelInstance& instance = mUploadData[i]; @@ -2290,13 +2075,13 @@ U32 LLModelPreview::calcResourceCost()  		}  	} -	mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",num_hulls)); -	mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",num_points));				 +	//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",num_hulls)); +	//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",num_points));				  	mFMP->childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost));  -	F32 scale = mFMP->childGetValue("debug scale").asReal()*2.f; -	mFMP->childSetTextArg("dimensions", "[X]", llformat("%.3f", mPreviewScale[0]*scale)); -	mFMP->childSetTextArg("dimensions", "[Y]", llformat("%.3f", mPreviewScale[1]*scale)); -	mFMP->childSetTextArg("dimensions", "[Z]", llformat("%.3f", mPreviewScale[2]*scale)); +	F32 scale = mFMP->childGetValue("import_scale").asReal()*2.f; +	mFMP->childSetTextArg("import_dimensions", "[X]", llformat("%.3f", mPreviewScale[0]*scale)); +	mFMP->childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", mPreviewScale[1]*scale)); +	mFMP->childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", mPreviewScale[2]*scale));  	updateStatusMessages(); @@ -2310,11 +2095,11 @@ void LLModelPreview::rebuildUploadData()  	//fill uploaddata instance vectors from scene data -	LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("debug scale"); +	LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");  	if (!scale_spinner)  	{ -		llerrs << "floater_model_preview.xml MUST contain debug scale spinner." << llendl; +		llerrs << "floater_model_preview.xml MUST contain import_scale spinner." << llendl;  	}  	F32 scale = scale_spinner->getValue().asReal(); @@ -2383,6 +2168,21 @@ void LLModelPreview::rebuildUploadData()  	{  		scale_spinner->setValue(max_import_scale);  	} + +	//refill "layer" combo in physics panel +	LLComboBox* combo_box = mFMP->getChild<LLComboBox>("physics_layer"); +	if (combo_box) +	{ +		S32 current = combo_box->getCurrentIndex(); +		combo_box->removeall(); +	 +		for (S32 i = 0; i < mBaseModel.size(); ++i) +		{ +			LLModel* mdl = mBaseModel[i]; +			combo_box->add(mdl->mLabel, i); +		} +		combo_box->setCurrentByIndex(current); +	}  } @@ -2421,6 +2221,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)  		return;  	} +	mLODFile[lod] = filename; +  	if (lod == 3 && !mGroup.empty())  	{  		for (std::map<LLPointer<LLModel>, U32>::iterator iter = mGroup.begin(); iter != mGroup.end(); ++iter) @@ -2445,15 +2247,34 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)  	mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); -	if (mFMP->childGetValue("description_form").asString().empty()) +	setPreviewLOD(lod); + +	if (lod == mPreviewLOD)  	{ -		std::string name = gDirUtilp->getBaseFileName(filename, true); -		mFMP->childSetValue("description_form", name); +		mFMP->childSetText("lod_file", mLODFile[mPreviewLOD]); +	} +	else if (lod == LLModel::LOD_PHYSICS) +	{ +		mFMP->childSetText("physics_file", mLODFile[lod]);  	}  	mFMP->openFloater();  } +void LLModelPreview::setPhysicsFromLOD(S32 lod) +{ +	if (lod >= 0 && lod <= 3) +	{ +		mModel[LLModel::LOD_PHYSICS] = mModel[lod]; +		mScene[LLModel::LOD_PHYSICS] = mScene[lod]; +		mLODFile[LLModel::LOD_PHYSICS].clear(); +		mFMP->childSetText("physics_file", mLODFile[LLModel::LOD_PHYSICS]); +		mVertexBuffer[LLModel::LOD_PHYSICS].clear(); +		rebuildUploadData(); +		refresh(); +	} +} +  void LLModelPreview::clearIncompatible(S32 lod)  {  	for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) @@ -2522,7 +2343,7 @@ void LLModelPreview::resetPreviewTarget()  	setPreviewTarget(mPreviewScale.magVec()*2.f);  } -void LLModelPreview::smoothNormals() +void LLModelPreview::generateNormals()  {  	S32 which_lod = mPreviewLOD; @@ -2533,7 +2354,7 @@ void LLModelPreview::smoothNormals()  		return;  	} -	F32 angle_cutoff = mFMP->childGetValue("edge threshold").asReal(); +	F32 angle_cutoff = mFMP->childGetValue("crease_angle").asReal();  	angle_cutoff *= DEG_TO_RAD; @@ -2541,7 +2362,7 @@ void LLModelPreview::smoothNormals()  	{  		for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter)  		{ -			(*iter)->smoothNormals(angle_cutoff); +			(*iter)->generateNormals(angle_cutoff);  		}  		mVertexBuffer[5].clear(); @@ -2549,7 +2370,7 @@ void LLModelPreview::smoothNormals()  	for (LLModelLoader::model_list::iterator iter = mModel[which_lod].begin(); iter != mModel[which_lod].end(); ++iter)  	{ -		(*iter)->smoothNormals(angle_cutoff); +		(*iter)->generateNormals(angle_cutoff);  	}  	mVertexBuffer[which_lod].clear(); @@ -2738,7 +2559,7 @@ void LLModelPreview::consolidate()  	refresh();  } -void LLModelPreview::scrubMaterials() +void LLModelPreview::clearMaterials()  {  	for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)  	{ //for each transform in current scene @@ -2761,7 +2582,6 @@ void LLModelPreview::scrubMaterials()  		}  	} -	  	mVertexBuffer[mPreviewLOD].clear();  	if (mPreviewLOD == LLModel::LOD_HIGH) @@ -2925,24 +2745,8 @@ void LLModelPreview::genLODs(S32 which_lod)  		start = end = which_lod;  	} -	 -	std::string combo_name[] =  -	{ -		"lowest detail combo", -		"low detail combo", -		"medium detail combo", -		"high detail combo", -		"physics detail combo" -	}; -	 -	std::string limit_name[] = -	{ -		"lowest limit", -		"low limit", -		"medium limit", -		"high limit", -		"physics limit" -	}; +	LLSpinCtrl* lim = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit", TRUE); +	lim->setMaxValue(base_triangle_count);  	for (S32 lod = start; lod >= end; --lod)  	{ @@ -2958,13 +2762,6 @@ void LLModelPreview::genLODs(S32 which_lod)  			triangle_count = limit;  		} -		LLComboBox* combo_box = mFMP->findChild<LLComboBox>(combo_name[lod]); -		combo_box->setCurrentByIndex(2); -		 -		LLSpinCtrl* lim = mFMP->getChild<LLSpinCtrl>(limit_name[lod], TRUE); -		lim->setMaxValue(base_triangle_count); -		lim->setVisible(true); -		  		mModel[lod].clear();  		mModel[lod].resize(mBaseModel.size());  		mVertexBuffer[lod].clear(); @@ -3154,32 +2951,44 @@ void LLModelPreview::updateStatusMessages()  		}  	} +	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); -	std::string upload_message; +	std::string mesh_status_good = mFMP->getString("mesh_status_good"); +	std::string mesh_status_bad = mFMP->getString("mesh_status_bad"); +	std::string mesh_status_na = mFMP->getString("mesh_status_na"); +	std::string mesh_status_none = mFMP->getString("mesh_status_none"); -	mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[TRIANGLES]", llformat("%d", total_tris[LLModel::LOD_PHYSICS])); +	bool upload_ok = true;  	for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)  	{ -		mFMP->childSetTextArg(info_name[lod], "[TRIANGLES]", llformat("%d", total_tris[lod])); -		mFMP->childSetTextArg(info_name[lod], "[VERTICES]", llformat("%d", total_verts[lod])); -		mFMP->childSetTextArg(info_name[lod], "[SUBMESHES]", llformat("%d", total_submeshes[lod])); +		if (total_tris[lod] > 0) +		{ +			mFMP->childSetText(lod_triangles_name[lod], llformat("%d", total_tris[lod])); +			mFMP->childSetText(lod_vertices_name[lod], llformat("%d", total_verts[lod])); +		} +		else +		{ +			mFMP->childSetText(lod_triangles_name[lod], mesh_status_na); +			mFMP->childSetText(lod_vertices_name[lod], mesh_status_na); +		} +		 -		std::string message = "good"; +		std::string message = mesh_status_good;  		const U32 lod_high = LLModel::LOD_HIGH;  		if (lod != lod_high)  		{  			if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high]) -			{ -				message = "mesh_mismatch"; -				upload_message = "bad_lod"; +			{ //number of submeshes is different +				message = mesh_status_bad; +				upload_ok = false;  			}  			else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size()) -			{ -				message = "model_mismatch"; -				upload_message = "bad_lod"; +			{ //number of meshes is different +				message = mesh_status_bad; +				upload_ok = false;  			}  			else if (!verts[lod].empty())  			{ @@ -3188,27 +2997,119 @@ void LLModelPreview::updateStatusMessages()  					S32 max_verts = verts[lod+1][i];  					if (verts[lod][i] > max_verts) -					{ -						message = "too_heavy"; -						upload_message = "bad_lod"; +					{ //too many vertices in this lod +						message = mesh_status_bad; +						upload_ok = false;  					}  				}  			} +			else +			{ //no mesh +				message = mesh_status_none; +			}  		} -		mFMP->childSetTextArg(info_name[lod], "[MESSAGE]", mFMP->getString(message)); +		mFMP->childSetText(lod_status_name[lod], message);  	} -	if (upload_message.empty()) +	if (upload_ok)  	{ -		mFMP->childSetTextArg("upload_message", "[MESSAGE]", std::string(""));  		mFMP->childEnable("ok_btn");  	}  	else  	{ -		mFMP->childSetTextArg("upload_message", "[MESSAGE]", mFMP->getString(upload_message));  		mFMP->childDisable("ok_btn");  	} + +	//add up physics triangles etc +	S32 start = 0; +	S32 end = mModel[LLModel::LOD_PHYSICS].size(); + +	S32 idx = mFMP->childGetValue("physics_layer").asInteger(); + +	if (idx >= 0 && idx < mModel[LLModel::LOD_PHYSICS].size()) +	{ +		start = idx; +		end = idx+1; +	} + +	S32 phys_tris = 0; +	S32 phys_hulls = 0; +	S32 phys_points = 0; + +	for (S32 i = start; i < end; ++i) +	{ //add up hulls and points and triangles for selected mesh(es) +		LLModel* model = mModel[LLModel::LOD_PHYSICS][i]; +		S32 cur_submeshes = model->getNumVolumeFaces(); + +		LLModel::convex_hull_decomposition& decomp = model->mConvexHullDecomp; + +		if (!decomp.empty()) +		{ +			phys_hulls += decomp.size(); +			for (U32 i = 0; i < decomp.size(); ++i) +			{ +				phys_points += decomp[i].size(); +			} +		} +		else +		{ //choose physics shape OR decomposition, can't use both +			for (S32 j = 0; j < cur_submeshes; ++j) +			{ //for each submesh (face), add triangles and vertices to current total +				const LLVolumeFace& face = model->getVolumeFace(j); +				phys_tris += face.mNumIndices/3; +			} +		} +	} + +	if (phys_tris > 0) +	{ +		mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", llformat("%d", phys_tris)); +	} +	else +	{ +		mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", mesh_status_na); +	} + +	if (phys_hulls > 0) +	{ +		mFMP->childSetTextArg("physics_hulls", "[HULLS]", llformat("%d", phys_hulls)); +		mFMP->childSetTextArg("physics_points", "[POINTS]", llformat("%d", phys_points)); +	} +	else +	{ +		mFMP->childSetTextArg("physics_hulls", "[HULLS]", mesh_status_na); +		mFMP->childSetTextArg("physics_points", "[POINTS]", mesh_status_na); +	} + +	//enable/disable controls based on radio groups +	if (mFMP->childGetValue("lod_from_file").asBoolean()) +	{  +		mFMP->childDisable("lod_triangle_limit"); +		mFMP->childDisable("lod_generate"); +		mFMP->childEnable("lod_file"); +		mFMP->childEnable("lod_browse"); +	} +	else +	{ +		mFMP->childEnable("lod_triangle_limit"); +		mFMP->childEnable("lod_generate"); +		mFMP->childDisable("lod_file"); +		mFMP->childDisable("lod_browse"); +	} + +	if (mFMP->childGetValue("physics_load_from_file").asBoolean()) +	{ +		mFMP->childDisable("physics_lod_combo"); +		mFMP->childEnable("physics_file"); +		mFMP->childEnable("physics_browse"); +	} +	else +	{ +		mFMP->childEnable("physics_lod_combo"); +		mFMP->childDisable("physics_file"); +		mFMP->childDisable("physics_browse"); +	}  }  void LLModelPreview::setPreviewTarget(F32 distance) @@ -3360,6 +3261,7 @@ void LLModelPreview::update()  	{  		mDirty = false;  		mResourceCost = calcResourceCost(); +		refresh();  	}  } @@ -3380,19 +3282,28 @@ BOOL LLModelPreview::render()  	LLGLDepthTest depth(GL_TRUE);  	LLGLDisable fog(GL_FOG); -	glMatrixMode(GL_PROJECTION); -	gGL.pushMatrix(); -	glLoadIdentity(); -	glOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f); -	 -	glMatrixMode(GL_MODELVIEW); -	gGL.pushMatrix(); -	glLoadIdentity(); +	{ +		//clear background to blue +		glMatrixMode(GL_PROJECTION); +		gGL.pushMatrix(); +		glLoadIdentity(); +		glOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f); -	gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); +		glMatrixMode(GL_MODELVIEW); +		gGL.pushMatrix(); +		glLoadIdentity(); +			 +		gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); -	gl_rect_2d_simple( width, height ); +		gl_rect_2d_simple( width, height ); +		glMatrixMode(GL_PROJECTION); +		gGL.popMatrix(); + +		glMatrixMode(GL_MODELVIEW); +		gGL.popMatrix(); +	} +  	bool avatar_preview = false;  	bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();  	bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean(); @@ -3445,24 +3356,20 @@ BOOL LLModelPreview::render()  	mFMP->childSetEnabled("consolidate", !avatar_preview); -	F32 explode = mFMP->mDecompFloater ? mFMP->mDecompFloater->childGetValue("explode").asReal() : 0.f; -	 -	glMatrixMode(GL_PROJECTION); -	gGL.popMatrix(); -	 -	glMatrixMode(GL_MODELVIEW); -	gGL.popMatrix(); +	F32 explode = mFMP->childGetValue("physics_explode").asReal();  	glClear(GL_DEPTH_BUFFER_BIT); -	LLViewerCamera::getInstance()->setAspect((F32) width / height ); +	F32 aspect = (F32) mFMP->mPreviewRect.getWidth()/mFMP->mPreviewRect.getHeight(); + +	LLViewerCamera::getInstance()->setAspect(aspect);  	LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); -	LLVector3 target_pos = mPreviewTarget;  	LLVector3 offset = mCameraOffset; +	LLVector3 target_pos = mPreviewTarget+offset; -	F32 z_near = llmax(mCameraDistance-mPreviewScale.magVec(), 0.001f); -	F32 z_far = mCameraDistance+mPreviewScale.magVec(); +	F32 z_near = 0.001f; +	F32 z_far = mCameraDistance+mPreviewScale.magVec()+mCameraOffset.magVec();  	if (avatar_preview)  	{ @@ -3504,19 +3411,8 @@ BOOL LLModelPreview::render()  		//genLODs();  	} -	bool physics = (mPreviewLOD == LLModel::LOD_PHYSICS); -	 -	S32 physics_idx = -1; -	 -	bool render_mesh = true; -	bool render_hull = false; -	 -	if (physics && mFMP->mDecompFloater) -	{ -		physics_idx = mFMP->mDecompFloater->childGetValue("model").asInteger(); -		render_mesh = mFMP->mDecompFloater->childGetValue("render_mesh").asBoolean(); -		render_hull = mFMP->mDecompFloater->childGetValue("render_hull").asBoolean(); -	} +	bool physics = mFMP->childGetValue("show physics").asBoolean(); +	S32 physics_idx = mFMP->childGetValue("physics_layer").asInteger();  	if (!mModel[mPreviewLOD].empty())  	{ @@ -3527,68 +3423,175 @@ BOOL LLModelPreview::render()  		if (!avatar_preview)  		{ -			//for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)  			for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)  			{  				LLModelInstance& instance = *iter; +				LLModel* model = instance.mLOD[mPreviewLOD]; +					 +				if (!model) +				{ +					continue; +				} +					  				gGL.pushMatrix();  				LLMatrix4 mat = instance.mTransform; + +				glMultMatrixf((GLfloat*) mat.mMatrix);		 +					 +				for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) +				{ +					LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; +							 +					buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); +					 +					glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); +					if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull()) +					{ +						gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); +						if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) +						{ +							mTextureSet.insert(instance.mMaterial[i].mDiffuseMap); +						} +					} +					 +					buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); +					gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +					glColor3f(0.4f, 0.4f, 0.4f); +							 +					if (mFMP->childGetValue("show edges").asBoolean()) +					{ +						glLineWidth(3.f); +						glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +						buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); +						glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +						glLineWidth(1.f); +					} +				} +				gGL.popMatrix(); +			} +		 +			if (physics) +			{ +				glClear(GL_DEPTH_BUFFER_BIT); +				LLGLEnable blend(GL_BLEND); +				gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ZERO); + +				LLModel* physics_model = NULL; -				glMultMatrixf((GLfloat*) mat.mMatrix);				 -				 -				//for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) +				if (physics_idx >= 0 && physics_idx < mModel[LLModel::LOD_PHYSICS].size() ) +				{ +					physics_model = mModel[LLModel::LOD_PHYSICS][physics_idx]; +				} + +				for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)  				{ -					//LLModelInstance& instance = *model_iter; -					LLModel* model = instance.mLOD[mPreviewLOD]; +					LLModelInstance& instance = *iter; +					LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS]; +  					if (!model)  					{  						continue;  					} + +					gGL.pushMatrix(); +					LLMatrix4 mat = instance.mTransform; + +					glMultMatrixf((GLfloat*) mat.mMatrix);				 + -					//if (instance.mTransform != mat) -					//{ -					//	llerrs << "WTF?" << llendl; -					//} -					 -					if (render_mesh) +					bool render_mesh = true; + +					LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; +					if (decomp)  					{ -						for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) +						LLMutexLock(decomp->mMutex); +											 +						std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > >::iterator iter =  +							mPhysicsMesh.find(model); +						if (iter != mPhysicsMesh.end())  						{ -							LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; -							 -							buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); -							if (physics) +							render_mesh = false; +							for (U32 i = 0; i < iter->second.size(); ++i)  							{ -								if (physics_idx > -1 && model == mModel[mPreviewLOD][physics_idx]) +								if (explode > 0.f)  								{ -									glColor4f(1,0,0,1); +									gGL.pushMatrix(); +										 +									LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; +									offset *= explode; +										 +									gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);  								} -								else +									 +								static std::vector<LLColor4U> hull_colors; +									 +								if (i+1 >= hull_colors.size()) +								{ +									hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255)); +								} +									 +								LLVertexBuffer* buff = iter->second[i]; +								if (buff) +								{ +									buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);			 +										 +									glColor4ubv(hull_colors[i].mV); +									buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); +								 +									if (mFMP->childGetValue("show edges").asBoolean()) +									{ +										glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +										glLineWidth(3.f); +										glColor4ub(hull_colors[i].mV[0]/2, hull_colors[i].mV[1]/2, hull_colors[i].mV[2]/2, 255); +										buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); +										glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +										glLineWidth(1.f); +									}	 +								} +									 +								if (explode > 0.f)  								{ -									glColor4f(0.75f, 0.75f, 0.75f, 1.f); +									gGL.popMatrix();  								}  							} -							else +						} +					} +						 +					if (render_mesh) +					{ +						if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) +						{ +							genBuffers(LLModel::LOD_PHYSICS, false); +						} +						for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) +						{ +							LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + +							buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); +							 +							glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); +							if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull())  							{ -								glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); -								if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull()) +								gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); +								if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1)  								{ -									gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); -									if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) -									{ -										mTextureSet.insert(instance.mMaterial[i].mDiffuseMap); -									} +									mTextureSet.insert(instance.mMaterial[i].mDiffuseMap);  								}  							}  							buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);  							gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  							glColor3f(0.4f, 0.4f, 0.4f); -							 -							if (mFMP->childGetValue("show edges").asBoolean()) + +							if (mFMP->childGetValue("show edges").asBoolean() || model == physics_model)  							{ +								if (model == physics_model) +								{ +									glColor3f(1.f, 1.f, 0.f); +								} +  								glLineWidth(3.f);  								glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  								buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); @@ -3597,75 +3600,11 @@ BOOL LLModelPreview::render()  							}  						}  					} -					 -					if (render_hull) -					{ -						LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; -						if (decomp) -						{ -							LLMutexLock(decomp->mMutex); -							 -							std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > >::iterator iter =  -							mPhysicsMesh.find(model); -							if (iter != mPhysicsMesh.end()) -							{ -								for (U32 i = 0; i < iter->second.size(); ++i) -								{ -									if (explode > 0.f) -									{ -										gGL.pushMatrix(); -										 -										LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; -										offset *= explode; -										 -										gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); -									} -									 -									static std::vector<LLColor4U> hull_colors; -									 -									if (i+1 >= hull_colors.size()) -									{ -										hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255)); -									} -									 -									LLVertexBuffer* buff = iter->second[i]; -									if (buff) -									{ -										buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);			 -										 -										glColor4ubv(hull_colors[i].mV); -										buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); -										 -										if (mFMP->childGetValue("show edges").asBoolean()) -										{ -											glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -											glLineWidth(3.f); -											glColor4ub(hull_colors[i].mV[0]/2, hull_colors[i].mV[1]/2, hull_colors[i].mV[2]/2, 255); -											buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); -											glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -											glLineWidth(1.f); -										}	 -									} -									 -									if (explode > 0.f) -									{ -										gGL.popMatrix(); -									} -								} -							} -						}	 -						 -						//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",decomp->mHulls.size())); -						//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",decomp->mTotalPoints));				 -					} -				} -				gGL.popMatrix(); -			} +					gGL.popMatrix(); +				} -			if (physics) -			{ -				mPreviewLOD = LLModel::LOD_PHYSICS; +				gGL.setSceneBlendType(LLRender::BT_ALPHA);  			}  		}  		else @@ -3819,36 +3758,38 @@ void LLModelPreview::pan(F32 right, F32 up)  void LLModelPreview::setPreviewLOD(S32 lod)  { -	mPreviewLOD = llclamp(lod, 0, 4); -	refresh(); -} +	lod = llclamp(lod, 0, (S32) LLModel::LOD_HIGH); -//static  -void LLFloaterModelPreview::onBrowseHighLOD(void* data) -{ -	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; -	mp->loadModel(3); -} +	if (lod != mPreviewLOD) +	{ +		mPreviewLOD = lod; +		 +		LLComboBox* combo_box = mFMP->getChild<LLComboBox>("preview_lod_combo"); +		combo_box->setCurrentByIndex(mPreviewLOD); +		mFMP->childSetTextArg("lod_table_footer", "[DETAIL]", mFMP->getString(lod_name[mPreviewLOD])); +		mFMP->childSetText("lod_file", mLODFile[mPreviewLOD]); -//static  -void LLFloaterModelPreview::onBrowseMediumLOD(void* data) -{ -	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; -	mp->loadModel(2); -} +		LLColor4 highlight_color = LLUIColorTable::instance().getColor("MeshImportTableHighlightColor"); +		LLColor4 normal_color = LLUIColorTable::instance().getColor("MeshImportTableNormalColor"); -//static  -void LLFloaterModelPreview::onBrowseLowLOD(void* data) -{ -	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; -	mp->loadModel(1); +		for (S32 i = 0; i <= LLModel::LOD_HIGH; ++i) +		{ +			const LLColor4& color = (i == lod) ? highlight_color : normal_color; + +			mFMP->childSetColor(lod_status_name[i], color); +			mFMP->childSetColor(lod_label_name[i], color); +			mFMP->childSetColor(lod_triangles_name[i], color); +			mFMP->childSetColor(lod_vertices_name[i], color); +		} +	} +	refresh();  }  //static  -void LLFloaterModelPreview::onBrowseLowestLOD(void* data) +void LLFloaterModelPreview::onBrowseLOD(void* data)  {  	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; -	mp->loadModel(0); +	mp->loadModel(mp->mModelPreview->mPreviewLOD);  }  //static @@ -3856,11 +3797,6 @@ void LLFloaterModelPreview::onUpload(void* user_data)  {  	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; -	if (mp->mDecompFloater) -	{ -		mp->mDecompFloater->closeFloater(); -	} -	  	mp->mModelPreview->rebuildUploadData();  	gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale,  @@ -3877,24 +3813,17 @@ void LLFloaterModelPreview::onConsolidate(void* user_data)  }  //static  -void LLFloaterModelPreview::onScrubMaterials(void* user_data) -{ -	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; -	mp->mModelPreview->scrubMaterials(); -} - -//static  -void LLFloaterModelPreview::onDecompose(void* user_data) +void LLFloaterModelPreview::onClearMaterials(void* user_data)  {  	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; -	mp->showDecompFloater(); +	mp->mModelPreview->clearMaterials();  }  //static   void LLFloaterModelPreview::refresh(LLUICtrl* ctrl, void* user_data)  {  	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; -	mp->mModelPreview->refresh(); +	sInstance->mModelPreview->mDirty = true;  }  void LLFloaterModelPreview::updateResourceCost() diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 65d46e5891..7e9978f330 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -49,14 +49,6 @@ class domInstance_geometry;  class domNode;  class domTranslate; -class LLPhysicsDecompFloater : public LLFloater -{ -public: - -	LLPhysicsDecompFloater(LLSD& key); -	~LLPhysicsDecompFloater(); -}; -  class LLModelLoader : public LLThread  {  public: @@ -145,16 +137,12 @@ public:  	static void onMouseCaptureLostModelPreview(LLMouseHandler*);  	static void setUploadAmount(S32 amount) { sUploadAmount = amount; } -	static void onBrowseHighLOD(void* data); -	static void onBrowseMediumLOD(void* data);  -	static void onBrowseLowLOD(void* data); -	static void onBrowseLowestLOD(void* data); +	static void onBrowseLOD(void* data);  	static void onUpload(void* data);  	static void onConsolidate(void* data); -	static void onScrubMaterials(void* data); -	static void onDecompose(void* data); +	static void onClearMaterials(void* data);  	static void onModelDecompositionComplete(LLModel* model, std::vector<LLPointer<LLVertexBuffer> >& physics_mesh);  	static void refresh(LLUICtrl* ctrl, void* data); @@ -167,27 +155,16 @@ protected:  	friend class LLModelPreview;  	friend class LLMeshFilePicker;  	friend class LLPhysicsDecomp; -	friend class LLPhysicsDecompFloater; -	static void		onDebugScaleCommit(LLUICtrl*, void*); +	static void		onImportScaleCommit(LLUICtrl*, void*);  	static void		onUploadJointsCommit(LLUICtrl*,void*);  	static void		onUploadSkinCommit(LLUICtrl*,void*);  	static void		onPreviewLODCommit(LLUICtrl*,void*); -	static void		onHighLODCommit(LLUICtrl*,void*); -	static void		onMediumLODCommit(LLUICtrl*,void*); -	static void		onLowLODCommit(LLUICtrl*,void*); -	static void		onLowestLODCommit(LLUICtrl*,void*); -	static void		onPhysicsLODCommit(LLUICtrl*,void*); -	 -	static void		onHighLimitCommit(LLUICtrl*,void*); -	static void		onMediumLimitCommit(LLUICtrl*,void*); -	static void		onLowLimitCommit(LLUICtrl*,void*); -	static void		onLowestLimitCommit(LLUICtrl*,void*); -	static void		onPhysicsLimitCommit(LLUICtrl*,void*); +	static void		onTriangleLimitCommit(LLUICtrl*,void*); -	static void		onSmoothNormalsCommit(LLUICtrl*,void*); +	static void		onGenerateNormalsCommit(LLUICtrl*,void*);  	static void		onAutoFillCommit(LLUICtrl*,void*);  	static void		onShowEdgesCommit(LLUICtrl*,void*); @@ -197,20 +174,24 @@ protected:  	static void onPhysicsParamCommit(LLUICtrl* ctrl, void* userdata);  	static void onPhysicsStageExecute(LLUICtrl* ctrl, void* userdata);  	static void onPhysicsStageCancel(LLUICtrl* ctrl, void* userdata); -	static void onClosePhysicsFloater(LLUICtrl* ctrl, void* userdata); +	 +	static void onPhysicsBrowse(LLUICtrl* ctrl, void* userdata); +	static void onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata); +	static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata); +	static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata); +	static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata); +	 +	  	void			draw(); -	static void		setLODMode(S32 lod, void* userdata); -	void			setLODMode(S32 lod, S32 which_mode);  	static void		setLimit(S32 lod, void* userdata);  	void			setLimit(S32 lod, S32 limit); -	void showDecompFloater(); +	void initDecompControls();  	LLModelPreview*	mModelPreview; -	LLFloater* mDecompFloater;  	LLPhysicsDecomp::decomp_params mDecompParams;  	S32				mLastMouseX; @@ -236,6 +217,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	void setPreviewTarget(F32 distance);  	void setTexture(U32 name) { mTextureName = name; } +	void setPhysicsFromLOD(S32 lod);  	BOOL render();  	void update();  	void genBuffers(S32 lod, bool skinned); @@ -250,9 +232,9 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	void loadModel(std::string filename, S32 lod);  	void loadModelCallback(S32 lod);  	void genLODs(S32 which_lod = -1); -	void smoothNormals(); +	void generateNormals();  	void consolidate(); -	void scrubMaterials(); +	void clearMaterials();  	U32 calcResourceCost();  	void rebuildUploadData();  	void clearIncompatible(S32 lod); @@ -280,9 +262,9 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	LLVector3	mPreviewScale;  	S32			mPreviewLOD;  	U32			mResourceCost; -	S32			mLODMode[LLModel::NUM_LODS];  	S32			mLimit[LLModel::NUM_LODS]; -	 +	std::string mLODFile[LLModel::NUM_LODS]; +  	LLModelLoader* mModelLoader; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index ddd2ff196b..2a5d034789 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -778,4 +778,10 @@      <color       name="MenuBarProjectBgColor"       reference="MdBlue" /> +    <color +      name="MeshImportTableNormalColor" +      value="1 1 1 1"/> +    <color +      name="MeshImportTableHighlightColor" +      value="0.2 0.8 1 1"/>  </colors> 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 c7433af226..f1b6024ff7 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,49 +1,358 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater can_close="true" can_drag_on_left="false" can_minimize="false" -     can_resize="false" height="656" min_height="656" min_width="856" -     name="Model Preview" title="Import Model" width="856"> - -  <text bottom_delta="20" left="10" name="status" height="15" follows="top|left"> -    Status: [STATUS] -  </text> +     can_resize="true" height="520" min_height="520" min_width="630" +     name="Model Preview" title="Upload Model" width="630">    <string name="status_idle">Idle</string>    <string name="status_reading_file">Loading...</string>    <string name="status_generating_meshes">Generating Meshes...</string> -  <string name="missing_lod">Cannot upload, missing required level of detail.</string> -  <string name="bad_lod">Cannot upload, supplied levels of detail invalid.</string>" -  <string name="too_heavy">Too many vertices.</string> -  <string name="required">Required</string> -  <string name="good">Good</string> -  <string name="mesh_mismatch">Submesh count mismatch.</string> -  <string name="model_mismatch">Model count mismatch.</string> -   -  <combo_box bottom_delta="20" follows="right|top" height="18" label="Preview" -	     left="450" name="preview_lod_combo" width="120" tool_tip="LOD to view in preview render"> -    <combo_item name="preview_lowest"> +  <string name="high">High</string> +  <string name="medium">Medium</string> +  <string name="low">Low</string> +  <string name="lowest">Lowest</string> +  <string name="mesh_status_good">Good</string> +  <string name="mesh_status_bad">Bad</string>" +  <string name="mesh_status_na">N/A</string> +  <string name="mesh_status_none">None</string> +  <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" --> + +  <text left="15" bottom="25" follows="top|left" height="15" name="name_label"> +    Name: +  </text> +  <line_editor bottom_delta="20" follows="top|left|right" height="19" max_length="254" +	     name="description_form" width="310" /> +  <text bottom_delta="24" follows="top|left" height="15" name="preview_label"> +    Preview: +  </text> + +  <!-- Placeholder panel for 3D preview render --> +  <panel +    name="preview_panel" +    left="15" +    width="310" +    height="310" +    follows="all"/> + +  <text bottom_delta="25" left="15" width="100"  follows="bottom|left" height="15" name="streaming cost"> +    Prim Cost: [COST] +  </text> + +  <text right="320" width="100" height="15" bottom_delta="0" follows="bottom|right" name="status">[STATUS]</text> + +  <text bottom_delta="20" left="15" follows="left|bottom" height="15" name="lod_label"> +    Level of Detail: +  </text> +  <combo_box bottom_delta="20" follows="left|bottom" height="18" +	     name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render"> +    <combo_item name="lowest">        Lowest      </combo_item> -    <combo_item name="preview_low"> +    <combo_item name="low">        Low      </combo_item> -    <combo_item name="preview_medium"> +    <combo_item name="medium">        Medium      </combo_item> -    <combo_item name="preview_high"> +    <combo_item name="high">        High      </combo_item> -    <combo_item name="preview_high"> -      Physics -    </combo_item>    </combo_box> -  + +  <check_box bottom="450" left="125" follows="left|bottom" label="Show Edges" name="show edges" width="120" height="16" tool_tip="Render wireframe in preview window"/> +  <check_box bottom_delta="15" left="125" follows="left|bottom" label="Show Physics" name="show physics" width="120" height="16" tool_tip="Show physics shape."/> + +  <button bottom="510" follows="bottom|left" height="20" label="Upload" +	     left="15" width="80" name="ok_btn" tool_tip="Upload to simulator"/> +  <button left_pad="10" follows="left|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/> + +  <tab_container +    follows="right|top|bottom" +    top="15" +    left="330" +    height="475" +    width="280" +    name="import_tab" +    border="true" +    tab_position="top"> + +    <!-- MODIFIERS PANEL --> +    <panel +      border="true" +      label="Modifiers" +      name="modifiers_panel" +      left="330" +      width="280" +      height="450"> + +      <text left="10" width="90" bottom="30" follows="top|left" height="15"> +        Scale: +      </text> +      <text left_pad="5" width="140" follows="top|left" height="15"> +        Dimensions: +      </text> + +      <spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> + +      <text left_pad="20" height="15" name="import_dimensions" follows="top|left"> +        [X] x [Y] x [Z] m +      </text> + +      <text left="10" top_pad="20" follows="top_left" height="15"> +        Include: +      </text> + +      <check_box top_pad="5" name="upload_textures" height="15" follows="top|left" label="Textures"/> +      <check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/> +      <check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/> +    </panel> + + +    <!-- LOD PANEL --> +    <panel +      border="true" +      label="Level of Detail" +      name="lod_panel"> + +      <text left="10" width="240" bottom="20" height="15" follows="left|top" name="lod_table_header"> +        Select Level of Detail: +      </text> +      +      <text valign="center" halign="center" bg_visible="true" bottom_delta="16" left="75" width="65" height="18" follows="left|top" value="Triangles"/> +      <text valign="center" halign="center" bg_visible="true" left_pad="0" width="65" height="18" follows="left|top" value="Vertices"/> +      <text valign="center" halign="center" left_pad="0" width="65" bg_visible="true" height="18" follows="left|top" value="Status"/> +       +      <text valign="center" halign="center" bg_visible="true" name="high_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="High"/> +      <text valign="center" halign="center" bg_visible="true" name="high_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="high_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="high_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + +      <text valign="center" halign="center" bg_visible="true" name="medium_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Medium"/> +      <text valign="center" halign="center" bg_visible="true" name="medium_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="medium_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="medium_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + +      <text valign="center" halign="center" bg_visible="true" name="low_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Low"/> +      <text valign="center" halign="center" bg_visible="true" name="low_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="low_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="low_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + +      <text valign="center" halign="center" bg_visible="true" name="lowest_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Lowest"/> +      <text valign="center" halign="center" bg_visible="true" name="lowest_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="lowest_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> +      <text valign="center" halign="center" bg_visible="true" name="lowest_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + +      <text left="10" width="240" height="15" top_pad="15" follows="left|top" name="lod_tabel_footer"> +        Level of Detail: [DETAIL] +      </text> + +      <text top_pad="10" height="15" follows="left|top"> +        Mesh +      </text> + +      <radio_group follows="top|left" height="100" left="30" name="lod_file_or_limit" width="240" value="lod_from_file"> +        <radio_item bottom="85" label="Load from file" name="lod_from_file"/> +        <radio_item bottom="40" label="Auto generate" name="lod_auuto_generate"/> +      </radio_group> + +      <line_editor follows="left|top" bottom_delta="-60" width="140" left="45" value="" name="lod_file" height="20"/> +      <button bottom_delta="3" name="lod_browse" label="Browse..." left_pad="5" follows="left|top" width="70" height="25"/> + +      <text follows="top|left" top_pad="22" width="140" left="45" height="15"> +        Triangle Limit: +      </text> +      <spinner follows="top|left" name="lod_triangle_limit" top_pad="5" height="20" width="60" decimal_digits="0" enabled="true"/> + +      <button bottom_delta="3" left_pad="5" name="lod_generate" label="Generate" height="25" width="70" follows="left|top"/> + +      <text name="submeshes_info" follows="left|top" left="10" top_pad="7" height="15 width=240"> +        Layers: [SUBMESHES] +      </text> +      <button left="30" follows="top|left" top_pad="5" name="clear_materials" label="Clear Materials" width="100" height="25"/> +      <button left="30" follows="top|left" top_pad="5" name="consolidate" label="Consolidate" width="100" height="25"/> + +      <text left="10" top_pad="10" follows="top|left" width="240" height="15"> +        Normals +      </text> +      <text left="35" top_pad="5" follows="top|left" width="100" height="15"> +        Crease Angle: +      </text> +      <spinner follows="top|left" top_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/> +      <button follows="top|left" bottom_delta="3" left_pad="5" width="140" height="25" label="Generate Normals" name="generate_normals"/> +    </panel> + +    <!--  PANEL --> +    <panel +      border="true" +      label="Physics" +      name="physics_panel"> + +      <!-- PHYSICS STEP ONE--> +      <panel +        follows="top|left" +        name="physics step 1" +        left="0" +        top="0" +        width="260" +        height="450" +        visible="true"> + +        <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig"> +          Step 1: Geometry +        </text> + +        <radio_group follows="top|left" top_pad="5" width="240" height="70" name="physics_load_radio" value="physics_load_from_file"> +          <radio_item bottom="50" name="physics_load_from_file" label="Load from file"/> +          <radio_item bottom="0" name="physics_use_lod" label="Use Level of Detail"/> +        </radio_group> + +        <line_editor follows="left|top" bottom_delta="-25" width="140" left="30" value="" name="physics_file" height="20"/> +        <button bottom_delta="3" name="physics_browse" label="Browse..." left_pad="5" follows="left|top" width="70" height="25"/> + +        <combo_box left="30" bottom_delta="40" follows="left|top" height="18" +	        name="physics_lod_combo" width="90" tool_tip="LOD to use for physics shape"> +          <combo_item name="physics_lowest"> +            Lowest +          </combo_item> +          <combo_item name="physics_low"> +            Low +          </combo_item> +          <combo_item name="physics_medium"> +            Medium +          </combo_item> +          <combo_item name="physics_high"> +            High +          </combo_item> +        </combo_box> + +        <!-- +        <text follows="top|left" name="physics_triangles" top_pad="15" height="15" left="10"> +          Triangles:  [TRIANGLES] +        </text> +        <text follows="top|left" name="physics_hulls" top_pad="5" height="15"> +          Hulls:      [HULLS] +        </text> +        <text follows="top|left" name="physics_points" top_pad="5" height="15"> +          Points:     [POINTS] +        </text> + +        <text follows="top|left" left="140" width="100"  bottom_delta="-40" height="15"> +          Layer: +        </text> +        <combo_box name="physics_layer" follows="top|left" width="100" height="20" top_pad="5"/> +         --> + +        <button bottom="440" left="180" width="80" follows="bottom|right" label="Optimize" name="physics_optimize" height="20"/> +         +      </panel> + + +      <!-- PHYSICS STEP 2--> +      <panel +       follows="top|left" +       name="physics step 2" +       left="0" +       top="0" +       width="260" +       height="450" +       visible="false"> + +        <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig"> +          Step 2: Decompose +        </text> +         +        <text top_pad="100" follows="top|left" height="15"> +          Decompose Method: +        </text> +        <combo_box name="Method" follows="top|left" top_pad="5" height="20" width="100"/> +        <text top_pad="10" follows="top|left" height="15"> +          Quality: +        </text> +        <combo_box name="Decompose Quality" follows="top|left" top_pad="5" height="20" width="100"/> + +        <check_box name="Simplify Coplanar" follows="top|left" top_pad="10" height="15" label="Simplify Coplaner"/> +        <check_box name="Close Holes (Slow)" follows="top|left" top_pad="10" height="15" label="Close Holes (slow)"/> +        <slider name="Cosine%" width="240" follows="top|left" top_pad="10" height="20" label="Cosine %"/> + +        <text follows="top|left" top_pad="20" height="30" width="260"> +          "Note: Only models that have been Decomposed" +          "can be made Physical or used as Vehicles." +        </text> + +        <button bottom="440" left="90" width="80" follows="bottom|right" label="<< Back" name="decompose_back" height="20"/> +        <button left_pad="5" width="90" follows="bottom|right" label="Decompose" name="Decompose" height="20"/> +      </panel> +       + +      <!-- PHYSICS STEP 3 --> +      <panel +       follows="top|left" +       name="physics step 3" +       left="0" +       top="0" +       width="260" +       height="450" +       visible="false"> + +        <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig"> +          Step 3: Simplify +        </text> + +        <text left="10" top_pad="100" height="15" width="240" follows="top|left"> +          Simplify Method: +        </text> +         +        <combo_box top_pad="5" height="20" width="100" follows="top|left" name="Simplify Method"/> + +        <slider name="Combine Quality" label="Combine Quality:" label_width="100" width="260" follows="top|left" top_pad="10" height="20"/> +        <slider name="Detail Scale" label="Detail Scale:" label_width="100" width="260" follows="top|left" top_pad="10" height="20"/> +        <slider name="Retain%" label="Retain %:" label_width="100" width="260" follows="top|left" top_pad="10" height="20"/> +         +        <button bottom="440" left="90" width="80" follows="bottom|right" label="<< Back" name="simplify_back" height="20"/> +        <button left_pad="5" width="90" follows="bottom|right" label="Simplify" name="Simplify" height="20"/> +         +      </panel> + +      <!-- INFO PANEL --> +      <panel +        left="0" +        top="35" +        width="260" +        height="100" +        follows="left|top" +        name="physics info" +        visible="false"> + +        <text follows="top|left" name="physics_triangles" top_pad="15" height="15" left="10"> +          Triangles:  [TRIANGLES] +        </text> +        <text follows="top|left" name="physics_hulls" top_pad="5" height="15"> +          Hulls:      [HULLS] +        </text> +        <text follows="top|left" name="physics_points" top_pad="5" height="15"> +          Points:     [POINTS] +        </text> + +        <text follows="top|left" left="140" width="100"  bottom_delta="-40" height="15"> +          Layer: +        </text> +        <combo_box name="physics_layer" follows="top|left" width="100" height="20" top_pad="5"/> + +        <slider name="physics_explode" follows="top|left" top_pad="25" left="10" label="Explode" min_val="0.0" max_val="3.0" height="20" width="240"/> +      </panel> +    </panel> + +    +     +  </tab_container> +   +  <!--    <button bottom_delta="0" left="10" width="120" name="auto fill" label="Generate LOD" tool_tip="Automatically generate levels of detail"/>    <button bottom_delta="0" left="140" width="120" name="smooth normals" label="Generate Normals" tool_tip="Regenerate normals based on mesh shape"/>    <button bottom_delta="0" left="260" width="120" name="consolidate" label="Consolidate" tool_tip="Combine similar submeshes (reduces number of submeshes)"/>    <button bottom_delta="30" left="260" width="120" name="scrub materials" label="Scrub Materials" tool_tip="Remove all material information (clear textures, set all colors to white)."/>    <spinner bottom_delta="0" left="140" width="120" height="16" initial_value="75" label_width="60" name="edge threshold" decimal_digits="0" min_val="0" max_val="180" increment="5" label="Hard Angle" tool_tip="Maximum angle that will be smoothed between triangles when using Generate Normals"/> -  <check_box bottom_delta="0" left="450" label="Show Edges" name="show edges" width="120" height="16" tool_tip="Render wireframe in preview window"/> +    <text bottom_delta="30" follows="top|left" height="15" left="10" name="high_lod_label">      High LOD:    </text> @@ -163,12 +472,7 @@    <check_box bottom_delta="20" follow="bottom|left" height="20" label="Joint Positions"               left="15" width="125" name="upload_joints" tool_tip="Upload joint position information (will override avatar joint positions when mesh is worn)."/> -  <text bottom_delta="35" follows="top|left" height="15" name="description_label"> -	  Description: -	  <!-- Info: [PRIM_COST] prim equivalents, [TEXTURES] textures. --> -	</text> -	<line_editor bottom_delta="24" follows="top|left|right" height="19" max_length="254" -	     name="description_form" width="280" /> +    	<button bottom_delta="25" follows="bottom|left" height="20" label="Upload"  	     left="15" name="ok_btn" width="125" tool_tip="Upload to simulator"/> @@ -178,11 +482,10 @@    <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="upload_message">      [MESSAGE]    </text> -  <text bottom_delta="20" left="15" width="280"  follows="top|left" height="15" name="streaming cost"> -    Estimated Streaming Cost: [COST] -  </text> +      <spinner bottom_delta="20" label="Scale" left="15" width="120"  name="debug scale" decimal_digits="3" increment="0.1" min_val="0" max_val="64" initial_value="1" tool_tip="Multiplier for incoming object scale.  If incoming dimensions are very small or very large, modify this value to get dimensions into an acceptable range."/>    <text bottom_delta="30" left="15" width="280" follows="top|left" height="15" name="dimensions">      Model Dimensions: [X]m x [Y]m x [Z]m    </text> +  -->  </floater>  | 
