PageRenderTime 80ms CodeModel.GetById 8ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmath/llvolume.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 1111 lines | 843 code | 187 blank | 81 comment | 66 complexity | 7662167199e69f00a002207ee3ce4bcf MD5 | raw file
   1/** 
   2 * @file llvolume.h
   3 * @brief LLVolume base class.
   4 *
   5 * $LicenseInfo:firstyear=2002&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#ifndef LL_LLVOLUME_H
  28#define LL_LLVOLUME_H
  29
  30#include <iostream>
  31
  32class LLProfileParams;
  33class LLPathParams;
  34class LLVolumeParams;
  35class LLProfile;
  36class LLPath;
  37
  38template <class T> class LLOctreeNode;
  39
  40class LLVector4a;
  41class LLVolumeFace;
  42class LLVolume;
  43class LLVolumeTriangle;
  44
  45#include "lldarray.h"
  46#include "lluuid.h"
  47#include "v4color.h"
  48//#include "vmath.h"
  49#include "v2math.h"
  50#include "v3math.h"
  51#include "v3dmath.h"
  52#include "v4math.h"
  53#include "llquaternion.h"
  54#include "llstrider.h"
  55#include "v4coloru.h"
  56#include "llrefcount.h"
  57#include "llfile.h"
  58
  59//============================================================================
  60
  61const S32 MIN_DETAIL_FACES = 6;
  62const S32 MIN_LOD = 0;
  63const S32 MAX_LOD = 3;
  64
  65// These are defined here but are not enforced at this level,
  66// rather they are here for the convenience of code that uses
  67// the LLVolume class.
  68const F32 MIN_VOLUME_PROFILE_WIDTH 	= 0.05f;
  69const F32 MIN_VOLUME_PATH_WIDTH 	= 0.05f;
  70
  71const F32 CUT_QUANTA    = 0.00002f;
  72const F32 SCALE_QUANTA  = 0.01f;
  73const F32 SHEAR_QUANTA  = 0.01f;
  74const F32 TAPER_QUANTA  = 0.01f;
  75const F32 REV_QUANTA    = 0.015f;
  76const F32 HOLLOW_QUANTA = 0.00002f;
  77
  78const S32 MAX_VOLUME_TRIANGLE_INDICES = 10000;
  79
  80//============================================================================
  81
  82// useful masks
  83const LLPCode LL_PCODE_HOLLOW_MASK 	= 0x80;		// has a thickness
  84const LLPCode LL_PCODE_SEGMENT_MASK = 0x40;		// segments (1 angle)
  85const LLPCode LL_PCODE_PATCH_MASK 	= 0x20;		// segmented segments (2 angles)
  86const LLPCode LL_PCODE_HEMI_MASK 	= 0x10;		// half-primitives get their own type per PR's dictum
  87const LLPCode LL_PCODE_BASE_MASK 	= 0x0F;
  88
  89	// primitive shapes
  90const LLPCode	LL_PCODE_CUBE 			= 1;
  91const LLPCode	LL_PCODE_PRISM 			= 2;
  92const LLPCode	LL_PCODE_TETRAHEDRON 	= 3;
  93const LLPCode	LL_PCODE_PYRAMID 		= 4;
  94const LLPCode	LL_PCODE_CYLINDER 		= 5;
  95const LLPCode	LL_PCODE_CONE 			= 6;
  96const LLPCode	LL_PCODE_SPHERE 		= 7;
  97const LLPCode	LL_PCODE_TORUS 			= 8;
  98const LLPCode	LL_PCODE_VOLUME			= 9;
  99
 100	// surfaces
 101//const LLPCode	LL_PCODE_SURFACE_TRIANGLE 	= 10;
 102//const LLPCode	LL_PCODE_SURFACE_SQUARE 	= 11;
 103//const LLPCode	LL_PCODE_SURFACE_DISC 		= 12;
 104
 105const LLPCode	LL_PCODE_APP				= 14; // App specific pcode (for viewer/sim side only objects)
 106const LLPCode	LL_PCODE_LEGACY				= 15;
 107
 108// Pcodes for legacy objects
 109//const LLPCode	LL_PCODE_LEGACY_ATOR =				0x10 | LL_PCODE_LEGACY; // ATOR
 110const LLPCode	LL_PCODE_LEGACY_AVATAR =			0x20 | LL_PCODE_LEGACY; // PLAYER
 111//const LLPCode	LL_PCODE_LEGACY_BIRD =				0x30 | LL_PCODE_LEGACY; // BIRD
 112//const LLPCode	LL_PCODE_LEGACY_DEMON =				0x40 | LL_PCODE_LEGACY; // DEMON
 113const LLPCode	LL_PCODE_LEGACY_GRASS =				0x50 | LL_PCODE_LEGACY; // GRASS
 114const LLPCode	LL_PCODE_TREE_NEW =					0x60 | LL_PCODE_LEGACY; // new trees
 115//const LLPCode	LL_PCODE_LEGACY_ORACLE =			0x70 | LL_PCODE_LEGACY; // ORACLE
 116const LLPCode	LL_PCODE_LEGACY_PART_SYS =			0x80 | LL_PCODE_LEGACY; // PART_SYS
 117const LLPCode	LL_PCODE_LEGACY_ROCK =				0x90 | LL_PCODE_LEGACY; // ROCK
 118//const LLPCode	LL_PCODE_LEGACY_SHOT =				0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT
 119//const LLPCode	LL_PCODE_LEGACY_SHOT_BIG =			0xB0 | LL_PCODE_LEGACY;
 120//const LLPCode	LL_PCODE_LEGACY_SMOKE =				0xC0 | LL_PCODE_LEGACY; // SMOKE
 121//const LLPCode	LL_PCODE_LEGACY_SPARK =				0xD0 | LL_PCODE_LEGACY;// SPARK
 122const LLPCode	LL_PCODE_LEGACY_TEXT_BUBBLE =		0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE
 123const LLPCode	LL_PCODE_LEGACY_TREE =				0xF0 | LL_PCODE_LEGACY; // TREE
 124
 125	// hemis
 126const LLPCode	LL_PCODE_CYLINDER_HEMI =		LL_PCODE_CYLINDER	| LL_PCODE_HEMI_MASK;
 127const LLPCode	LL_PCODE_CONE_HEMI =			LL_PCODE_CONE		| LL_PCODE_HEMI_MASK;
 128const LLPCode	LL_PCODE_SPHERE_HEMI =			LL_PCODE_SPHERE		| LL_PCODE_HEMI_MASK;
 129const LLPCode	LL_PCODE_TORUS_HEMI =			LL_PCODE_TORUS		| LL_PCODE_HEMI_MASK;
 130
 131
 132// Volumes consist of a profile at the base that is swept around
 133// a path to make a volume.
 134// The profile code
 135const U8	LL_PCODE_PROFILE_MASK		= 0x0f;
 136const U8	LL_PCODE_PROFILE_MIN		= 0x00;
 137const U8    LL_PCODE_PROFILE_CIRCLE		= 0x00;
 138const U8    LL_PCODE_PROFILE_SQUARE		= 0x01;
 139const U8	LL_PCODE_PROFILE_ISOTRI		= 0x02;
 140const U8    LL_PCODE_PROFILE_EQUALTRI	= 0x03;
 141const U8    LL_PCODE_PROFILE_RIGHTTRI	= 0x04;
 142const U8	LL_PCODE_PROFILE_CIRCLE_HALF = 0x05;
 143const U8	LL_PCODE_PROFILE_MAX		= 0x05;
 144
 145// Stored in the profile byte
 146const U8	LL_PCODE_HOLE_MASK		= 0xf0;
 147const U8	LL_PCODE_HOLE_MIN		= 0x00;	  
 148const U8	LL_PCODE_HOLE_SAME		= 0x00;		// same as outside profile
 149const U8	LL_PCODE_HOLE_CIRCLE	= 0x10;
 150const U8	LL_PCODE_HOLE_SQUARE	= 0x20;
 151const U8	LL_PCODE_HOLE_TRIANGLE	= 0x30;
 152const U8	LL_PCODE_HOLE_MAX		= 0x03;		// min/max needs to be >> 4 of real min/max
 153
 154const U8    LL_PCODE_PATH_IGNORE    = 0x00;
 155const U8	LL_PCODE_PATH_MIN		= 0x01;		// min/max needs to be >> 4 of real min/max
 156const U8    LL_PCODE_PATH_LINE      = 0x10;
 157const U8    LL_PCODE_PATH_CIRCLE    = 0x20;
 158const U8    LL_PCODE_PATH_CIRCLE2   = 0x30;
 159const U8    LL_PCODE_PATH_TEST      = 0x40;
 160const U8    LL_PCODE_PATH_FLEXIBLE  = 0x80;
 161const U8	LL_PCODE_PATH_MAX		= 0x08;
 162
 163//============================================================================
 164
 165// face identifiers
 166typedef U16 LLFaceID;
 167
 168const LLFaceID	LL_FACE_PATH_BEGIN		= 0x1 << 0;
 169const LLFaceID	LL_FACE_PATH_END		= 0x1 << 1;
 170const LLFaceID	LL_FACE_INNER_SIDE		= 0x1 << 2;
 171const LLFaceID	LL_FACE_PROFILE_BEGIN	= 0x1 << 3;
 172const LLFaceID	LL_FACE_PROFILE_END		= 0x1 << 4;
 173const LLFaceID	LL_FACE_OUTER_SIDE_0	= 0x1 << 5;
 174const LLFaceID	LL_FACE_OUTER_SIDE_1	= 0x1 << 6;
 175const LLFaceID	LL_FACE_OUTER_SIDE_2	= 0x1 << 7;
 176const LLFaceID	LL_FACE_OUTER_SIDE_3	= 0x1 << 8;
 177
 178//============================================================================
 179
 180// sculpt types + flags
 181
 182const U8 LL_SCULPT_TYPE_NONE      = 0;
 183const U8 LL_SCULPT_TYPE_SPHERE    = 1;
 184const U8 LL_SCULPT_TYPE_TORUS     = 2;
 185const U8 LL_SCULPT_TYPE_PLANE     = 3;
 186const U8 LL_SCULPT_TYPE_CYLINDER  = 4;
 187const U8 LL_SCULPT_TYPE_MESH      = 5;
 188const U8 LL_SCULPT_TYPE_MASK      = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
 189	LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
 190
 191const U8 LL_SCULPT_FLAG_INVERT    = 64;
 192const U8 LL_SCULPT_FLAG_MIRROR    = 128;
 193
 194const S32 LL_SCULPT_MESH_MAX_FACES = 8;
 195
 196class LLProfileParams
 197{
 198public:
 199	LLProfileParams()
 200		: mCurveType(LL_PCODE_PROFILE_SQUARE),
 201		  mBegin(0.f),
 202		  mEnd(1.f),
 203		  mHollow(0.f),
 204		  mCRC(0)
 205	{
 206	}
 207
 208	LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow)
 209		: mCurveType(curve),
 210		  mBegin(begin),
 211		  mEnd(end),
 212		  mHollow(hollow),
 213		  mCRC(0)
 214	{
 215	}
 216
 217	LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow)
 218	{
 219		mCurveType = curve;
 220		F32 temp_f32 = begin * CUT_QUANTA;
 221		if (temp_f32 > 1.f)
 222		{
 223			temp_f32 = 1.f;
 224		}
 225		mBegin = temp_f32;
 226		temp_f32 = end * CUT_QUANTA;
 227		if (temp_f32 > 1.f)
 228		{
 229			temp_f32 = 1.f;
 230		}
 231		mEnd = 1.f - temp_f32;
 232		temp_f32 = hollow * HOLLOW_QUANTA;
 233		if (temp_f32 > 1.f)
 234		{
 235			temp_f32 = 1.f;
 236		}
 237		mHollow = temp_f32;
 238		mCRC = 0;
 239	}
 240
 241	bool operator==(const LLProfileParams &params) const;
 242	bool operator!=(const LLProfileParams &params) const;
 243	bool operator<(const LLProfileParams &params) const;
 244	
 245	void copyParams(const LLProfileParams &params);
 246
 247	BOOL importFile(LLFILE *fp);
 248	BOOL exportFile(LLFILE *fp) const;
 249
 250	BOOL importLegacyStream(std::istream& input_stream);
 251	BOOL exportLegacyStream(std::ostream& output_stream) const;
 252
 253	LLSD asLLSD() const;
 254	operator LLSD() const { return asLLSD(); }
 255	bool fromLLSD(LLSD& sd);
 256
 257	const F32&  getBegin () const				{ return mBegin; }
 258	const F32&  getEnd   () const				{ return mEnd;   }
 259	const F32&  getHollow() const				{ return mHollow; }
 260	const U8&   getCurveType () const			{ return mCurveType; }
 261
 262	void setCurveType(const U32 type)			{ mCurveType = type;}
 263	void setBegin(const F32 begin)				{ mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;}
 264	void setEnd(const F32 end)					{ mEnd   = (end   <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;}
 265	void setHollow(const F32 hollow)			{ mHollow = ((int) (hollow * 100000))/100000.0f;}
 266
 267	friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params);
 268
 269protected:
 270	// Profile params
 271	U8			  mCurveType;
 272	F32           mBegin;
 273	F32           mEnd;
 274	F32			  mHollow;
 275
 276	U32           mCRC;
 277};
 278
 279inline bool LLProfileParams::operator==(const LLProfileParams &params) const
 280{
 281	return 
 282		(getCurveType() == params.getCurveType()) &&
 283		(getBegin() == params.getBegin()) &&
 284		(getEnd() == params.getEnd()) &&
 285		(getHollow() == params.getHollow());
 286}
 287
 288inline bool LLProfileParams::operator!=(const LLProfileParams &params) const
 289{
 290	return 
 291		(getCurveType() != params.getCurveType()) ||
 292		(getBegin() != params.getBegin()) ||
 293		(getEnd() != params.getEnd()) ||
 294		(getHollow() != params.getHollow());
 295}
 296
 297
 298inline bool LLProfileParams::operator<(const LLProfileParams &params) const
 299{
 300	if (getCurveType() != params.getCurveType())
 301	{
 302		return getCurveType() < params.getCurveType();
 303	}
 304	else
 305	if (getBegin() != params.getBegin())
 306	{
 307		return getBegin() < params.getBegin();
 308	}
 309	else
 310	if (getEnd() != params.getEnd())
 311	{
 312		return getEnd() < params.getEnd();
 313	}
 314	else
 315	{
 316		return getHollow() < params.getHollow();
 317	}
 318}
 319
 320#define U8_TO_F32(x) (F32)(*((S8 *)&x))
 321
 322class LLPathParams
 323{
 324public:
 325	LLPathParams()
 326		:
 327		mCurveType(LL_PCODE_PATH_LINE),
 328		mBegin(0.f),
 329		mEnd(1.f),
 330		mScale(1.f,1.f),
 331		mShear(0.f,0.f),
 332		mTwistBegin(0.f),
 333		mTwistEnd(0.f),
 334		mRadiusOffset(0.f),
 335		mTaper(0.f,0.f),
 336		mRevolutions(1.f),
 337		mSkew(0.f),
 338		mCRC(0)
 339	{
 340	}
 341
 342	LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew)
 343		: mCurveType(curve),
 344		  mBegin(begin),
 345		  mEnd(end),
 346		  mScale(scx,scy),
 347		  mShear(shx,shy),
 348		  mTwistBegin(twistbegin),
 349		  mTwistEnd(twistend), 
 350		  mRadiusOffset(radiusoffset),
 351		  mTaper(tx,ty),
 352		  mRevolutions(revolutions),
 353		  mSkew(skew),
 354		  mCRC(0)
 355	{
 356	}
 357
 358	LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew)
 359	{
 360		mCurveType = curve;
 361		mBegin = (F32)(begin * CUT_QUANTA);
 362		mEnd = (F32)(100.f - end) * CUT_QUANTA;
 363		if (mEnd > 1.f)
 364			mEnd = 1.f;
 365		mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA);
 366		mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA);
 367		mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA;
 368		mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA;
 369		mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA;
 370		mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA);
 371		mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f;
 372		mSkew = U8_TO_F32(skew) * SCALE_QUANTA;
 373
 374		mCRC = 0;
 375	}
 376
 377	bool operator==(const LLPathParams &params) const;
 378	bool operator!=(const LLPathParams &params) const;
 379	bool operator<(const LLPathParams &params) const;
 380
 381	void copyParams(const LLPathParams &params);
 382
 383	BOOL importFile(LLFILE *fp);
 384	BOOL exportFile(LLFILE *fp) const;
 385
 386	BOOL importLegacyStream(std::istream& input_stream);
 387	BOOL exportLegacyStream(std::ostream& output_stream) const;
 388
 389	LLSD asLLSD() const;
 390	operator LLSD() const { return asLLSD(); }
 391	bool fromLLSD(LLSD& sd);
 392
 393	const F32& getBegin() const			{ return mBegin; }
 394	const F32& getEnd() const			{ return mEnd; }
 395	const LLVector2 &getScale() const	{ return mScale; }
 396	const F32& getScaleX() const		{ return mScale.mV[0]; }
 397	const F32& getScaleY() const		{ return mScale.mV[1]; }
 398	const LLVector2 getBeginScale() const;
 399	const LLVector2 getEndScale() const;
 400	const LLVector2 &getShear() const	{ return mShear; }
 401	const F32& getShearX() const		{ return mShear.mV[0]; }
 402	const F32& getShearY() const		{ return mShear.mV[1]; }
 403	const U8& getCurveType () const		{ return mCurveType; }
 404
 405	const F32& getTwistBegin() const	{ return mTwistBegin;	}
 406	const F32& getTwistEnd() const		{ return mTwistEnd;	}
 407	const F32& getTwist() const			{ return mTwistEnd; }	// deprecated
 408	const F32& getRadiusOffset() const	{ return mRadiusOffset; }
 409	const LLVector2 &getTaper() const	{ return mTaper;		}
 410	const F32& getTaperX() const		{ return mTaper.mV[0];	}
 411	const F32& getTaperY() const		{ return mTaper.mV[1];	}
 412	const F32& getRevolutions() const	{ return mRevolutions;	}
 413	const F32& getSkew() const			{ return mSkew;			}
 414
 415	void setCurveType(const U8 type)	{ mCurveType = type;	}
 416	void setBegin(const F32 begin)		{ mBegin     = begin;	}
 417	void setEnd(const F32 end)			{ mEnd       = end;	}
 418
 419	void setScale(const F32 x, const F32 y)		{ mScale.setVec(x,y); }
 420	void setScaleX(const F32 v)					{ mScale.mV[VX] = v; }
 421	void setScaleY(const F32 v)					{ mScale.mV[VY] = v; }
 422	void setShear(const F32 x, const F32 y)		{ mShear.setVec(x,y); }
 423	void setShearX(const F32 v)					{ mShear.mV[VX] = v; }
 424	void setShearY(const F32 v)					{ mShear.mV[VY] = v; }
 425
 426	void setTwistBegin(const F32 twist_begin)	{ mTwistBegin	= twist_begin;	}
 427	void setTwistEnd(const F32 twist_end)		{ mTwistEnd		= twist_end;	}
 428	void setTwist(const F32 twist)				{ setTwistEnd(twist); }	// deprecated
 429	void setRadiusOffset(const F32 radius_offset){ mRadiusOffset	= radius_offset; }
 430	void setTaper(const F32 x, const F32 y)		{ mTaper.setVec(x,y);			}
 431	void setTaperX(const F32 v)					{ mTaper.mV[VX]	= v;			}
 432	void setTaperY(const F32 v)					{ mTaper.mV[VY]	= v;			}
 433	void setRevolutions(const F32 revolutions)	{ mRevolutions	= revolutions;	}
 434	void setSkew(const F32 skew)				{ mSkew			= skew;			}
 435
 436	friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params);
 437
 438protected:
 439	// Path params
 440	U8			  mCurveType;
 441	F32           mBegin;
 442	F32           mEnd;
 443	LLVector2	  mScale;
 444	LLVector2     mShear;
 445
 446	F32			  mTwistBegin;
 447	F32			  mTwistEnd;
 448	F32			  mRadiusOffset;
 449	LLVector2	  mTaper;
 450	F32			  mRevolutions;
 451	F32			  mSkew;
 452
 453	U32           mCRC;
 454};
 455
 456inline bool LLPathParams::operator==(const LLPathParams &params) const
 457{
 458	return
 459		(getCurveType() == params.getCurveType()) && 
 460		(getScale() == params.getScale()) &&
 461		(getBegin() == params.getBegin()) && 
 462		(getEnd() == params.getEnd()) && 
 463		(getShear() == params.getShear()) &&
 464		(getTwist() == params.getTwist()) &&
 465		(getTwistBegin() == params.getTwistBegin()) &&
 466		(getRadiusOffset() == params.getRadiusOffset()) &&
 467		(getTaper() == params.getTaper()) &&
 468		(getRevolutions() == params.getRevolutions()) &&
 469		(getSkew() == params.getSkew());
 470}
 471
 472inline bool LLPathParams::operator!=(const LLPathParams &params) const
 473{
 474	return
 475		(getCurveType() != params.getCurveType()) ||
 476		(getScale() != params.getScale()) ||
 477		(getBegin() != params.getBegin()) || 
 478		(getEnd() != params.getEnd()) || 
 479		(getShear() != params.getShear()) ||
 480		(getTwist() != params.getTwist()) ||
 481		(getTwistBegin() !=params.getTwistBegin()) ||
 482		(getRadiusOffset() != params.getRadiusOffset()) ||
 483		(getTaper() != params.getTaper()) ||
 484		(getRevolutions() != params.getRevolutions()) ||
 485		(getSkew() != params.getSkew());
 486}
 487
 488
 489inline bool LLPathParams::operator<(const LLPathParams &params) const
 490{
 491	if( getCurveType() != params.getCurveType()) 
 492	{
 493		return getCurveType() < params.getCurveType();
 494	}
 495	else
 496	if( getScale() != params.getScale()) 
 497	{
 498		return getScale() < params.getScale();
 499	}
 500	else
 501	if( getBegin() != params.getBegin()) 
 502	{
 503		return getBegin() < params.getBegin();
 504	}
 505	else
 506	if( getEnd() != params.getEnd()) 
 507	{
 508		return getEnd() < params.getEnd();
 509	}
 510	else
 511	if( getShear() != params.getShear()) 
 512	{
 513		return getShear() < params.getShear();
 514	}
 515	else
 516	if( getTwist() != params.getTwist())
 517	{
 518		return getTwist() < params.getTwist();
 519	}
 520	else
 521	if( getTwistBegin() != params.getTwistBegin())
 522	{
 523		return getTwistBegin() < params.getTwistBegin();
 524	}
 525	else
 526	if( getRadiusOffset() != params.getRadiusOffset())
 527	{
 528		return getRadiusOffset() < params.getRadiusOffset();
 529	}
 530	else
 531	if( getTaper() != params.getTaper())
 532	{
 533		return getTaper() < params.getTaper();
 534	}
 535	else
 536	if( getRevolutions() != params.getRevolutions())
 537	{
 538		return getRevolutions() < params.getRevolutions();
 539	}
 540	else
 541	{
 542		return getSkew() < params.getSkew();
 543	}
 544}
 545
 546typedef LLVolumeParams* LLVolumeParamsPtr;
 547typedef const LLVolumeParams* const_LLVolumeParamsPtr;
 548
 549class LLVolumeParams
 550{
 551public:
 552	LLVolumeParams()
 553		: mSculptType(LL_SCULPT_TYPE_NONE)
 554	{
 555	}
 556
 557	LLVolumeParams(LLProfileParams &profile, LLPathParams &path,
 558				   LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE)
 559		: mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type)
 560	{
 561	}
 562
 563	bool operator==(const LLVolumeParams &params) const;
 564	bool operator!=(const LLVolumeParams &params) const;
 565	bool operator<(const LLVolumeParams &params) const;
 566
 567
 568	void copyParams(const LLVolumeParams &params);
 569	
 570	const LLProfileParams &getProfileParams() const {return mProfileParams;}
 571	LLProfileParams &getProfileParams() {return mProfileParams;}
 572	const LLPathParams &getPathParams() const {return mPathParams;}
 573	LLPathParams &getPathParams() {return mPathParams;}
 574
 575	BOOL importFile(LLFILE *fp);
 576	BOOL exportFile(LLFILE *fp) const;
 577
 578	BOOL importLegacyStream(std::istream& input_stream);
 579	BOOL exportLegacyStream(std::ostream& output_stream) const;
 580
 581	LLSD sculptAsLLSD() const;
 582	bool sculptFromLLSD(LLSD& sd);
 583	
 584	LLSD asLLSD() const;
 585	operator LLSD() const { return asLLSD(); }
 586	bool fromLLSD(LLSD& sd);
 587
 588	bool setType(U8 profile, U8 path);
 589
 590	//void setBeginS(const F32 beginS)			{ mProfileParams.setBegin(beginS); }	// range 0 to 1
 591	//void setBeginT(const F32 beginT)			{ mPathParams.setBegin(beginT); }		// range 0 to 1
 592	//void setEndS(const F32 endS)				{ mProfileParams.setEnd(endS); }		// range 0 to 1, must be greater than begin
 593	//void setEndT(const F32 endT)				{ mPathParams.setEnd(endT); }			// range 0 to 1, must be greater than begin
 594
 595	bool setBeginAndEndS(const F32 begin, const F32 end);			// both range from 0 to 1, begin must be less than end
 596	bool setBeginAndEndT(const F32 begin, const F32 end);			// both range from 0 to 1, begin must be less than end
 597
 598	bool setHollow(const F32 hollow);	// range 0 to 1
 599	bool setRatio(const F32 x)					{ return setRatio(x,x); }			// 0 = point, 1 = same as base
 600	bool setShear(const F32 x)					{ return setShear(x,x); }			// 0 = no movement, 
 601	bool setRatio(const F32 x, const F32 y);			// 0 = point, 1 = same as base
 602	bool setShear(const F32 x, const F32 y);			// 0 = no movement
 603
 604	bool setTwistBegin(const F32 twist_begin);	// range -1 to 1
 605	bool setTwistEnd(const F32 twist_end);		// range -1 to 1
 606	bool setTwist(const F32 twist)				{ return setTwistEnd(twist); }		// deprecated
 607	bool setTaper(const F32 x, const F32 y)		{ bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; }
 608	bool setTaperX(const F32 v);				// -1 to 1
 609	bool setTaperY(const F32 v);				// -1 to 1
 610	bool setRevolutions(const F32 revolutions);	// 1 to 4
 611	bool setRadiusOffset(const F32 radius_offset);
 612	bool setSkew(const F32 skew);
 613	bool setSculptID(const LLUUID sculpt_id, U8 sculpt_type);
 614
 615	static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow,
 616		U8 path_curve, F32 path_begin, F32 path_end,
 617		F32 scx, F32 scy, F32 shx, F32 shy,
 618		F32 twistend, F32 twistbegin, F32 radiusoffset,
 619		F32 tx, F32 ty, F32 revolutions, F32 skew);
 620	
 621	const F32&  getBeginS() 	const	{ return mProfileParams.getBegin(); }
 622 	const F32&  getBeginT() 	const	{ return mPathParams.getBegin(); }
 623 	const F32&  getEndS() 		const	{ return mProfileParams.getEnd(); }
 624 	const F32&  getEndT() 		const	{ return mPathParams.getEnd(); }
 625 
 626 	const F32&  getHollow() 	const   { return mProfileParams.getHollow(); }
 627 	const F32&  getTwist() 	const   	{ return mPathParams.getTwist(); }
 628 	const F32&  getRatio() 	const		{ return mPathParams.getScaleX(); }
 629 	const F32&  getRatioX() 	const   { return mPathParams.getScaleX(); }
 630 	const F32&  getRatioY() 	const   { return mPathParams.getScaleY(); }
 631 	const F32&  getShearX() 	const   { return mPathParams.getShearX(); }
 632 	const F32&  getShearY() 	const   { return mPathParams.getShearY(); }
 633
 634	const F32&	getTwistBegin()const	{ return mPathParams.getTwistBegin();	}
 635	const F32&  getRadiusOffset() const	{ return mPathParams.getRadiusOffset();	}
 636	const F32&  getTaper() const		{ return mPathParams.getTaperX();		}
 637	const F32&	getTaperX() const		{ return mPathParams.getTaperX();		}
 638	const F32&  getTaperY() const		{ return mPathParams.getTaperY();		}
 639	const F32&  getRevolutions() const	{ return mPathParams.getRevolutions();	}
 640	const F32&  getSkew() const			{ return mPathParams.getSkew();			}
 641	const LLUUID& getSculptID() const	{ return mSculptID;						}
 642	const U8& getSculptType() const     { return mSculptType;                   }
 643	bool isSculpt() const;
 644	bool isMeshSculpt() const;
 645	BOOL isConvex() const;
 646
 647	// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
 648	// (begin, end) = (0, 1) will not change the volume
 649	// (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T)
 650	void reduceS(F32 begin, F32 end);
 651	void reduceT(F32 begin, F32 end);
 652
 653	struct compare
 654	{
 655		bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const
 656		{
 657			return (*first < *second);
 658		}
 659	};
 660	
 661	friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
 662
 663	// debug helper functions
 664	void setCube();
 665
 666protected:
 667	LLProfileParams mProfileParams;
 668	LLPathParams	mPathParams;
 669	LLUUID mSculptID;
 670	U8 mSculptType;
 671};
 672
 673
 674class LLProfile
 675{
 676public:
 677	LLProfile()
 678		: mOpen(FALSE),
 679		  mConcave(FALSE),
 680		  mDirty(TRUE),
 681		  mTotalOut(0),
 682		  mTotal(2)
 683	{
 684	}
 685
 686	~LLProfile();
 687
 688	S32	 getTotal() const								{ return mTotal; }
 689	S32	 getTotalOut() const							{ return mTotalOut; }	// Total number of outside points
 690	BOOL isFlat(S32 face) const							{ return (mFaces[face].mCount == 2); }
 691	BOOL isOpen() const									{ return mOpen; }
 692	void setDirty()										{ mDirty     = TRUE; }
 693
 694	static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
 695				  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 696	BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
 697				  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 698	BOOL isConcave() const								{ return mConcave; }
 699public:
 700	struct Face
 701	{
 702		S32       mIndex;
 703		S32       mCount;
 704		F32       mScaleU;
 705		BOOL      mCap;
 706		BOOL      mFlat;
 707		LLFaceID  mFaceID;
 708	};
 709	
 710	std::vector<LLVector3> mProfile;	
 711	std::vector<LLVector2> mNormals;
 712	std::vector<Face>      mFaces;
 713	std::vector<LLVector3> mEdgeNormals;
 714	std::vector<LLVector3> mEdgeCenters;
 715
 716	friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);
 717
 718protected:
 719	void genNormals(const LLProfileParams& params);
 720	static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
 721	void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
 722
 723	Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
 724	Face* addCap (S16 faceID);
 725	Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat);
 726
 727protected:
 728	BOOL		  mOpen;
 729	BOOL		  mConcave;
 730	BOOL          mDirty;
 731
 732	S32			  mTotalOut;
 733	S32			  mTotal;
 734};
 735
 736//-------------------------------------------------------------------
 737// SWEEP/EXTRUDE PATHS
 738//-------------------------------------------------------------------
 739
 740class LLPath
 741{
 742public:
 743	struct PathPt
 744	{
 745		LLVector3	 mPos;
 746		LLVector2    mScale;
 747		LLQuaternion mRot;
 748		F32			 mTexT;
 749		PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); }
 750	};
 751
 752public:
 753	LLPath()
 754		: mOpen(FALSE),
 755		  mTotal(0),
 756		  mDirty(TRUE),
 757		  mStep(1)
 758	{
 759	}
 760
 761	virtual ~LLPath();
 762
 763	static S32 getNumPoints(const LLPathParams& params, F32 detail);
 764	static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
 765
 766	void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
 767	virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
 768						  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 769
 770	BOOL isOpen() const						{ return mOpen; }
 771	F32 getStep() const						{ return mStep; }
 772	void setDirty()							{ mDirty     = TRUE; }
 773
 774	S32 getPathLength() const				{ return (S32)mPath.size(); }
 775
 776	void resizePath(S32 length) { mPath.resize(length); }
 777
 778	friend std::ostream& operator<<(std::ostream &s, const LLPath &path);
 779
 780public:
 781	std::vector<PathPt> mPath;
 782
 783protected:
 784	BOOL		  mOpen;
 785	S32			  mTotal;
 786	BOOL          mDirty;
 787	F32           mStep;
 788};
 789
 790class LLDynamicPath : public LLPath
 791{
 792public:
 793	LLDynamicPath() : LLPath() { }
 794	/*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
 795							  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 796};
 797
 798// Yet another "face" class - caches volume-specific, but not instance-specific data for faces)
 799class LLVolumeFace
 800{
 801public:
 802	class VertexData
 803	{
 804		enum 
 805		{
 806			POSITION = 0,
 807			NORMAL = 1
 808		};
 809
 810	private:
 811		void init();
 812	public:
 813		VertexData();
 814		VertexData(const VertexData& rhs);
 815		const VertexData& operator=(const VertexData& rhs);
 816
 817		~VertexData();
 818		LLVector4a& getPosition();
 819		LLVector4a& getNormal();
 820		const LLVector4a& getPosition() const;
 821		const LLVector4a& getNormal() const;
 822		void setPosition(const LLVector4a& pos);
 823		void setNormal(const LLVector4a& norm);
 824		
 825
 826		LLVector2 mTexCoord;
 827
 828		bool operator<(const VertexData& rhs) const;
 829		bool operator==(const VertexData& rhs) const;
 830		bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const;
 831
 832	private:
 833		LLVector4a* mData;
 834	};
 835
 836	LLVolumeFace();
 837	LLVolumeFace(const LLVolumeFace& src);
 838	LLVolumeFace& operator=(const LLVolumeFace& rhs);
 839
 840	~LLVolumeFace();
 841private:
 842	void freeData();
 843public:
 844
 845	BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
 846	void createBinormals();
 847	
 848	void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
 849
 850	void resizeVertices(S32 num_verts);
 851	void allocateBinormals(S32 num_verts);
 852	void allocateWeights(S32 num_verts);
 853	void resizeIndices(S32 num_indices);
 854	void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
 855
 856	void pushVertex(const VertexData& cv);
 857	void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc);
 858	void pushIndex(const U16& idx);
 859
 860	void swapData(LLVolumeFace& rhs);
 861
 862	void getVertexData(U16 indx, LLVolumeFace::VertexData& cv);
 863
 864	class VertexMapData : public LLVolumeFace::VertexData
 865	{
 866	public:
 867		U16 mIndex;
 868
 869		bool operator==(const LLVolumeFace::VertexData& rhs) const;
 870
 871		struct ComparePosition
 872		{
 873			bool operator()(const LLVector3& a, const LLVector3& b) const;
 874		};
 875
 876		typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
 877	};
 878
 879	void optimize(F32 angle_cutoff = 2.f);
 880	void cacheOptimize();
 881
 882	void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
 883
 884	enum
 885	{
 886		SINGLE_MASK =	0x0001,
 887		CAP_MASK =		0x0002,
 888		END_MASK =		0x0004,
 889		SIDE_MASK =		0x0008,
 890		INNER_MASK =	0x0010,
 891		OUTER_MASK =	0x0020,
 892		HOLLOW_MASK =	0x0040,
 893		OPEN_MASK =		0x0080,
 894		FLAT_MASK =		0x0100,
 895		TOP_MASK =		0x0200,
 896		BOTTOM_MASK =	0x0400
 897	};
 898	
 899public:
 900	S32 mID;
 901	U32 mTypeMask;
 902	
 903	// Only used for INNER/OUTER faces
 904	S32 mBeginS;
 905	S32 mBeginT;
 906	S32 mNumS;
 907	S32 mNumT;
 908
 909	LLVector4a* mExtents; //minimum and maximum point of face
 910	LLVector4a* mCenter;
 911	LLVector2   mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
 912
 913	S32 mNumVertices;
 914	S32 mNumIndices;
 915
 916	LLVector4a* mPositions;
 917	LLVector4a* mNormals;
 918	LLVector4a* mBinormals;
 919	LLVector2*  mTexCoords;
 920	U16* mIndices;
 921
 922	std::vector<S32>	mEdge;
 923
 924	//list of skin weights for rigged volumes
 925	// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
 926	// mWeights.size() should be empty or match mVertices.size()  
 927	LLVector4a* mWeights;
 928
 929	LLOctreeNode<LLVolumeTriangle>* mOctree;
 930
 931private:
 932	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
 933	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
 934	BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE);
 935};
 936
 937class LLVolume : public LLRefCount
 938{
 939	friend class LLVolumeLODGroup;
 940
 941protected:
 942	~LLVolume(); // use unref
 943
 944public:
 945	struct Point
 946	{
 947		LLVector3 mPos;
 948	};
 949
 950	struct FaceParams
 951	{
 952		LLFaceID mFaceID;
 953		S32 mBeginS;
 954		S32 mCountS;
 955		S32 mBeginT;
 956		S32 mCountT;
 957	};
 958
 959	LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE);
 960	
 961	U8 getProfileType()	const								{ return mParams.getProfileParams().getCurveType(); }
 962	U8 getPathType() const									{ return mParams.getPathParams().getCurveType(); }
 963	S32	getNumFaces() const;
 964	S32 getNumVolumeFaces() const							{ return mVolumeFaces.size(); }
 965	F32 getDetail() const									{ return mDetail; }
 966	const LLVolumeParams& getParams() const					{ return mParams; }
 967	LLVolumeParams getCopyOfParams() const					{ return mParams; }
 968	const LLProfile& getProfile() const						{ return *mProfilep; }
 969	LLPath& getPath() const									{ return *mPathp; }
 970	void resizePath(S32 length);
 971	const std::vector<Point>& getMesh() const				{ return mMesh; }
 972	const LLVector3& getMeshPt(const U32 i) const			{ return mMesh[i].mPos; }
 973
 974	void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
 975
 976	void regen();
 977	void genBinormals(S32 face);
 978
 979	BOOL isConvex() const;
 980	BOOL isCap(S32 face);
 981	BOOL isFlat(S32 face);
 982	BOOL isUnique() const									{ return mUnique; }
 983
 984	S32 getSculptLevel() const                              { return mSculptLevel; }
 985	void setSculptLevel(S32 level)							{ mSculptLevel = level; }
 986
 987	S32 *getTriangleIndices(U32 &num_indices) const;
 988
 989	// returns number of triangle indeces required for path/profile mesh
 990	S32 getNumTriangleIndices() const;
 991	static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
 992
 993	S32 getNumTriangles(S32* vcount = NULL) const;
 994
 995	void generateSilhouetteVertices(std::vector<LLVector3> &vertices, 
 996									std::vector<LLVector3> &normals, 
 997									const LLVector3& view_vec,
 998									const LLMatrix4& mat,
 999									const LLMatrix3& norm_mat,
1000									S32 face_index);
1001
1002	//get the face index of the face that intersects with the given line segment at the point 
1003	//closest to start.  Moves end to the point of intersection.  Returns -1 if no intersection.
1004	//Line segment must be in volume space.
1005	S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
1006							 S32 face = -1,                          // which face to check, -1 = ALL_SIDES
1007							 LLVector3* intersection = NULL,         // return the intersection point
1008							 LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
1009							 LLVector3* normal = NULL,               // return the surface normal at the intersection point
1010							 LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
1011		);
1012
1013	S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, 
1014								   S32 face = 1,
1015								   LLVector3* intersection = NULL,
1016								   LLVector2* tex_coord = NULL,
1017								   LLVector3* normal = NULL,
1018								   LLVector3* bi_normal = NULL);
1019	
1020	// The following cleans up vertices and triangles,
1021	// getting rid of degenerate triangles and duplicate vertices,
1022	// and allocates new arrays with the clean data.
1023	static BOOL cleanupTriangleData( const S32 num_input_vertices,
1024								const std::vector<Point> &input_vertices,
1025								const S32 num_input_triangles,
1026								S32 *input_triangles,
1027								S32 &num_output_vertices,
1028								LLVector3 **output_vertices,
1029								S32 &num_output_triangles,
1030								S32 **output_triangles);
1031	LLFaceID generateFaceMask();
1032
1033	BOOL isFaceMaskValid(LLFaceID face_mask);
1034	static S32 sNumMeshPoints;
1035
1036	friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume);
1037	friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep);		// HACK to bypass Windoze confusion over 
1038																				// conversion if *(LLVolume*) to LLVolume&
1039	const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
1040	
1041	U32					mFaceMask;			// bit array of which faces exist in this volume
1042	LLVector3			mLODScaleBias;		// vector for biasing LOD based on scale
1043	
1044	void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
1045	void copyVolumeFaces(const LLVolume* volume);
1046	void cacheOptimize();
1047
1048private:
1049	void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
1050	F32 sculptGetSurfaceArea();
1051	void sculptGeneratePlaceholder();
1052	void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);
1053
1054	
1055protected:
1056	BOOL generate();
1057	void createVolumeFaces();
1058public:
1059	virtual bool unpackVolumeFaces(std::istream& is, S32 size);
1060
1061	virtual void setMeshAssetLoaded(BOOL loaded);
1062	virtual BOOL isMeshAssetLoaded();
1063
1064 protected:
1065	BOOL mUnique;
1066	F32 mDetail;
1067	S32 mSculptLevel;
1068	BOOL mIsMeshAssetLoaded;
1069	
1070	LLVolumeParams mParams;
1071	LLPath *mPathp;
1072	LLProfile *mProfilep;
1073	std::vector<Point> mMesh;
1074	
1075	BOOL mGenerateSingleFace;
1076	typedef std::vector<LLVolumeFace> face_list_t;
1077	face_list_t mVolumeFaces;
1078
1079public:
1080	LLVector4a* mHullPoints;
1081	U16* mHullIndices;
1082	S32 mNumHullPoints;
1083	S32 mNumHullIndices;
1084};
1085
1086std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
1087
1088void calc_binormal_from_triangle(
1089		LLVector4a& binormal,
1090		const LLVector4a& pos0,
1091		const LLVector2& tex0,
1092		const LLVector4a& pos1,
1093		const LLVector2& tex1,
1094		const LLVector4a& pos2,
1095		const LLVector2& tex2);
1096
1097BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
1098BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
1099BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size);
1100
1101BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
1102							F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided);
1103
1104BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
1105							F32& intersection_a, F32& intersection_b, F32& intersection_t);
1106BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
1107							F32& intersection_a, F32& intersection_b, F32& intersection_t);
1108	
1109	
1110
1111#endif