PageRenderTime 110ms CodeModel.GetById 20ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llfloaterimagepreview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 949 lines | 693 code | 148 blank | 108 comment | 80 complexity | b605ce28ace9f7662d03a85a3a4c10d2 MD5 | raw file
  1/** 
  2 * @file llfloaterimagepreview.cpp
  3 * @brief LLFloaterImagePreview class implementation
  4 *
  5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llfloaterimagepreview.h"
 30
 31#include "llimagebmp.h"
 32#include "llimagetga.h"
 33#include "llimagejpeg.h"
 34#include "llimagepng.h"
 35
 36#include "llagent.h"
 37#include "llbutton.h"
 38#include "llcombobox.h"
 39#include "lldrawable.h"
 40#include "lldrawpoolavatar.h"
 41#include "llrender.h"
 42#include "llface.h"
 43#include "llfocusmgr.h"
 44#include "lltextbox.h"
 45#include "lltoolmgr.h"
 46#include "llui.h"
 47#include "llviewercamera.h"
 48#include "llviewerwindow.h"
 49#include "llviewerobjectlist.h"
 50#include "llvoavatar.h"
 51#include "pipeline.h"
 52#include "lluictrlfactory.h"
 53#include "llviewershadermgr.h"
 54#include "llviewertexturelist.h"
 55#include "llstring.h"
 56
 57#include "llendianswizzle.h"
 58
 59#include "llviewercontrol.h"
 60#include "lltrans.h"
 61#include "llimagedimensionsinfo.h"
 62
 63const S32 PREVIEW_BORDER_WIDTH = 2;
 64const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
 65const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
 66const S32 PREVIEW_VPAD = -24;	// yuk, hard coded
 67const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16;
 68const S32 PREVIEW_TEXTURE_HEIGHT = 320;
 69
 70//-----------------------------------------------------------------------------
 71// LLFloaterImagePreview()
 72//-----------------------------------------------------------------------------
 73LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : 
 74	LLFloaterNameDesc(filename),
 75
 76	mAvatarPreview(NULL),
 77	mSculptedPreview(NULL),
 78	mLastMouseX(0),
 79	mLastMouseY(0),
 80	mImagep(NULL)
 81{
 82	loadImage(mFilenameAndPath);
 83}
 84
 85//-----------------------------------------------------------------------------
 86// postBuild()
 87//-----------------------------------------------------------------------------
 88BOOL LLFloaterImagePreview::postBuild()
 89{
 90	if (!LLFloaterNameDesc::postBuild())
 91	{
 92		return FALSE;
 93	}
 94	
 95	LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
 96	if (iface)
 97	{
 98		iface->selectFirstItem();
 99	}
100	childSetCommitCallback("clothing_type_combo", onPreviewTypeCommit, this);
101
102	mPreviewRect.set(PREVIEW_HPAD, 
103		PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD,
104		getRect().getWidth() - PREVIEW_HPAD, 
105		PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
106	mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
107
108	getChildView("bad_image_text")->setVisible(FALSE);
109
110	if (mRawImagep.notNull() && gAgent.getRegion() != NULL)
111	{
112		mAvatarPreview = new LLImagePreviewAvatar(256, 256);
113		mAvatarPreview->setPreviewTarget("mPelvis", "mUpperBodyMesh0", mRawImagep, 2.f, FALSE);
114
115		mSculptedPreview = new LLImagePreviewSculpted(256, 256);
116		mSculptedPreview->setPreviewTarget(mRawImagep, 2.0f);
117
118		if (mRawImagep->getWidth() * mRawImagep->getHeight () <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)
119			getChildView("lossless_check")->setEnabled(TRUE);
120	}
121	else
122	{
123		mAvatarPreview = NULL;
124		mSculptedPreview = NULL;
125		getChildView("bad_image_text")->setVisible(TRUE);
126		getChildView("clothing_type_combo")->setEnabled(FALSE);
127		getChildView("ok_btn")->setEnabled(FALSE);
128
129		if(!mImageLoadError.empty())
130		{
131			getChild<LLUICtrl>("bad_image_text")->setValue(mImageLoadError.c_str());
132		}
133	}
134	
135	getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
136	
137	return TRUE;
138}
139
140//-----------------------------------------------------------------------------
141// LLFloaterImagePreview()
142//-----------------------------------------------------------------------------
143LLFloaterImagePreview::~LLFloaterImagePreview()
144{
145	clearAllPreviewTextures();
146
147	mRawImagep = NULL;
148	mImagep = NULL ;
149}
150
151//static 
152//-----------------------------------------------------------------------------
153// onPreviewTypeCommit()
154//-----------------------------------------------------------------------------
155void	LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata)
156{
157	LLFloaterImagePreview *fp =(LLFloaterImagePreview *)userdata;
158	
159	if (!fp->mAvatarPreview || !fp->mSculptedPreview)
160	{
161		return;
162	}
163
164	S32 which_mode = 0;
165
166	LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface("clothing_type_combo");
167	if (iface)
168	{
169		which_mode = iface->getFirstSelectedIndex();
170	}
171
172	switch(which_mode)
173	{
174	case 0:
175		break;
176	case 1:
177		fp->mAvatarPreview->setPreviewTarget("mSkull", "mHairMesh0", fp->mRawImagep, 0.4f, FALSE);
178		break;
179	case 2:
180		fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, FALSE);
181		break;
182	case 3:
183		fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.0f, FALSE);
184		break;
185	case 4:
186		fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, FALSE);
187		break;
188	case 5:
189		fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, TRUE);
190		break;
191	case 6:
192		fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.2f, TRUE);
193		break;
194	case 7:
195		fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, TRUE);
196		break;
197	case 8:
198		fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mSkirtMesh0", fp->mRawImagep, 1.3f, FALSE);
199		break;
200	case 9:
201		fp->mSculptedPreview->setPreviewTarget(fp->mRawImagep, 2.0f);
202		break;
203	default:
204		break;
205	}
206	
207	fp->mAvatarPreview->refresh();
208	fp->mSculptedPreview->refresh();
209}
210
211
212//-----------------------------------------------------------------------------
213// clearAllPreviewTextures()
214//-----------------------------------------------------------------------------
215void LLFloaterImagePreview::clearAllPreviewTextures()
216{
217	if (mAvatarPreview)
218	{
219		mAvatarPreview->clearPreviewTexture("mHairMesh0");
220		mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
221		mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
222		mAvatarPreview->clearPreviewTexture("mHeadMesh0");
223		mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
224		mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
225		mAvatarPreview->clearPreviewTexture("mSkirtMesh0");
226	}
227}
228
229//-----------------------------------------------------------------------------
230// draw()
231//-----------------------------------------------------------------------------
232void LLFloaterImagePreview::draw()
233{
234	LLFloater::draw();
235	LLRect r = getRect();
236
237	if (mRawImagep.notNull())
238	{
239		LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
240		U32 selected = 0;
241		if (iface)
242			selected = iface->getFirstSelectedIndex();
243		
244		if (selected <= 0)
245		{
246			gl_rect_2d_checkerboard(mPreviewRect);
247			LLGLDisable gls_alpha(GL_ALPHA_TEST);
248
249			if(mImagep.notNull())
250			{
251				gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName());
252			}
253			else
254			{
255				mImagep = LLViewerTextureManager::getLocalTexture(mRawImagep.get(), FALSE) ;
256				
257				gGL.getTexUnit(0)->unbind(mImagep->getTarget()) ;
258				gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName());
259				stop_glerror();
260
261				gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
262				
263				gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
264				if (mAvatarPreview)
265				{
266					mAvatarPreview->setTexture(mImagep->getTexName());
267					mSculptedPreview->setTexture(mImagep->getTexName());
268				}
269			}
270
271			gGL.color3f(1.f, 1.f, 1.f);
272			gGL.begin( LLRender::QUADS );
273			{
274				gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop);
275				gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
276				gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom);
277				gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
278				gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom);
279				gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
280				gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop);
281				gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
282			}
283			gGL.end();
284
285			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
286
287			stop_glerror();
288		}
289		else
290		{
291			if ((mAvatarPreview) && (mSculptedPreview))
292			{
293				gGL.color3f(1.f, 1.f, 1.f);
294
295				if (selected == 9)
296				{
297					gGL.getTexUnit(0)->bind(mSculptedPreview);
298				}
299				else
300				{
301					gGL.getTexUnit(0)->bind(mAvatarPreview);
302				}
303
304				gGL.begin( LLRender::QUADS );
305				{
306					gGL.texCoord2f(0.f, 1.f);
307					gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
308					gGL.texCoord2f(0.f, 0.f);
309					gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
310					gGL.texCoord2f(1.f, 0.f);
311					gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
312					gGL.texCoord2f(1.f, 1.f);
313					gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
314				}
315				gGL.end();
316
317				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
318			}
319		}
320	}
321}
322
323
324//-----------------------------------------------------------------------------
325// loadImage()
326//-----------------------------------------------------------------------------
327bool LLFloaterImagePreview::loadImage(const std::string& src_filename)
328{
329	std::string exten = gDirUtilp->getExtension(src_filename);
330	U32 codec = LLImageBase::getCodecFromExtension(exten);
331
332	LLImageDimensionsInfo image_info;
333	if (!image_info.load(src_filename,codec))
334	{
335		mImageLoadError = image_info.getLastError();
336		return false;
337	}
338
339	S32 max_width = gSavedSettings.getS32("max_texture_dimension_X");
340	S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y");
341
342	if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
343	{
344		LLStringUtil::format_map_t args;
345		args["WIDTH"] = llformat("%d", max_width);
346		args["HEIGHT"] = llformat("%d", max_height);
347
348		mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args);
349		return false;
350	}
351	
352	// Load the image
353	LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
354	if (image.isNull())
355	{
356		return false;
357	}
358	if (!image->load(src_filename))
359	{
360		return false;
361	}
362	// Decompress or expand it in a raw image structure
363	LLPointer<LLImageRaw> raw_image = new LLImageRaw;
364	if (!image->decode(raw_image, 0.0f))
365	{
366		return false;
367	}
368	// Check the image constraints
369	if ((image->getComponents() != 3) && (image->getComponents() != 4))
370	{
371		image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
372		return false;
373	}
374	
375	raw_image->biasedScaleToPowerOfTwo(1024);
376	mRawImagep = raw_image;
377	
378	return true;
379}
380
381//-----------------------------------------------------------------------------
382// handleMouseDown()
383//-----------------------------------------------------------------------------
384BOOL LLFloaterImagePreview::handleMouseDown(S32 x, S32 y, MASK mask)
385{
386	if (mPreviewRect.pointInRect(x, y))
387	{
388		bringToFront( x, y );
389		gFocusMgr.setMouseCapture(this);
390		gViewerWindow->hideCursor();
391		mLastMouseX = x;
392		mLastMouseY = y;
393		return TRUE;
394	}
395
396	return LLFloater::handleMouseDown(x, y, mask);
397}
398
399//-----------------------------------------------------------------------------
400// handleMouseUp()
401//-----------------------------------------------------------------------------
402BOOL LLFloaterImagePreview::handleMouseUp(S32 x, S32 y, MASK mask)
403{
404	gFocusMgr.setMouseCapture(FALSE);
405	gViewerWindow->showCursor();
406	return LLFloater::handleMouseUp(x, y, mask);
407}
408
409//-----------------------------------------------------------------------------
410// handleHover()
411//-----------------------------------------------------------------------------
412BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask)
413{
414	MASK local_mask = mask & ~MASK_ALT;
415
416	if (mAvatarPreview && hasMouseCapture())
417	{
418		if (local_mask == MASK_PAN)
419		{
420			// pan here
421			LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
422			if (iface && iface->getFirstSelectedIndex() <= 0)
423			{
424				mPreviewImageRect.translate((F32)(x - mLastMouseX) * -0.005f * mPreviewImageRect.getWidth(), 
425					(F32)(y - mLastMouseY) * -0.005f * mPreviewImageRect.getHeight());
426			}
427			else
428			{
429				mAvatarPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
430				mSculptedPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
431			}
432		}
433		else if (local_mask == MASK_ORBIT)
434		{
435			F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
436			F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
437			
438			mAvatarPreview->rotate(yaw_radians, pitch_radians);
439			mSculptedPreview->rotate(yaw_radians, pitch_radians);
440		}
441		else 
442		{
443			LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
444			if (iface && iface->getFirstSelectedIndex() <= 0)
445			{
446				F32 zoom_amt = (F32)(y - mLastMouseY) * -0.002f;
447				mPreviewImageRect.stretch(zoom_amt);
448			}
449			else
450			{
451				F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
452				F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
453				
454				mAvatarPreview->rotate(yaw_radians, 0.f);
455				mAvatarPreview->zoom(zoom_amt);
456				mSculptedPreview->rotate(yaw_radians, 0.f);
457				mSculptedPreview->zoom(zoom_amt);
458			}
459		}
460
461		LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
462		if (iface && iface->getFirstSelectedIndex() <= 0)
463		{
464			if (mPreviewImageRect.getWidth() > 1.f)
465			{
466				mPreviewImageRect.stretch((1.f - mPreviewImageRect.getWidth()) * 0.5f);
467			}
468			else if (mPreviewImageRect.getWidth() < 0.1f)
469			{
470				mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getWidth()) * 0.5f);
471			}
472
473			if (mPreviewImageRect.getHeight() > 1.f)
474			{
475				mPreviewImageRect.stretch((1.f - mPreviewImageRect.getHeight()) * 0.5f);
476			}
477			else if (mPreviewImageRect.getHeight() < 0.1f)
478			{
479				mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getHeight()) * 0.5f);
480			}
481
482			if (mPreviewImageRect.mLeft < 0.f)
483			{
484				mPreviewImageRect.translate(-mPreviewImageRect.mLeft, 0.f);
485			}
486			else if (mPreviewImageRect.mRight > 1.f)
487			{
488				mPreviewImageRect.translate(1.f - mPreviewImageRect.mRight, 0.f);
489			}
490
491			if (mPreviewImageRect.mBottom < 0.f)
492			{
493				mPreviewImageRect.translate(0.f, -mPreviewImageRect.mBottom);
494			}
495			else if (mPreviewImageRect.mTop > 1.f)
496			{
497				mPreviewImageRect.translate(0.f, 1.f - mPreviewImageRect.mTop);
498			}
499		}
500		else
501		{
502			mAvatarPreview->refresh();
503			mSculptedPreview->refresh();
504		}
505
506		LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
507	}
508
509	if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview)
510	{
511		return LLFloater::handleHover(x, y, mask);
512	}
513	else if (local_mask == MASK_ORBIT)
514	{
515		gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
516	}
517	else if (local_mask == MASK_PAN)
518	{
519		gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
520	}
521	else
522	{
523		gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
524	}
525
526	return TRUE;
527}
528
529//-----------------------------------------------------------------------------
530// handleScrollWheel()
531//-----------------------------------------------------------------------------
532BOOL LLFloaterImagePreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
533{
534	if (mPreviewRect.pointInRect(x, y) && mAvatarPreview)
535	{
536		mAvatarPreview->zoom((F32)clicks * -0.2f);
537		mAvatarPreview->refresh();
538
539		mSculptedPreview->zoom((F32)clicks * -0.2f);
540		mSculptedPreview->refresh();
541	}
542
543	return TRUE;
544}
545
546//-----------------------------------------------------------------------------
547// onMouseCaptureLost()
548//-----------------------------------------------------------------------------
549// static
550void LLFloaterImagePreview::onMouseCaptureLostImagePreview(LLMouseHandler* handler)
551{
552	gViewerWindow->showCursor();
553}
554
555
556//-----------------------------------------------------------------------------
557// LLImagePreviewAvatar
558//-----------------------------------------------------------------------------
559LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
560{
561	mNeedsUpdate = TRUE;
562	mTargetJoint = NULL;
563	mTargetMesh = NULL;
564	mCameraDistance = 0.f;
565	mCameraYaw = 0.f;
566	mCameraPitch = 0.f;
567	mCameraZoom = 1.f;
568
569	mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion());
570	mDummyAvatar->createDrawable(&gPipeline);
571	mDummyAvatar->mIsDummy = TRUE;
572	mDummyAvatar->mSpecialRenderMode = 2;
573	mDummyAvatar->setPositionAgent(LLVector3::zero);
574	mDummyAvatar->slamPosition();
575	mDummyAvatar->updateJointLODs();
576	mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
577	// gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance());
578
579	mTextureName = 0;
580}
581
582
583LLImagePreviewAvatar::~LLImagePreviewAvatar()
584{
585	mDummyAvatar->markDead();
586}
587
588//virtual
589S8 LLImagePreviewAvatar::getType() const
590{
591	return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_AVATAR ;
592}
593
594void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) 
595{ 
596	mTargetJoint = mDummyAvatar->mRoot.findJoint(joint_name);
597	// clear out existing test mesh
598	if (mTargetMesh)
599	{
600		mTargetMesh->setTestTexture(0);
601	}
602
603	if (male)
604	{
605		mDummyAvatar->setVisualParamWeight( "male", 1.f );
606		mDummyAvatar->updateVisualParams();
607		mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
608	}
609	else
610	{
611		mDummyAvatar->setVisualParamWeight( "male", 0.f );
612		mDummyAvatar->updateVisualParams();
613		mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
614	}
615	mDummyAvatar->mRoot.setVisible(FALSE, TRUE);
616
617	mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
618	mTargetMesh->setTestTexture(mTextureName);
619	mTargetMesh->setVisible(TRUE, FALSE);
620	mCameraDistance = distance;
621	mCameraZoom = 1.f;
622	mCameraPitch = 0.f;
623	mCameraYaw = 0.f;
624	mCameraOffset.clearVec();
625}
626
627//-----------------------------------------------------------------------------
628// clearPreviewTexture()
629//-----------------------------------------------------------------------------
630void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name)
631{
632	if (mDummyAvatar)
633	{
634		LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
635		// clear out existing test mesh
636		if (mesh)
637		{
638			mesh->setTestTexture(0);
639		}
640	}
641}
642
643//-----------------------------------------------------------------------------
644// update()
645//-----------------------------------------------------------------------------
646BOOL LLImagePreviewAvatar::render()
647{
648	mNeedsUpdate = FALSE;
649	LLVOAvatar* avatarp = mDummyAvatar;
650
651	gGL.pushUIMatrix();
652	gGL.loadUIIdentity();
653
654	gGL.matrixMode(LLRender::MM_PROJECTION);
655	gGL.pushMatrix();
656	gGL.loadIdentity();
657	gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
658
659	gGL.matrixMode(LLRender::MM_MODELVIEW);
660	gGL.pushMatrix();
661	gGL.loadIdentity();
662	
663
664	LLGLSUIDefault def;
665	gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
666
667	if (LLGLSLShader::sNoFixedFunction)
668	{
669		gUIProgram.bind();
670	}
671
672	gl_rect_2d_simple( mFullWidth, mFullHeight );
673
674	gGL.matrixMode(LLRender::MM_PROJECTION);
675	gGL.popMatrix();
676
677	gGL.matrixMode(LLRender::MM_MODELVIEW);
678	gGL.popMatrix();
679
680	gGL.flush();
681	LLVector3 target_pos = mTargetJoint->getWorldPosition();
682
683	LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * 
684		LLQuaternion(mCameraYaw, LLVector3::z_axis);
685
686	LLQuaternion av_rot = avatarp->mPelvisp->getWorldRotation() * camera_rot;
687	LLViewerCamera::getInstance()->setOriginAndLookAt(
688		target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot),		// camera
689		LLVector3::z_axis,																	// up
690		target_pos + (mCameraOffset  * av_rot) );											// point of interest
691
692	stop_glerror();
693
694	LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / mFullHeight);
695	LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
696	LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
697
698	LLVertexBuffer::unbind();
699	avatarp->updateLOD();
700		
701	if (avatarp->mDrawable.notNull())
702	{
703		LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
704		// make sure alpha=0 shows avatar material color
705		LLGLDisable no_blend(GL_BLEND);
706
707		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
708		gPipeline.enableLightsPreview();
709		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
710	}
711
712	gGL.popUIMatrix();
713	gGL.color4f(1,1,1,1);
714	return TRUE;
715}
716
717//-----------------------------------------------------------------------------
718// refresh()
719//-----------------------------------------------------------------------------
720void LLImagePreviewAvatar::refresh()
721{ 
722	mNeedsUpdate = TRUE; 
723}
724
725//-----------------------------------------------------------------------------
726// rotate()
727//-----------------------------------------------------------------------------
728void LLImagePreviewAvatar::rotate(F32 yaw_radians, F32 pitch_radians)
729{
730	mCameraYaw = mCameraYaw + yaw_radians;
731
732	mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
733}
734
735//-----------------------------------------------------------------------------
736// zoom()
737//-----------------------------------------------------------------------------
738void LLImagePreviewAvatar::zoom(F32 zoom_amt)
739{
740	mCameraZoom	= llclamp(mCameraZoom + zoom_amt, 1.f, 10.f);
741}
742
743void LLImagePreviewAvatar::pan(F32 right, F32 up)
744{
745	mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f);
746	mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
747}
748
749
750//-----------------------------------------------------------------------------
751// LLImagePreviewSculpted
752//-----------------------------------------------------------------------------
753
754LLImagePreviewSculpted::LLImagePreviewSculpted(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
755{
756	mNeedsUpdate = TRUE;
757	mCameraDistance = 0.f;
758	mCameraYaw = 0.f;
759	mCameraPitch = 0.f;
760	mCameraZoom = 1.f;
761	mTextureName = 0;
762
763	LLVolumeParams volume_params;
764	volume_params.setType(LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE);
765	volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_SPHERE);
766	
767	F32 const HIGHEST_LOD = 4.0f;
768	mVolume = new LLVolume(volume_params,  HIGHEST_LOD);
769}
770
771
772LLImagePreviewSculpted::~LLImagePreviewSculpted()
773{
774}
775
776//virtual
777S8 LLImagePreviewSculpted::getType() const
778{
779	return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_SCULPTED ;
780}
781
782void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
783{ 
784	mCameraDistance = distance;
785	mCameraZoom = 1.f;
786	mCameraPitch = 0.f;
787	mCameraYaw = 0.f;
788	mCameraOffset.clearVec();
789
790	if (imagep)
791	{
792		mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0);
793	}
794
795	const LLVolumeFace &vf = mVolume->getVolumeFace(0);
796	U32 num_indices = vf.mNumIndices;
797	U32 num_vertices = vf.mNumVertices;
798
799	mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0);
800	mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
801
802	LLStrider<LLVector3> vertex_strider;
803	LLStrider<LLVector3> normal_strider;
804	LLStrider<LLVector2> tc_strider;
805	LLStrider<U16> index_strider;
806
807	mVertexBuffer->getVertexStrider(vertex_strider);
808	mVertexBuffer->getNormalStrider(normal_strider);
809	mVertexBuffer->getTexCoord0Strider(tc_strider);
810	mVertexBuffer->getIndexStrider(index_strider);
811
812	// build vertices and normals
813	LLStrider<LLVector3> pos;
814	pos = (LLVector3*) vf.mPositions; pos.setStride(16);
815	LLStrider<LLVector3> norm;
816	norm = (LLVector3*) vf.mNormals; norm.setStride(16);
817	LLStrider<LLVector2> tc;
818	tc = (LLVector2*) vf.mTexCoords; tc.setStride(8);
819
820	for (U32 i = 0; i < num_vertices; i++)
821	{
822		*(vertex_strider++) = *pos++;
823		LLVector3 normal = *norm++;
824		normal.normalize();
825		*(normal_strider++) = normal;
826		*(tc_strider++) = *tc++;
827	}
828
829	// build indices
830	for (U16 i = 0; i < num_indices; i++)
831	{
832		*(index_strider++) = vf.mIndices[i];
833	}
834}
835
836
837//-----------------------------------------------------------------------------
838// render()
839//-----------------------------------------------------------------------------
840BOOL LLImagePreviewSculpted::render()
841{
842	mNeedsUpdate = FALSE;
843	LLGLSUIDefault def;
844	LLGLDisable no_blend(GL_BLEND);
845	LLGLEnable cull(GL_CULL_FACE);
846	LLGLDepthTest depth(GL_TRUE);
847
848	gGL.matrixMode(LLRender::MM_PROJECTION);
849	gGL.pushMatrix();
850	gGL.loadIdentity();
851	gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
852
853	gGL.matrixMode(LLRender::MM_MODELVIEW);
854	gGL.pushMatrix();
855	gGL.loadIdentity();
856		
857	gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
858
859	if (LLGLSLShader::sNoFixedFunction)
860	{
861		gUIProgram.bind();
862	}
863
864	gl_rect_2d_simple( mFullWidth, mFullHeight );
865	
866	gGL.matrixMode(LLRender::MM_PROJECTION);
867	gGL.popMatrix();
868
869	gGL.matrixMode(LLRender::MM_MODELVIEW);
870	gGL.popMatrix();
871
872	glClear(GL_DEPTH_BUFFER_BIT);
873	
874	LLVector3 target_pos(0, 0, 0);
875
876	LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * 
877		LLQuaternion(mCameraYaw, LLVector3::z_axis);
878
879	LLQuaternion av_rot = camera_rot;
880	LLViewerCamera::getInstance()->setOriginAndLookAt(
881		target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot),		// camera
882		LLVector3::z_axis,																	// up
883		target_pos + (mCameraOffset  * av_rot) );											// point of interest
884
885	stop_glerror();
886
887	LLViewerCamera::getInstance()->setAspect((F32) mFullWidth / mFullHeight);
888	LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
889	LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
890
891	const LLVolumeFace &vf = mVolume->getVolumeFace(0);
892	U32 num_indices = vf.mNumIndices;
893	
894	gPipeline.enableLightsAvatar();
895
896	if (LLGLSLShader::sNoFixedFunction)
897	{
898		gObjectPreviewProgram.bind();
899	}
900	gGL.pushMatrix();
901	const F32 SCALE = 1.25f;
902	gGL.scalef(SCALE, SCALE, SCALE);
903	const F32 BRIGHTNESS = 0.9f;
904	gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS);
905
906	mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
907	mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0);
908
909	gGL.popMatrix();
910
911	if (LLGLSLShader::sNoFixedFunction)
912	{
913		gObjectPreviewProgram.unbind();
914	}
915
916	return TRUE;
917}
918
919//-----------------------------------------------------------------------------
920// refresh()
921//-----------------------------------------------------------------------------
922void LLImagePreviewSculpted::refresh()
923{ 
924	mNeedsUpdate = TRUE; 
925}
926
927//-----------------------------------------------------------------------------
928// rotate()
929//-----------------------------------------------------------------------------
930void LLImagePreviewSculpted::rotate(F32 yaw_radians, F32 pitch_radians)
931{
932	mCameraYaw = mCameraYaw + yaw_radians;
933
934	mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
935}
936
937//-----------------------------------------------------------------------------
938// zoom()
939//-----------------------------------------------------------------------------
940void LLImagePreviewSculpted::zoom(F32 zoom_amt)
941{
942	mCameraZoom	= llclamp(mCameraZoom + zoom_amt, 1.f, 10.f);
943}
944
945void LLImagePreviewSculpted::pan(F32 right, F32 up)
946{
947	mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f);
948	mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
949}