PageRenderTime 163ms CodeModel.GetById 12ms app.highlight 136ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llprimitive/llmodel.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2456 lines | 1860 code | 442 blank | 154 comment | 345 complexity | 75405adb5eb7de9bfb8475a95d1e2d9d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llmodel.cpp
   3 * @brief Model handling implementation
   4 *
   5 * $LicenseInfo:firstyear=2001&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 "linden_common.h"
  28
  29#include "llmodel.h"
  30#include "llmemory.h"
  31#include "llconvexdecomposition.h"
  32#include "llsdserialize.h"
  33#include "llvector4a.h"
  34#if LL_MSVC
  35#pragma warning (disable : 4263)
  36#pragma warning (disable : 4264)
  37#endif
  38#include "dae.h"
  39#include "dae/daeErrorHandler.h"
  40#include "dom/domConstants.h"
  41#include "dom/domMesh.h"
  42#if LL_MSVC
  43#pragma warning (default : 4263)
  44#pragma warning (default : 4264)
  45#endif
  46
  47#ifdef LL_STANDALONE
  48# include <zlib.h>
  49#else
  50# include "zlib/zlib.h"
  51#endif
  52
  53
  54
  55std::string model_names[] =
  56{
  57	"lowest_lod",
  58	"low_lod",
  59	"medium_lod",
  60	"high_lod",
  61	"physics_mesh"
  62};
  63
  64const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
  65
  66LLModel::LLModel(LLVolumeParams& params, F32 detail)
  67	: LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0)
  68	, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS)
  69{
  70	mDecompID = -1;
  71	mLocalID = -1;
  72}
  73
  74LLModel::~LLModel()
  75{
  76	if (mDecompID >= 0)
  77	{
  78		LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
  79	}
  80}
  81
  82
  83bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
  84					 domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
  85{
  86	idx_stride = 0;
  87
  88	for (U32 j = 0; j < inputs.getCount(); ++j)
  89	{
  90		idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride);
  91
  92		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
  93		{ //found vertex array
  94			const domURIFragmentType& uri = inputs[j]->getSource();
  95			daeElementRef elem = uri.getElement();
  96			domVertices* vertices = (domVertices*) elem.cast();
  97			if ( !vertices )
  98			{
  99				return false;
 100			}
 101				
 102			domInputLocal_Array& v_inp = vertices->getInput_array();
 103			
 104			
 105			for (U32 k = 0; k < v_inp.getCount(); ++k)
 106			{
 107				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
 108				{
 109					pos_offset = inputs[j]->getOffset();
 110
 111					const domURIFragmentType& uri = v_inp[k]->getSource();
 112					daeElementRef elem = uri.getElement();
 113					pos_source = (domSource*) elem.cast();
 114				}
 115				
 116				if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0)
 117				{
 118					norm_offset = inputs[j]->getOffset();
 119
 120					const domURIFragmentType& uri = v_inp[k]->getSource();
 121					daeElementRef elem = uri.getElement();
 122					norm_source = (domSource*) elem.cast();
 123				}
 124			}
 125		}
 126
 127		if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
 128		{
 129			//found normal array for this triangle list
 130			norm_offset = inputs[j]->getOffset();
 131			const domURIFragmentType& uri = inputs[j]->getSource();
 132			daeElementRef elem = uri.getElement();
 133			norm_source = (domSource*) elem.cast();
 134		}
 135		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
 136		{ //found texCoords
 137			tc_offset = inputs[j]->getOffset();
 138			const domURIFragmentType& uri = inputs[j]->getSource();
 139			daeElementRef elem = uri.getElement();
 140			tc_source = (domSource*) elem.cast();
 141		}
 142	}
 143
 144	idx_stride += 1;
 145	
 146	return true;
 147}
 148
 149LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
 150{
 151	LLVolumeFace face;
 152	std::vector<LLVolumeFace::VertexData> verts;
 153	std::vector<U16> indices;
 154	
 155	const domInputLocalOffset_Array& inputs = tri->getInput_array();
 156
 157	S32 pos_offset = -1;
 158	S32 tc_offset = -1;
 159	S32 norm_offset = -1;
 160
 161	domSource* pos_source = NULL;
 162	domSource* tc_source = NULL;
 163	domSource* norm_source = NULL;
 164
 165	S32 idx_stride = 0;
 166
 167	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
 168	{
 169		return LLModel::BAD_ELEMENT;
 170	}
 171
 172	
 173	domPRef p = tri->getP();
 174	domListOfUInts& idx = p->getValue();
 175	
 176	domListOfFloats  dummy ;
 177	domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ;
 178	domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ;
 179	domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ;
 180
 181	if (pos_source)
 182	{
 183		face.mExtents[0].set(v[0], v[1], v[2]);
 184		face.mExtents[1].set(v[0], v[1], v[2]);
 185	}
 186	
 187	LLVolumeFace::VertexMapData::PointMap point_map;
 188	
 189	for (U32 i = 0; i < idx.getCount(); i += idx_stride)
 190	{
 191		LLVolumeFace::VertexData cv;
 192		if (pos_source)
 193		{
 194			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
 195								v[idx[i+pos_offset]*3+1],
 196								v[idx[i+pos_offset]*3+2]));
 197		}
 198
 199		if (tc_source)
 200		{
 201			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
 202								tc[idx[i+tc_offset]*2+1]);
 203		}
 204		
 205		if (norm_source)
 206		{
 207			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
 208								n[idx[i+norm_offset]*3+1],
 209								n[idx[i+norm_offset]*3+2]));
 210		}
 211		
 212		BOOL found = FALSE;
 213			
 214		LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
 215		point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
 216		
 217		if (point_iter != point_map.end())
 218		{
 219			for (U32 j = 0; j < point_iter->second.size(); ++j)
 220			{
 221				if ((point_iter->second)[j] == cv)
 222				{
 223					found = TRUE;
 224					indices.push_back((point_iter->second)[j].mIndex);
 225					break;
 226				}
 227			}
 228		}
 229
 230		if (!found)
 231		{
 232			update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
 233			verts.push_back(cv);
 234			if (verts.size() >= 65535)
 235			{
 236				//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl;
 237				return LLModel::VERTEX_NUMBER_OVERFLOW ;
 238			}
 239			U16 index = (U16) (verts.size()-1);
 240			indices.push_back(index);
 241
 242			LLVolumeFace::VertexMapData d;
 243			d.setPosition(cv.getPosition());
 244			d.mTexCoord = cv.mTexCoord;
 245			d.setNormal(cv.getNormal());
 246			d.mIndex = index;
 247			if (point_iter != point_map.end())
 248			{
 249				point_iter->second.push_back(d);
 250			}
 251			else
 252			{
 253				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
 254			}
 255		}
 256
 257		if (indices.size()%3 == 0 && verts.size() >= 65532)
 258		{
 259			face_list.push_back(face);
 260			face_list.rbegin()->fillFromLegacyData(verts, indices);
 261			LLVolumeFace& new_face = *face_list.rbegin();
 262			if (!norm_source)
 263			{
 264				ll_aligned_free_16(new_face.mNormals);
 265				new_face.mNormals = NULL;
 266			}
 267
 268			if (!tc_source)
 269			{
 270				ll_aligned_free_16(new_face.mTexCoords);
 271				new_face.mTexCoords = NULL;
 272			}
 273
 274			face = LLVolumeFace();
 275			point_map.clear();
 276		}
 277	}
 278
 279	if (!verts.empty())
 280	{
 281		std::string material;
 282
 283		if (tri->getMaterial())
 284		{
 285			material = std::string(tri->getMaterial());
 286		}
 287		
 288		materials.push_back(material);
 289		face_list.push_back(face);
 290
 291		face_list.rbegin()->fillFromLegacyData(verts, indices);
 292		LLVolumeFace& new_face = *face_list.rbegin();
 293		if (!norm_source)
 294		{
 295			ll_aligned_free_16(new_face.mNormals);
 296			new_face.mNormals = NULL;
 297		}
 298
 299		if (!tc_source)
 300		{
 301			ll_aligned_free_16(new_face.mTexCoords);
 302			new_face.mTexCoords = NULL;
 303		}
 304	}
 305
 306	return LLModel::NO_ERRORS ;
 307}
 308
 309LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly)
 310{
 311	domPRef p = poly->getP();
 312	domListOfUInts& idx = p->getValue();
 313
 314	if (idx.getCount() == 0)
 315	{
 316		return LLModel::NO_ERRORS ;
 317	}
 318
 319	const domInputLocalOffset_Array& inputs = poly->getInput_array();
 320
 321
 322	domListOfUInts& vcount = poly->getVcount()->getValue();
 323	
 324	S32 pos_offset = -1;
 325	S32 tc_offset = -1;
 326	S32 norm_offset = -1;
 327
 328	domSource* pos_source = NULL;
 329	domSource* tc_source = NULL;
 330	domSource* norm_source = NULL;
 331
 332	S32 idx_stride = 0;
 333
 334	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
 335	{
 336		return LLModel::BAD_ELEMENT;
 337	}
 338
 339	LLVolumeFace face;
 340
 341	std::vector<U16> indices;
 342	std::vector<LLVolumeFace::VertexData> verts;
 343
 344	domListOfFloats v;
 345	domListOfFloats tc;
 346	domListOfFloats n;
 347
 348	if (pos_source)
 349	{
 350		v = pos_source->getFloat_array()->getValue();
 351		face.mExtents[0].set(v[0], v[1], v[2]);
 352		face.mExtents[1].set(v[0], v[1], v[2]);
 353	}
 354
 355	if (tc_source)
 356	{
 357		tc = tc_source->getFloat_array()->getValue();
 358	}
 359
 360	if (norm_source)
 361	{
 362		n = norm_source->getFloat_array()->getValue();
 363	}
 364	
 365	LLVolumeFace::VertexMapData::PointMap point_map;
 366
 367	U32 cur_idx = 0;
 368	for (U32 i = 0; i < vcount.getCount(); ++i)
 369	{ //for each polygon
 370		U32 first_index = 0;
 371		U32 last_index = 0;
 372		for (U32 j = 0; j < vcount[i]; ++j)
 373		{ //for each vertex
 374
 375			LLVolumeFace::VertexData cv;
 376
 377			if (pos_source)
 378			{
 379				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
 380									v[idx[cur_idx+pos_offset]*3+1],
 381									v[idx[cur_idx+pos_offset]*3+2]);
 382			}
 383
 384			if (tc_source)
 385			{
 386				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
 387									tc[idx[cur_idx+tc_offset]*2+1]);
 388			}
 389			
 390			if (norm_source)
 391			{
 392				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
 393									n[idx[cur_idx+norm_offset]*3+1],
 394									n[idx[cur_idx+norm_offset]*3+2]);
 395			}
 396			
 397			cur_idx += idx_stride;
 398			
 399			BOOL found = FALSE;
 400				
 401			LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
 402			LLVector3 pos3(cv.getPosition().getF32ptr());
 403			point_iter = point_map.find(pos3);
 404			
 405			if (point_iter != point_map.end())
 406			{
 407				for (U32 k = 0; k < point_iter->second.size(); ++k)
 408				{
 409					if ((point_iter->second)[k] == cv)
 410					{
 411						found = TRUE;
 412						U32 index = (point_iter->second)[k].mIndex;
 413						if (j == 0)
 414						{
 415							first_index = index;
 416						}
 417						else if (j == 1)
 418						{
 419							last_index = index;
 420						}
 421						else
 422						{
 423							indices.push_back(first_index);
 424							indices.push_back(last_index);
 425							indices.push_back(index);
 426							last_index = index;
 427						}
 428
 429						break;
 430					}
 431				}
 432			}
 433
 434			if (!found)
 435			{
 436				update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
 437				verts.push_back(cv);
 438				if (verts.size() >= 65535)
 439				{
 440					//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl;
 441					return LLModel::VERTEX_NUMBER_OVERFLOW ;
 442				}
 443				U16 index = (U16) (verts.size()-1);
 444			
 445				if (j == 0)
 446				{
 447					first_index = index;
 448				}
 449				else if (j == 1)
 450				{
 451					last_index = index;
 452				}
 453				else
 454				{
 455					indices.push_back(first_index);
 456					indices.push_back(last_index);
 457					indices.push_back(index);
 458					last_index = index;
 459				}	
 460
 461				LLVolumeFace::VertexMapData d;
 462				d.setPosition(cv.getPosition());
 463				d.mTexCoord = cv.mTexCoord;
 464				d.setNormal(cv.getNormal());
 465				d.mIndex = index;
 466				if (point_iter != point_map.end())
 467				{
 468					point_iter->second.push_back(d);
 469				}
 470				else
 471				{
 472					point_map[pos3].push_back(d);
 473				}
 474			}
 475
 476			if (indices.size()%3 == 0 && indices.size() >= 65532)
 477			{
 478				face_list.push_back(face);
 479				face_list.rbegin()->fillFromLegacyData(verts, indices);
 480				LLVolumeFace& new_face = *face_list.rbegin();
 481				if (!norm_source)
 482				{
 483					ll_aligned_free_16(new_face.mNormals);
 484					new_face.mNormals = NULL;
 485				}
 486
 487				if (!tc_source)
 488				{
 489					ll_aligned_free_16(new_face.mTexCoords);
 490					new_face.mTexCoords = NULL;
 491				}
 492
 493				face = LLVolumeFace();
 494				verts.clear();
 495				indices.clear();
 496				point_map.clear();
 497			}
 498		}
 499	}
 500
 501	if (!verts.empty())
 502	{
 503		std::string material;
 504
 505		if (poly->getMaterial())
 506		{
 507			material = std::string(poly->getMaterial());
 508		}
 509	
 510		materials.push_back(material);
 511		face_list.push_back(face);
 512		face_list.rbegin()->fillFromLegacyData(verts, indices);
 513
 514		LLVolumeFace& new_face = *face_list.rbegin();
 515		if (!norm_source)
 516		{
 517			ll_aligned_free_16(new_face.mNormals);
 518			new_face.mNormals = NULL;
 519		}
 520
 521		if (!tc_source)
 522		{
 523			ll_aligned_free_16(new_face.mTexCoords);
 524			new_face.mTexCoords = NULL;
 525		}
 526	}
 527
 528	return LLModel::NO_ERRORS ;
 529}
 530
 531LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly)
 532{
 533	LLVolumeFace face;
 534	std::vector<U16> indices;
 535	std::vector<LLVolumeFace::VertexData> verts;
 536
 537	const domInputLocalOffset_Array& inputs = poly->getInput_array();
 538
 539	S32 v_offset = -1;
 540	S32 n_offset = -1;
 541	S32 t_offset = -1;
 542
 543	domListOfFloats* v = NULL;
 544	domListOfFloats* n = NULL;
 545	domListOfFloats* t = NULL;
 546	
 547	U32 stride = 0;
 548	for (U32 i = 0; i < inputs.getCount(); ++i)
 549	{
 550		stride = llmax((U32) inputs[i]->getOffset()+1, stride);
 551
 552		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0)
 553		{ //found vertex array
 554			v_offset = inputs[i]->getOffset();
 555
 556			const domURIFragmentType& uri = inputs[i]->getSource();
 557			daeElementRef elem = uri.getElement();
 558			domVertices* vertices = (domVertices*) elem.cast();
 559			if (!vertices)
 560			{
 561				return LLModel::BAD_ELEMENT;
 562			}
 563			domInputLocal_Array& v_inp = vertices->getInput_array();
 564
 565			for (U32 k = 0; k < v_inp.getCount(); ++k)
 566			{
 567				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
 568				{
 569					const domURIFragmentType& uri = v_inp[k]->getSource();
 570					daeElementRef elem = uri.getElement();
 571					domSource* src = (domSource*) elem.cast();
 572					if (!src)
 573					{
 574						return LLModel::BAD_ELEMENT;
 575					}
 576					v = &(src->getFloat_array()->getValue());
 577				}
 578			}
 579		}
 580		else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0)
 581		{
 582			n_offset = inputs[i]->getOffset();
 583			//found normal array for this triangle list
 584			const domURIFragmentType& uri = inputs[i]->getSource();
 585			daeElementRef elem = uri.getElement();
 586			domSource* src = (domSource*) elem.cast();
 587			if (!src)
 588			{
 589				return LLModel::BAD_ELEMENT;
 590			}
 591			n = &(src->getFloat_array()->getValue());
 592		}
 593		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
 594		{ //found texCoords
 595			t_offset = inputs[i]->getOffset();
 596			const domURIFragmentType& uri = inputs[i]->getSource();
 597			daeElementRef elem = uri.getElement();
 598			domSource* src = (domSource*) elem.cast();
 599			if (!src)
 600			{
 601				return LLModel::BAD_ELEMENT;
 602			}
 603			t = &(src->getFloat_array()->getValue());
 604		}
 605	}
 606
 607	domP_Array& ps = poly->getP_array();
 608
 609	//make a triangle list in <verts>
 610	for (U32 i = 0; i < ps.getCount(); ++i)
 611	{ //for each polygon
 612		domListOfUInts& idx = ps[i]->getValue();
 613		for (U32 j = 0; j < idx.getCount()/stride; ++j)
 614		{ //for each vertex
 615			if (j > 2)
 616			{
 617				U32 size = verts.size();
 618				LLVolumeFace::VertexData v0 = verts[size-3];
 619				LLVolumeFace::VertexData v1 = verts[size-1];
 620
 621				verts.push_back(v0);
 622				verts.push_back(v1);
 623			}
 624
 625			LLVolumeFace::VertexData vert;
 626
 627
 628			if (v)
 629			{
 630				U32 v_idx = idx[j*stride+v_offset]*3;
 631				vert.getPosition().set(v->get(v_idx),
 632								v->get(v_idx+1),
 633								v->get(v_idx+2));
 634			}
 635			
 636			if (n)
 637			{
 638				U32 n_idx = idx[j*stride+n_offset]*3;
 639				vert.getNormal().set(n->get(n_idx),
 640								n->get(n_idx+1),
 641								n->get(n_idx+2));
 642			}
 643			
 644			if (t)
 645			{
 646				U32 t_idx = idx[j*stride+t_offset]*2;
 647				vert.mTexCoord.setVec(t->get(t_idx),
 648								t->get(t_idx+1));								
 649			}
 650						
 651			verts.push_back(vert);
 652		}
 653	}
 654
 655	if (verts.empty())
 656	{
 657		return LLModel::NO_ERRORS;
 658	}
 659
 660	face.mExtents[0] = verts[0].getPosition();
 661	face.mExtents[1] = verts[0].getPosition();
 662	
 663	//create a map of unique vertices to indices
 664	std::map<LLVolumeFace::VertexData, U32> vert_idx;
 665
 666	U32 cur_idx = 0;
 667	for (U32 i = 0; i < verts.size(); ++i)
 668	{
 669		std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]);
 670		if (iter == vert_idx.end())
 671		{
 672			vert_idx[verts[i]] = cur_idx++;
 673		}
 674	}
 675
 676	//build vertex array from map
 677	std::vector<LLVolumeFace::VertexData> new_verts;
 678	new_verts.resize(vert_idx.size());
 679
 680	for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter)
 681	{
 682		new_verts[iter->second] = iter->first;
 683		update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition());
 684	}
 685
 686	//build index array from map
 687	indices.resize(verts.size());
 688
 689	for (U32 i = 0; i < verts.size(); ++i)
 690	{
 691		indices[i] = vert_idx[verts[i]];
 692	}
 693
 694	// DEBUG just build an expanded triangle list
 695	/*for (U32 i = 0; i < verts.size(); ++i)
 696	{
 697		indices.push_back((U16) i);
 698		update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition());
 699	}*/
 700
 701    if (!new_verts.empty())
 702	{
 703		std::string material;
 704
 705		if (poly->getMaterial())
 706		{
 707			material = std::string(poly->getMaterial());
 708		}
 709
 710		materials.push_back(material);
 711		face_list.push_back(face);
 712		face_list.rbegin()->fillFromLegacyData(new_verts, indices);
 713
 714		LLVolumeFace& new_face = *face_list.rbegin();
 715		if (!n)
 716		{
 717			ll_aligned_free_16(new_face.mNormals);
 718			new_face.mNormals = NULL;
 719		}
 720
 721		if (!t)
 722		{
 723			ll_aligned_free_16(new_face.mTexCoords);
 724			new_face.mTexCoords = NULL;
 725		}
 726	}
 727
 728	return LLModel::NO_ERRORS ;
 729}
 730
 731//static
 732std::string LLModel::getStatusString(U32 status)
 733{
 734	const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"};
 735
 736	if(status < INVALID_STATUS)
 737	{
 738		if(status_strings[status] == std::string())
 739		{
 740			llerrs << "No valid status string for this status: " << (U32)status << llendl ;
 741		}
 742		return status_strings[status] ;
 743	}
 744
 745	llerrs << "Invalid model status: " << (U32)status << llendl ;
 746
 747	return std::string() ;
 748}
 749
 750void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
 751{
 752	domTriangles_Array& tris = mesh->getTriangles_array();
 753		
 754	for (U32 i = 0; i < tris.getCount(); ++i)
 755	{
 756		domTrianglesRef& tri = tris.get(i);
 757
 758		mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri);
 759		
 760		if(mStatus != NO_ERRORS)
 761		{
 762			mVolumeFaces.clear() ;
 763			mMaterialList.clear() ;
 764			return ; //abort
 765		}
 766	}
 767
 768	domPolylist_Array& polys = mesh->getPolylist_array();
 769	for (U32 i = 0; i < polys.getCount(); ++i)
 770	{
 771		domPolylistRef& poly = polys.get(i);
 772		mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
 773
 774		if(mStatus != NO_ERRORS)
 775		{
 776			mVolumeFaces.clear() ;
 777			mMaterialList.clear() ;
 778			return ; //abort
 779		}
 780	}
 781	
 782	domPolygons_Array& polygons = mesh->getPolygons_array();
 783	
 784	for (U32 i = 0; i < polygons.getCount(); ++i)
 785	{
 786		domPolygonsRef& poly = polygons.get(i);
 787		mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
 788
 789		if(mStatus != NO_ERRORS)
 790		{
 791			mVolumeFaces.clear() ;
 792			mMaterialList.clear() ;
 793			return ; //abort
 794		}
 795	}
 796 
 797}
 798
 799BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
 800{
 801	if (mesh)
 802	{
 803		mVolumeFaces.clear();
 804		mMaterialList.clear();
 805
 806		addVolumeFacesFromDomMesh(mesh);
 807		
 808		if (getNumVolumeFaces() > 0)
 809		{
 810			normalizeVolumeFaces();
 811			optimizeVolumeFaces();
 812			
 813			if (getNumVolumeFaces() > 0)
 814			{
 815				return TRUE;
 816			}
 817		}
 818	}
 819	else
 820	{	
 821		llwarns << "no mesh found" << llendl;
 822	}
 823	
 824	return FALSE;
 825}
 826
 827void LLModel::offsetMesh( const LLVector3& pivotPoint )
 828{
 829	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
 830	
 831	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )
 832	{
 833		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++;
 834		LLVolumeFace& face = *currentFaceIt;
 835		LLVector4a *pos = (LLVector4a*) face.mPositions;
 836		
 837		for (U32 i=0; i<face.mNumVertices; ++i )
 838		{
 839			pos[i].add( pivot );
 840		}
 841	}
 842}
 843
 844void LLModel::optimizeVolumeFaces()
 845{
 846	for (U32 i = 0; i < getNumVolumeFaces(); ++i)
 847	{
 848		mVolumeFaces[i].optimize();
 849	}
 850}
 851
 852// Shrink the model to fit
 853// on a 1x1x1 cube centered at the origin.
 854// The positions and extents
 855// multiplied by  mNormalizedScale
 856// and offset by mNormalizedTranslation
 857// to be the "original" extents and position.
 858// Also, the positions will fit
 859// within the unit cube.
 860void LLModel::normalizeVolumeFaces()
 861{
 862
 863	// ensure we don't have too many faces
 864	if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES)
 865		mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES);
 866	
 867	if (!mVolumeFaces.empty())
 868	{
 869		LLVector4a min, max;
 870		
 871		// For all of the volume faces
 872		// in the model, loop over
 873		// them and see what the extents
 874		// of the volume along each axis.
 875		min = mVolumeFaces[0].mExtents[0];
 876		max = mVolumeFaces[0].mExtents[1];
 877
 878		for (U32 i = 1; i < mVolumeFaces.size(); ++i)
 879		{
 880			LLVolumeFace& face = mVolumeFaces[i];
 881
 882			update_min_max(min, max, face.mExtents[0]);
 883			update_min_max(min, max, face.mExtents[1]);
 884
 885			if (face.mTexCoords)
 886			{
 887				LLVector2& min_tc = face.mTexCoordExtents[0];
 888				LLVector2& max_tc = face.mTexCoordExtents[1];
 889
 890				min_tc = face.mTexCoords[0];
 891				max_tc = face.mTexCoords[0];
 892
 893				for (U32 j = 1; j < face.mNumVertices; ++j)
 894				{
 895					update_min_max(min_tc, max_tc, face.mTexCoords[j]);
 896				}
 897			}
 898			else
 899			{
 900				face.mTexCoordExtents[0].set(0,0);
 901				face.mTexCoordExtents[1].set(1,1);
 902			}
 903		}
 904
 905		// Now that we have the extents of the model
 906		// we can compute the offset needed to center
 907		// the model at the origin.
 908
 909		// Compute center of the model
 910		// and make it negative to get translation
 911		// needed to center at origin.
 912		LLVector4a trans;
 913		trans.setAdd(min, max);
 914		trans.mul(-0.5f);
 915
 916		// Compute the total size along all
 917		// axes of the model.
 918		LLVector4a size;
 919		size.setSub(max, min);
 920
 921		// Prevent division by zero.
 922		F32 x = size[0];
 923		F32 y = size[1];
 924		F32 z = size[2];
 925		F32 w = size[3];
 926		if (fabs(x)<F_APPROXIMATELY_ZERO)
 927		{
 928			x = 1.0;
 929		}
 930		if (fabs(y)<F_APPROXIMATELY_ZERO)
 931		{
 932			y = 1.0;
 933		}
 934		if (fabs(z)<F_APPROXIMATELY_ZERO)
 935		{
 936			z = 1.0;
 937		}
 938		size.set(x,y,z,w);
 939
 940		// Compute scale as reciprocal of size
 941		LLVector4a scale;
 942		scale.splat(1.f);
 943		scale.div(size);
 944
 945		LLVector4a inv_scale(1.f);
 946		inv_scale.div(scale);
 947
 948		for (U32 i = 0; i < mVolumeFaces.size(); ++i)
 949		{
 950			LLVolumeFace& face = mVolumeFaces[i];
 951
 952			// We shrink the extents so
 953			// that they fall within
 954			// the unit cube.
 955			face.mExtents[0].add(trans);
 956			face.mExtents[0].mul(scale);
 957
 958			face.mExtents[1].add(trans);
 959			face.mExtents[1].mul(scale);
 960
 961			// For all the positions, we scale
 962			// the positions to fit within the unit cube.
 963			LLVector4a* pos = (LLVector4a*) face.mPositions;
 964			LLVector4a* norm = (LLVector4a*) face.mNormals;
 965
 966			for (U32 j = 0; j < face.mNumVertices; ++j)
 967			{
 968			 	pos[j].add(trans);
 969				pos[j].mul(scale);
 970				if (norm && !norm[j].equals3(LLVector4a::getZero()))
 971				{
 972					norm[j].mul(inv_scale);
 973					norm[j].normalize3();
 974				}
 975			}
 976		}
 977
 978		// mNormalizedScale is the scale at which
 979		// we would need to multiply the model
 980		// by to get the original size of the
 981		// model instead of the normalized size.
 982		LLVector4a normalized_scale;
 983		normalized_scale.splat(1.f);
 984		normalized_scale.div(scale);
 985		mNormalizedScale.set(normalized_scale.getF32ptr());
 986		mNormalizedTranslation.set(trans.getF32ptr());
 987		mNormalizedTranslation *= -1.f; 
 988	}
 989}
 990
 991void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out)
 992{
 993	scale_out = mNormalizedScale;
 994	translation_out = mNormalizedTranslation;
 995}
 996
 997void LLModel::setNumVolumeFaces(S32 count)
 998{
 999	mVolumeFaces.resize(count);
1000}
1001
1002void LLModel::setVolumeFaceData(
1003	S32 f, 
1004	LLStrider<LLVector3> pos, 
1005	LLStrider<LLVector3> norm, 
1006	LLStrider<LLVector2> tc, 
1007	LLStrider<U16> ind, 
1008	U32 num_verts, 
1009	U32 num_indices)
1010{
1011	LLVolumeFace& face = mVolumeFaces[f];
1012
1013	face.resizeVertices(num_verts);
1014	face.resizeIndices(num_indices);
1015
1016	LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
1017	if (norm.get())
1018	{
1019		LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
1020	}
1021	else
1022	{
1023		ll_aligned_free_16(face.mNormals);
1024		face.mNormals = NULL;
1025	}
1026
1027	if (tc.get())
1028	{
1029		LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
1030	}
1031	else
1032	{
1033		ll_aligned_free_16(face.mTexCoords);
1034		face.mTexCoords = NULL;
1035	}
1036
1037	U32 size = (num_indices*2+0xF)&~0xF;
1038	LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
1039}
1040
1041void LLModel::appendFaces(LLModel *model, LLMatrix4 &transform, LLMatrix4& norm_mat)
1042{
1043	if (mVolumeFaces.empty())
1044	{
1045		setNumVolumeFaces(1);
1046	}
1047
1048	LLVolumeFace& face = mVolumeFaces[mVolumeFaces.size()-1];
1049
1050
1051	for (S32 i = 0; i < model->getNumFaces(); ++i)
1052	{
1053		face.appendFace(model->getVolumeFace(i), transform, norm_mat);
1054	}
1055
1056}
1057
1058void LLModel::appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat)
1059{
1060	S32 rindex = getNumVolumeFaces()-1; 
1061	if (rindex == -1 || 
1062		mVolumeFaces[rindex].mNumVertices + src_face.mNumVertices >= 65536)
1063	{ //empty or overflow will occur, append new face
1064		LLVolumeFace cur_face;
1065		cur_face.appendFace(src_face, mat, norm_mat);
1066		addFace(cur_face);
1067		mMaterialList.push_back(src_material);
1068	}
1069	else
1070	{ //append to existing end face
1071		mVolumeFaces.rbegin()->appendFace(src_face, mat, norm_mat);
1072	}
1073}
1074
1075void LLModel::addFace(const LLVolumeFace& face)
1076{
1077	if (face.mNumVertices == 0)
1078	{
1079		llerrs << "Cannot add empty face." << llendl;
1080	}
1081
1082	mVolumeFaces.push_back(face);
1083
1084	if (mVolumeFaces.size() > MAX_MODEL_FACES)
1085	{
1086		llerrs << "Model prims cannot have more than " << MAX_MODEL_FACES << " faces!" << llendl;
1087	}
1088}
1089
1090
1091void LLModel::generateNormals(F32 angle_cutoff)
1092{
1093	//generate normals for all faces by:
1094	// 1 - Create faceted copy of face with no texture coordinates
1095	// 2 - Weld vertices in faceted copy that are shared between triangles with less than "angle_cutoff" difference between normals
1096	// 3 - Generate smoothed set of normals based on welding results
1097	// 4 - Create faceted copy of face with texture coordinates
1098	// 5 - Copy smoothed normals to faceted copy, using closest normal to triangle normal where more than one normal exists for a given position
1099	// 6 - Remove redundant vertices from new faceted (now smooth) copy
1100
1101	angle_cutoff = cosf(angle_cutoff);
1102	for (U32 j = 0; j < mVolumeFaces.size(); ++j)
1103	{
1104		LLVolumeFace& vol_face = mVolumeFaces[j];
1105
1106		if (vol_face.mNumIndices > 65535)
1107		{
1108			llwarns << "Too many vertices for normal generation to work." << llendl;
1109			continue;
1110		}
1111
1112		//create faceted copy of current face with no texture coordinates (step 1)
1113		LLVolumeFace faceted;
1114
1115		LLVector4a* src_pos = (LLVector4a*) vol_face.mPositions;
1116		//LLVector4a* src_norm = (LLVector4a*) vol_face.mNormals;
1117
1118
1119		faceted.resizeVertices(vol_face.mNumIndices);
1120		faceted.resizeIndices(vol_face.mNumIndices);
1121		//bake out triangles into temporary face, clearing texture coordinates
1122		for (U32 i = 0; i < vol_face.mNumIndices; ++i)
1123		{
1124			U32 idx = vol_face.mIndices[i];
1125		
1126			faceted.mPositions[i] = src_pos[idx];
1127			faceted.mTexCoords[i] = LLVector2(0,0);
1128			faceted.mIndices[i] = i;
1129		}
1130
1131		//generate normals for temporary face
1132		for (U32 i = 0; i < faceted.mNumIndices; i += 3)
1133		{ //for each triangle
1134			U16 i0 = faceted.mIndices[i+0];
1135			U16 i1 = faceted.mIndices[i+1];
1136			U16 i2 = faceted.mIndices[i+2];
1137			
1138			LLVector4a& p0 = faceted.mPositions[i0];
1139			LLVector4a& p1 = faceted.mPositions[i1];
1140			LLVector4a& p2 = faceted.mPositions[i2];
1141
1142			LLVector4a& n0 = faceted.mNormals[i0];
1143			LLVector4a& n1 = faceted.mNormals[i1];
1144			LLVector4a& n2 = faceted.mNormals[i2];
1145
1146			LLVector4a lhs, rhs;
1147			lhs.setSub(p1, p0);
1148			rhs.setSub(p2, p0);
1149
1150			n0.setCross3(lhs, rhs);
1151			n0.normalize3();
1152			n1 = n0;
1153			n2 = n0;
1154		}
1155
1156		//weld vertices in temporary face, respecting angle_cutoff (step 2)
1157		faceted.optimize(angle_cutoff);
1158
1159		//generate normals for welded face based on new topology (step 3)
1160
1161		for (U32 i = 0; i < faceted.mNumVertices; i++)
1162		{
1163			faceted.mNormals[i].clear();
1164		}
1165
1166		for (U32 i = 0; i < faceted.mNumIndices; i += 3)
1167		{ //for each triangle
1168			U16 i0 = faceted.mIndices[i+0];
1169			U16 i1 = faceted.mIndices[i+1];
1170			U16 i2 = faceted.mIndices[i+2];
1171			
1172			LLVector4a& p0 = faceted.mPositions[i0];
1173			LLVector4a& p1 = faceted.mPositions[i1];
1174			LLVector4a& p2 = faceted.mPositions[i2];
1175
1176			LLVector4a& n0 = faceted.mNormals[i0];
1177			LLVector4a& n1 = faceted.mNormals[i1];
1178			LLVector4a& n2 = faceted.mNormals[i2];
1179
1180			LLVector4a lhs, rhs;
1181			lhs.setSub(p1, p0);
1182			rhs.setSub(p2, p0);
1183
1184			LLVector4a n;
1185			n.setCross3(lhs, rhs);
1186
1187			n0.add(n);
1188			n1.add(n);
1189			n2.add(n);
1190		}
1191
1192		//normalize normals and build point map
1193		LLVolumeFace::VertexMapData::PointMap point_map;
1194
1195		for (U32 i = 0; i < faceted.mNumVertices; ++i)
1196		{
1197			faceted.mNormals[i].normalize3();
1198
1199			LLVolumeFace::VertexMapData v;
1200			v.setPosition(faceted.mPositions[i]);
1201			v.setNormal(faceted.mNormals[i]);
1202
1203			point_map[LLVector3(v.getPosition().getF32ptr())].push_back(v);
1204		}
1205
1206		//create faceted copy of current face with texture coordinates (step 4)
1207		LLVolumeFace new_face;
1208
1209		//bake out triangles into new face
1210		new_face.resizeIndices(vol_face.mNumIndices);
1211		new_face.resizeVertices(vol_face.mNumIndices);
1212		
1213		for (U32 i = 0; i < vol_face.mNumIndices; ++i)
1214		{
1215			U32 idx = vol_face.mIndices[i];
1216			LLVolumeFace::VertexData v;
1217			new_face.mPositions[i] = vol_face.mPositions[idx];
1218			new_face.mNormals[i].clear();
1219			new_face.mIndices[i] = i;
1220		}
1221
1222		if (vol_face.mTexCoords)
1223		{
1224			for (U32 i = 0; i < vol_face.mNumIndices; i++)
1225			{
1226				U32 idx = vol_face.mIndices[i];
1227				new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
1228			}
1229		}
1230		else
1231		{
1232			ll_aligned_free_16(new_face.mTexCoords);
1233			new_face.mTexCoords = NULL;
1234		}
1235
1236		//generate normals for new face
1237		for (U32 i = 0; i < new_face.mNumIndices; i += 3)
1238		{ //for each triangle
1239			U16 i0 = new_face.mIndices[i+0];
1240			U16 i1 = new_face.mIndices[i+1];
1241			U16 i2 = new_face.mIndices[i+2];
1242			
1243			LLVector4a& p0 = new_face.mPositions[i0];
1244			LLVector4a& p1 = new_face.mPositions[i1];
1245			LLVector4a& p2 = new_face.mPositions[i2];
1246
1247			LLVector4a& n0 = new_face.mNormals[i0];
1248			LLVector4a& n1 = new_face.mNormals[i1];
1249			LLVector4a& n2 = new_face.mNormals[i2];
1250
1251			LLVector4a lhs, rhs;
1252			lhs.setSub(p1, p0);
1253			rhs.setSub(p2, p0);
1254
1255			n0.setCross3(lhs, rhs);
1256			n0.normalize3();
1257			n1 = n0;
1258			n2 = n0;
1259		}
1260
1261		//swap out normals in new_face with best match from point map (step 5)
1262		for (U32 i = 0; i < new_face.mNumVertices; ++i)
1263		{
1264			//LLVolumeFace::VertexData v = new_face.mVertices[i];
1265
1266			LLVector4a ref_norm = new_face.mNormals[i];
1267
1268			LLVolumeFace::VertexMapData::PointMap::iterator iter = point_map.find(LLVector3(new_face.mPositions[i].getF32ptr()));
1269
1270			if (iter != point_map.end())
1271			{
1272				F32 best = -2.f;
1273				for (U32 k = 0; k < iter->second.size(); ++k)
1274				{
1275					LLVector4a& n = iter->second[k].getNormal();
1276
1277					F32 cur = n.dot3(ref_norm).getF32();
1278
1279					if (cur > best)
1280					{
1281						best = cur;
1282						new_face.mNormals[i] = n;
1283					}
1284				}
1285			}
1286		}
1287		
1288		//remove redundant vertices from new face (step 6)
1289		new_face.optimize();
1290
1291		mVolumeFaces[j] = new_face;
1292	}
1293}
1294
1295//static
1296std::string LLModel::getElementLabel(daeElement *element)
1297{ // try to get a decent label for this element
1298	// if we have a name attribute, use it
1299	std::string name = element->getAttribute("name");
1300	if (name.length())
1301	{
1302		return name;
1303	}
1304
1305	// if we have an ID attribute, use it
1306	if (element->getID())
1307	{
1308		return std::string(element->getID());
1309	}
1310
1311	// if we have a parent, use it
1312	daeElement* parent = element->getParent();
1313	if (parent)
1314	{
1315		// if parent has a name, use it
1316		std::string name = parent->getAttribute("name");
1317		if (name.length())
1318		{
1319			return name;
1320		}
1321
1322		// if parent has an ID, use it
1323		if (parent->getID())
1324		{
1325			return std::string(parent->getID());
1326		}
1327	}
1328
1329	// try to use our type
1330	daeString element_name = element->getElementName();
1331	if (element_name)
1332	{
1333		return std::string(element_name);
1334	}
1335
1336	// if all else fails, use "object"
1337	return std::string("object");
1338}
1339
1340//static 
1341LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
1342{
1343	LLVolumeParams volume_params;
1344	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
1345	LLModel* ret = new LLModel(volume_params, 0.f); 
1346	ret->createVolumeFacesFromDomMesh(mesh);
1347	ret->mLabel = getElementLabel(mesh);
1348	return ret;
1349}
1350
1351std::string LLModel::getName() const
1352{
1353	if (!mRequestedLabel.empty())
1354		return mRequestedLabel;
1355	else
1356		return mLabel;
1357}
1358
1359//static
1360LLSD LLModel::writeModel(
1361	std::ostream& ostr,
1362	LLModel* physics,
1363	LLModel* high,
1364	LLModel* medium,
1365	LLModel* low,
1366	LLModel* impostor,
1367	const LLModel::Decomposition& decomp,
1368	BOOL upload_skin,
1369	BOOL upload_joints,
1370	BOOL nowrite,
1371	BOOL as_slm)
1372{
1373	LLSD mdl;
1374
1375	LLModel* model[] = 
1376	{
1377		impostor,
1378		low,
1379		medium,
1380		high,
1381		physics
1382	};
1383
1384	bool skinning = upload_skin && high && !high->mSkinWeights.empty();
1385
1386	if (skinning)
1387	{ //write skinning block
1388		mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints);
1389	}
1390
1391	if (!decomp.mBaseHull.empty() ||
1392		!decomp.mHull.empty())		
1393	{
1394		mdl["physics_convex"] = decomp.asLLSD();
1395		if (!decomp.mHull.empty() && !as_slm)
1396		{ //convex decomposition exists, physics mesh will not be used (unless this is an slm file)
1397			model[LLModel::LOD_PHYSICS] = NULL;
1398		}
1399	}
1400
1401	if (as_slm)
1402	{ //save material list names
1403		for (U32 i = 0; i < high->mMaterialList.size(); ++i)
1404		{
1405			mdl["material_list"][i] = high->mMaterialList[i];
1406		}
1407	}
1408
1409	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
1410	{
1411		if (model[idx] && model[idx]->getNumVolumeFaces() > 0)
1412		{
1413			LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr());
1414			LLVector3 max_pos = min_pos;
1415
1416			//find position domain
1417			for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
1418			{ //for each face
1419				const LLVolumeFace& face = model[idx]->getVolumeFace(i);
1420				for (U32 j = 0; j < face.mNumVertices; ++j)
1421				{
1422					update_min_max(min_pos, max_pos, face.mPositions[j].getF32ptr());
1423				}
1424			}
1425
1426			LLVector3 pos_range = max_pos - min_pos;
1427
1428			for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
1429			{ //for each face
1430				const LLVolumeFace& face = model[idx]->getVolumeFace(i);
1431				if (face.mNumVertices < 3)
1432				{ //don't export an empty face
1433					mdl[model_names[idx]][i]["NoGeometry"] = true;
1434					continue;
1435				}
1436				LLSD::Binary verts(face.mNumVertices*3*2);
1437				LLSD::Binary tc(face.mNumVertices*2*2);
1438				LLSD::Binary normals(face.mNumVertices*3*2);
1439				LLSD::Binary indices(face.mNumIndices*2);
1440
1441				U32 vert_idx = 0;
1442				U32 norm_idx = 0;
1443				U32 tc_idx = 0;
1444			
1445				LLVector2* ftc = (LLVector2*) face.mTexCoords;
1446				LLVector2 min_tc;
1447				LLVector2 max_tc;
1448
1449				if (ftc)
1450				{
1451					min_tc = ftc[0];
1452					max_tc = min_tc;
1453					
1454					//get texture coordinate domain
1455					for (U32 j = 0; j < face.mNumVertices; ++j)
1456					{
1457						update_min_max(min_tc, max_tc, ftc[j]);
1458					}
1459				}
1460
1461				LLVector2 tc_range = max_tc - min_tc;
1462
1463				for (U32 j = 0; j < face.mNumVertices; ++j)
1464				{ //for each vert
1465		
1466					F32* pos = face.mPositions[j].getF32ptr();
1467										
1468					//position
1469					for (U32 k = 0; k < 3; ++k)
1470					{ //for each component
1471						//convert to 16-bit normalized across domain
1472						U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
1473
1474						U8* buff = (U8*) &val;
1475						//write to binary buffer
1476						verts[vert_idx++] = buff[0];
1477						verts[vert_idx++] = buff[1];
1478					}
1479
1480					if (face.mNormals)
1481					{ //normals
1482						F32* norm = face.mNormals[j].getF32ptr();
1483
1484						for (U32 k = 0; k < 3; ++k)
1485						{ //for each component
1486							//convert to 16-bit normalized
1487							U16 val = (U16) ((norm[k]+1.f)*0.5f*65535);
1488							U8* buff = (U8*) &val;
1489
1490							//write to binary buffer
1491							normals[norm_idx++] = buff[0];
1492							normals[norm_idx++] = buff[1];
1493						}
1494					}
1495					
1496					F32* src_tc = (F32*) face.mTexCoords[j].mV;
1497
1498					//texcoord
1499					if (face.mTexCoords)
1500					{
1501						for (U32 k = 0; k < 2; ++k)
1502						{ //for each component
1503							//convert to 16-bit normalized
1504							U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
1505
1506							U8* buff = (U8*) &val;
1507							//write to binary buffer
1508							tc[tc_idx++] = buff[0];
1509							tc[tc_idx++] = buff[1];
1510						}
1511					}
1512				}
1513
1514				U32 idx_idx = 0;
1515				for (U32 j = 0; j < face.mNumIndices; ++j)
1516				{
1517					U8* buff = (U8*) &(face.mIndices[j]);
1518					indices[idx_idx++] = buff[0];
1519					indices[idx_idx++] = buff[1];
1520				}
1521
1522				//write out face data
1523				mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
1524				mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
1525				mdl[model_names[idx]][i]["Position"] = verts;
1526				
1527				if (face.mNormals)
1528				{
1529					mdl[model_names[idx]][i]["Normal"] = normals;
1530				}
1531
1532				if (face.mTexCoords)
1533				{
1534					mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
1535					mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
1536					mdl[model_names[idx]][i]["TexCoord0"] = tc;
1537				}
1538
1539				mdl[model_names[idx]][i]["TriangleList"] = indices;
1540
1541				if (skinning)
1542				{
1543					//write out skin weights
1544
1545					//each influence list entry is up to 4 24-bit values
1546					// first 8 bits is bone index
1547					// last 16 bits is bone influence weight
1548					// a bone index of 0xFF signifies no more influences for this vertex
1549
1550					std::stringstream ostr;
1551
1552					for (U32 j = 0; j < face.mNumVertices; ++j)
1553					{
1554						LLVector3 pos(face.mPositions[j].getF32ptr());
1555
1556						weight_list& weights = high->getJointInfluences(pos);
1557
1558						S32 count = 0;
1559						for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
1560						{
1561							if (iter->mJointIdx < 255 && iter->mJointIdx >= 0)
1562							{
1563								U8 idx = (U8) iter->mJointIdx;
1564								ostr.write((const char*) &idx, 1);
1565
1566								U16 influence = (U16) (iter->mWeight*65535);
1567								ostr.write((const char*) &influence, 2);
1568
1569								++count;
1570							}		
1571						}
1572						U8 end_list = 0xFF;
1573						if (count < 4)
1574						{
1575							ostr.write((const char*) &end_list, 1);
1576						}
1577					}
1578
1579					//copy ostr to binary buffer
1580					std::string data = ostr.str();
1581					const U8* buff = (U8*) data.data();
1582					U32 bytes = data.size();
1583
1584					LLSD::Binary w(bytes);
1585					for (U32 j = 0; j < bytes; ++j)
1586					{
1587						w[j] = buff[j];
1588					}
1589
1590					mdl[model_names[idx]][i]["Weights"] = w;
1591				}
1592			}
1593		}
1594	}
1595	
1596	return writeModelToStream(ostr, mdl, nowrite, as_slm);
1597}
1598
1599LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)
1600{
1601	U32 bytes = 0;
1602	
1603	std::string::size_type cur_offset = 0;
1604
1605	LLSD header;
1606
1607	if (as_slm && mdl.has("material_list"))
1608	{ //save material binding names to header
1609		header["material_list"] = mdl["material_list"];
1610	}
1611
1612	std::string skin;
1613
1614	if (mdl.has("skin"))
1615	{ //write out skin block
1616		skin = zip_llsd(mdl["skin"]);
1617
1618		U32 size = skin.size();
1619		if (size > 0)
1620		{
1621			header["skin"]["offset"] = (LLSD::Integer) cur_offset;
1622			header["skin"]["size"] = (LLSD::Integer) size;
1623			cur_offset += size;
1624			bytes += size;
1625		}
1626	}
1627
1628	std::string decomposition;
1629
1630	if (mdl.has("physics_convex"))
1631	{ //write out convex decomposition
1632		decomposition = zip_llsd(mdl["physics_convex"]);
1633
1634		U32 size = decomposition.size();
1635		if (size > 0)
1636		{
1637			header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
1638			header["physics_convex"]["size"] = (LLSD::Integer) size;
1639			cur_offset += size;
1640			bytes += size;
1641		}
1642	}
1643
1644	std::string out[MODEL_NAMES_LENGTH];
1645
1646	for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
1647	{
1648		if (mdl.has(model_names[i]))
1649		{
1650			out[i] = zip_llsd(mdl[model_names[i]]);
1651
1652			U32 size = out[i].size();
1653
1654			header[model_names[i]]["offset"] = (LLSD::Integer) cur_offset;
1655			header[model_names[i]]["size"] = (LLSD::Integer) size;
1656			cur_offset += size;
1657			bytes += size;
1658		}
1659	}
1660
1661	if (!nowrite)
1662	{
1663		LLSDSerialize::toBinary(header, ostr);
1664
1665		if (!skin.empty())
1666		{ //write skin block
1667			ostr.write((const char*) skin.data(), header["skin"]["size"].asInteger());
1668		}
1669
1670		if (!decomposition.empty())
1671		{ //write decomposition block
1672			ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
1673		}
1674
1675		for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
1676		{
1677			if (!out[i].empty())
1678			{
1679				ostr.write((const char*) out[i].data(), header[model_names[i]]["size"].asInteger());
1680			}
1681		}
1682	}
1683	
1684	return header;
1685}
1686
1687LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
1688{
1689	//1. If a vertex has been weighted then we'll find it via pos and return it's weight list
1690	weight_map::iterator iterPos = mSkinWeights.begin();
1691	weight_map::iterator iterEnd = mSkinWeights.end();
1692	
1693	for ( ; iterPos!=iterEnd; ++iterPos )
1694	{
1695		if ( jointPositionalLookup( iterPos->first, pos ) )
1696		{
1697			return iterPos->second;
1698		}
1699	}
1700	
1701	//2. Otherwise we'll use the older implementation
1702	weight_map::iterator iter = mSkinWeights.find(pos);
1703	
1704	if (iter != mSkinWeights.end())
1705	{
1706		if ((iter->first - pos).magVec() > 0.1f)
1707		{
1708			llerrs << "Couldn't find weight list." << llendl;
1709		}
1710
1711		return iter->second;
1712	}
1713	else
1714	{  //no exact match found, get closest point
1715		const F32 epsilon = 1e-5f;
1716		weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
1717		weight_map::iterator iter_down = ++iter_up;
1718
1719		weight_map::iterator best = iter_up;
1720
1721		F32 min_dist = (iter->first - pos).magVec();
1722
1723		bool done = false;
1724		while (!done)
1725		{ //search up and down mSkinWeights from lower bound of pos until a 
1726		  //match is found within epsilon.  If no match is found within epsilon,
1727		  //return closest match
1728			done = true;
1729			if (iter_up != mSkinWeights.end() && ++iter_up != mSkinWeights.end())
1730			{
1731				done = false;
1732				F32 dist = (iter_up->first - pos).magVec();
1733
1734				if (dist < epsilon)
1735				{
1736					return iter_up->second;
1737				}
1738
1739				if (dist < min_dist)
1740				{
1741					best = iter_up;
1742					min_dist = dist;
1743				}
1744			}
1745
1746			if (iter_down != mSkinWeights.begin() && --iter_down != mSkinWeights.begin())
1747			{
1748				done = false;
1749
1750				F32 dist = (iter_down->first - pos).magVec();
1751
1752				if (dist < epsilon)
1753				{
1754					return iter_down->second;
1755				}
1756
1757				if (dist < min_dist)
1758				{
1759					best = iter_down;
1760					min_dist = dist;
1761				}
1762
1763			}
1764		}
1765		
1766		return best->second;
1767	}					
1768}
1769
1770void LLModel::setConvexHullDecomposition(
1771	const LLModel::convex_hull_decomposition& decomp)
1772{
1773	mPhysics.mHull = decomp;
1774	mPhysics.mMesh.clear();
1775	updateHullCenters();
1776}
1777
1778void LLModel::updateHullCenters()
1779{
1780	mHullCenter.resize(mPhysics.mHull.size());
1781	mHullPoints = 0;
1782	mCenterOfHullCenters.clear();
1783
1784	for (U32 i = 0; i < mPhysics.mHull.size(); ++i)
1785	{
1786		LLVector3 cur_center;
1787
1788		for (U32 j = 0; j < mPhysics.mHull[i].size(); ++j)
1789		{
1790			cur_center += mPhysics.mHull[i][j];
1791		}
1792		mCenterOfHullCenters += cur_center;
1793		cur_center *= 1.f/mPhysics.mHull[i].size();
1794		mHullCenter[i] = cur_center;
1795		mHullPoints += mPhysics.mHull[i].size();
1796	}
1797
1798	if (mHullPoints > 0)
1799	{
1800		mCenterOfHullCenters *= 1.f / mHullPoints;
1801		llassert(mPhysics.hasHullList());
1802	}
1803}
1804
1805bool LLModel::loadModel(std::istream& is)
1806{
1807	mSculptLevel = -1;  // default is an error occured
1808
1809	LLSD header;
1810	{
1811		if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
1812		{
1813			llwarns << "Mesh header parse error.  Not a valid mesh asset!" << llendl;
1814			return false;
1815		}
1816	}
1817	
1818	if (header.has("material_list"))
1819	{ //load material list names
1820		mMaterialList.clear();
1821		for (U32 i = 0; i < header["material_list"].size(); ++i)
1822		{
1823			mMaterialList.push_back(header["material_list"][i].asString());
1824		}
1825	}
1826
1827	std::string nm[] = 
1828	{
1829		"lowest_lod",
1830		"low_lod",
1831		"medium_lod",
1832		"high_lod",
1833		"physics_mesh",
1834	};
1835
1836	const S32 MODEL_LODS = 5;
1837
1838	S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
1839
1840	if (header[nm[lod]]["offset"].asInteger() == -1 || 
1841		header[nm[lod]]["size"].asInteger() == 0 )
1842	{ //cannot load requested LOD
1843		llwarns << "LoD data is invalid!" << llendl;
1844		return false;
1845	}
1846
1847	bool has_skin = header["skin"]["offset"].asInteger() >=0 &&
1848					header["skin"]["size"].asInteger() > 0;
1849
1850	if (lod == LLModel::LOD_HIGH)
1851	{ //try to load skin info and decomp info
1852		std::ios::pos_type cur_pos = is.tellg();
1853		loadSkinInfo(header, is);
1854		is.seekg(cur_pos);
1855	}
1856
1857	if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)
1858	{
1859		std::ios::pos_type cur_pos = is.tellg();
1860		loadDecomposition(header, is);
1861		is.seekg(cur_pos);
1862	}
1863
1864	is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
1865
1866	if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()))
1867	{
1868		if (has_skin)
1869		{ 
1870			//build out mSkinWeight from face info
1871			for (S32 i = 0; i < getNumVolumeFaces(); ++i)
1872			{
1873				const LLVolumeFace& face = getVolumeFace(i);
1874
1875				if (face.mWeights)
1876				{
1877					for (S32 j = 0; j < face.mNumVertices; ++j)
1878					{
1879						LLVector4a& w = face.mWeights[j];
1880
1881						std::vector<JointWeight> wght;
1882
1883						for (S32 k = 0; k < 4; ++k)
1884						{
1885							S32 idx = (S32) w[k];
1886							F32 f = w[k] - idx;
1887							if (f > 0.f)
1888							{
1889								wght.push_back(JointWeight(idx, f));
1890							}
1891						}
1892
1893						if (!wght.empty())
1894						{
1895							LLVector3 pos(face.mPositions[j].getF32ptr());
1896							mSkinWeights[pos] = wght;
1897						}
1898					}
1899				}
1900			}
1901		}
1902		return true;
1903	}
1904	else
1905	{
1906		llwarns << "unpackVolumeFaces failed!" << llendl;
1907	}
1908
1909	return false;
1910
1911}
1912
1913bool LLModel::isMaterialListSubset( LLModel* ref )
1914{
1915	int refCnt = ref->mMaterialList.size();
1916	int modelCnt = mMaterialList.size();
1917	
1918	for (U32 src = 0; src < modelCnt; ++src)
1919	{				
1920		bool foundRef = false;
1921		
1922		for (U32 dst = 0; dst < refCnt; ++dst)
1923		{
1924			//llinfos<<mMaterialList[src]<<" "<<ref->mMaterialList[dst]<<llendl;
1925			foundRef = mMaterialList[src] == ref->mMaterialList[dst];									
1926				
1927			if ( foundRef )
1928			{	
1929				break;
1930			}										
1931		}
1932		if (!foundRef)
1933		{
1934			return false;
1935		}
1936	}
1937	
1938	return true;
1939}
1940
1941bool LLModel::needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt )
1942{
1943	bool changed = false;
1944	if ( refFaceCnt< modelFaceCnt )
1945	{
1946		refFaceCnt += modelFaceCnt - refFaceCnt;
1947		changed = true;
1948	}
1949	else 
1950	if ( modelFaceCnt < refFaceCnt )
1951	{
1952		modelFaceCnt += refFaceCnt - modelFaceCnt;
1953		changed = true;
1954	}
1955	
1956	return changed;
1957}
1958
1959bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt )
1960{
1961	//Is this a subset?
1962	//LODs cannot currently add new materials, e.g.
1963	//1. ref = a,b,c lod1 = d,e => This is not permitted
1964	//2. ref = a,b,c lod1 = c => This would be permitted
1965	
1966	bool isASubset = isMaterialListSubset( ref );
1967	if ( !isASubset )
1968	{
1969		llinfos<<"Material of model is not a subset of reference."<<llendl;
1970		return false;
1971	}
1972	
1973	std::map<std::string, U32> index_map;
1974	
1975	//build a map of material slot names to face indexes
1976	bool reorder = false;
1977
1978	std::set<std::string> base_mat;
1979	std::set<std::string> cur_mat;
1980
1981	for (U32 i = 0; i < mMaterialList.size(); i++)
1982	{
1983		index_map[ref->mMaterialList[i]] = i;
1984		if (!reorder)
1985		{ //if any material name does not match reference, we need to reorder
1986			reorder = ref->mMaterialList[i] != mMaterialList[i];
1987		}
1988		base_mat.insert(ref->mMaterialList[i]);
1989		cur_mat.insert(mMaterialList[i]);
1990	}
1991
1992
1993	if (reorder && 
1994		base_mat == cur_mat) //don't reorder if material name sets don't match
1995	{
1996		std::vector<LLVolumeFace> new_face_list;
1997		new_face_list.resize(mVolumeFaces.size());
1998
1999		std::vector<std::string> new_material_list;
2000		new_material_list.resize(mVolumeFaces.size());
2001
2002		//rebuild face list so materials have the same order 
2003		//as the reference model
2004		for (U32 i = 0; i < mMaterialList.size(); ++i)
2005		{ 
2006			U32 ref_idx = index_map[mMaterialList[i]];
2007			new_face_list[ref_idx] = mVolumeFaces[i];
2008
2009			new_material_list[ref_idx] = mMaterialList[i];
2010		}
2011
2012		llassert(new_material_list == ref->mMaterialList);
2013		
2014		mVolumeFaces = new_face_list;
2015	}
2016
2017	//override material list with reference model ordering
2018	mMaterialList = ref->mMaterialList;
2019	return true;
2020}
2021
2022
2023bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
2024{
2025	S32 offset = header["skin"]["offset"].asInteger();
2026	S32 size = header["skin"]["size"].asInteger();
2027
2028	if (offset >= 0 && size > 0)
2029	{
2030		is.seekg(offset, std::ios_base::cur);
2031
2032		LLSD skin_data;
2033
2034		if (unzip_llsd(skin_data, is, size))
2035		{
2036			mSkinInfo.fromLLSD(skin_data);
2037			return true;
2038		}
2039	}
2040
2041	return false;
2042}
2043
2044bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
2045{
2046	S32 offset = header["physics_convex"]["offset"].asInteger();
2047	S32 size = header["physics_convex"]["size"].asInteger();
2048
2049	if (offset >= 0 && size > 0)
2050	{
2051		is.seekg(offset, std::ios_base::cur);
2052
2053		LLSD data;
2054
2055		if (unzip_llsd(data, is, size))
2056		{
2057			mPhysics.fromLLSD(data);
2058			updateHullCenters();
2059		}
2060	}
2061
2062	return true;
2063}
2064
2065
2066LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin)
2067{
2068	fromLLSD(skin);
2069}
2070
2071void LLMeshSkinInfo::fromLLSD(LLSD& skin)
2072{
2073	if (skin.has("joint_names"))
2074	{
2075		for (U32 i = 0; i < skin["joint_names"].size(); ++i)
2076		{
2077			mJointNames.push_back(skin["joint_names"][i]);
2078		}
2079	}
2080
2081	if (skin.has("inverse_bind_matrix"))
2082	{
2083		for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i)
2084		{
2085			LLMatrix4 mat;
2086			for (U32 j = 0; j < 4; j++)
2087			{
2088				for (U32 k = 0; k < 4; k++)
2089				{
2090					mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal();
2091				}
2092			}
2093
2094			mInvBindMatrix.push_back(mat);
2095		}
2096	}
2097
2098	if (skin.has("bind_shape_matrix"))
2099	{
2100		for (U32 j = 0; j < 4; j++)
2101		{
2102			for (U32 k = 0; k < 4; k++)
2103			{
2104				mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal();
2105			}
2106		}
2107	}
2108
2109	if (skin.has("alt_inverse_bind_matrix"))
2110	{
2111		for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
2112		{
2113			LLMatrix4 mat;
2114			for (U32 j = 0; j < 4; j++)
2115			{
2116				for (U32 k = 0; k < 4; k++)
2117				{
2118					mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal();
2119				}
2120			}
2121			
2122			mAlternateBindMatrix.push_back(mat);
2123		}
2124	}
2125
2126	if (skin.has("pelvis_offset"))
2127	{
2128		mPelvisOffset = skin["pelvis_offset"].asReal();
2129	}
2130}
2131
2132LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const
2133{
2134	LLSD ret;
2135
2136	for (U32 i = 0; i < mJointNames.size(); ++i)
2137	{
2138		ret["joint_names"][i] = mJointNames[i];
2139
2140		for (U32 j = 0; j < 4; j++)
2141		{
2142			for (U32 k = 0; k < 4;

Large files files are truncated, but you can click here to view the full file