12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562 |
- /**
- * @file llvolume.h
- * @brief LLVolume base class.
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #ifndef LL_LLVOLUME_H
- #define LL_LLVOLUME_H
- #include <iostream>
- #include <vector>
- #if LL_JEMALLOC
- # include "jemalloc/jemalloc.h"
- # include "hbtracy.h"
- #endif
- #include "llalignedarray.h"
- #include "llcolor4.h"
- #include "llcolor4u.h"
- #include "llfile.h"
- #include "llmath.h"
- #include "llmatrix4a.h"
- #include "llmutex.h"
- #include "llpointer.h"
- #include "llrefcount.h"
- #include "llstrider.h"
- #include "lluuid.h"
- #include "llvector2.h"
- #include "llvector3.h"
- #include "llvector3d.h"
- #include "llvector4.h"
- class LLPath;
- class LLPathParams;
- class LLProfile;
- class LLProfileParams;
- class LLVolume;
- class LLVolumeFace;
- class LLVolumeOctree;
- class LLVolumeParams;
- class LLVolumeTriangle;
- // Define to 1 in case we add support for on-the-wire tangents
- #define LL_USE_TANGENTS 0
- // To reduce the sources verbosity and typing, you may use this macro in the
- // public methods declaration block for classes dealing with volumes. HB
- #define LL_VOLUME_AREANA_NEW_DELETE \
- LL_INLINE void* operator new(size_t size) \
- { return allocate_volume_mem(size); } \
- LL_INLINE void* operator new[](size_t size) \
- { return allocate_volume_mem(size); } \
- LL_INLINE void operator delete(void* ptr) noexcept \
- { free_volume_mem(ptr); } \
- LL_INLINE void operator delete[](void* ptr) noexcept \
- { free_volume_mem(ptr); }
- // Forward declarations
- LL_INLINE void* allocate_volume_mem(size_t size);
- LL_INLINE void free_volume_mem(void* addr) noexcept;
- constexpr S32 MIN_DETAIL_FACES = 6;
- // These are defined here but are not enforced at this level, rather they are
- // here for the convenience of code that uses the LLVolume class.
- constexpr F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f;
- constexpr F32 MIN_VOLUME_PATH_WIDTH = 0.05f;
- constexpr F32 CUT_QUANTA = 0.00002f;
- constexpr F32 SCALE_QUANTA = 0.01f;
- constexpr F32 SHEAR_QUANTA = 0.01f;
- constexpr F32 TAPER_QUANTA = 0.01f;
- constexpr F32 REV_QUANTA = 0.015f;
- constexpr F32 HOLLOW_QUANTA = 0.00002f;
- constexpr S32 MAX_VOLUME_TRIANGLE_INDICES = 10000;
- // Useful masks
- constexpr LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // Has a thickness
- constexpr LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // Segments (1 angle)
- constexpr LLPCode LL_PCODE_PATCH_MASK = 0x20; // Segmented segments (2 angles)
- constexpr LLPCode LL_PCODE_HEMI_MASK = 0x10; // Half-prims get their own type
- constexpr LLPCode LL_PCODE_BASE_MASK = 0x0F;
- // Primitive shapes
- constexpr LLPCode LL_PCODE_CUBE = 1;
- constexpr LLPCode LL_PCODE_PRISM = 2;
- constexpr LLPCode LL_PCODE_TETRAHEDRON = 3;
- constexpr LLPCode LL_PCODE_PYRAMID = 4;
- constexpr LLPCode LL_PCODE_CYLINDER = 5;
- constexpr LLPCode LL_PCODE_CONE = 6;
- constexpr LLPCode LL_PCODE_SPHERE = 7;
- constexpr LLPCode LL_PCODE_TORUS = 8;
- constexpr LLPCode LL_PCODE_VOLUME = 9;
- // Surfaces (deprecated)
- //constexpr LLPCode LL_PCODE_SURFACE_TRIANGLE = 10;
- //constexpr LLPCode LL_PCODE_SURFACE_SQUARE = 11;
- //constexpr LLPCode LL_PCODE_SURFACE_DISC = 12;
- // App specific pcode (for viewer/sim side only objects)
- constexpr LLPCode LL_PCODE_APP = 14;
- constexpr LLPCode LL_PCODE_LEGACY = 15;
- // Pcodes for legacy objects
- constexpr LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY;
- constexpr LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY;
- constexpr LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY;
- constexpr LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY;
- constexpr LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY;
- // Deprecated
- //constexpr LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_SHOT_BIG= 0xB0 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;
- //constexpr LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE= 0xE0 | LL_PCODE_LEGACY;
- // Hemis
- constexpr LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_HEMI_MASK | LL_PCODE_CYLINDER;
- constexpr LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_HEMI_MASK | LL_PCODE_CONE;
- constexpr LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_HEMI_MASK | LL_PCODE_SPHERE;
- constexpr LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_HEMI_MASK | LL_PCODE_TORUS;
- // Volumes consist of a profile at the base that is swept around a path to make
- // a volume.
- // The profile code
- constexpr U8 LL_PCODE_PROFILE_MASK = 0x0f;
- constexpr U8 LL_PCODE_PROFILE_MIN = 0x00;
- constexpr U8 LL_PCODE_PROFILE_CIRCLE = 0x00;
- constexpr U8 LL_PCODE_PROFILE_SQUARE = 0x01;
- constexpr U8 LL_PCODE_PROFILE_ISOTRI = 0x02;
- constexpr U8 LL_PCODE_PROFILE_EQUALTRI = 0x03;
- constexpr U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04;
- constexpr U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05;
- constexpr U8 LL_PCODE_PROFILE_MAX = 0x05;
- // Stored in the profile byte
- constexpr U8 LL_PCODE_HOLE_MASK = 0xf0;
- constexpr U8 LL_PCODE_HOLE_MIN = 0x00;
- constexpr U8 LL_PCODE_HOLE_SAME = 0x00; // Same as outside profile
- constexpr U8 LL_PCODE_HOLE_CIRCLE = 0x10;
- constexpr U8 LL_PCODE_HOLE_SQUARE = 0x20;
- constexpr U8 LL_PCODE_HOLE_TRIANGLE = 0x30;
- constexpr U8 LL_PCODE_HOLE_MAX = 0x03; // Min/max needs to be >> 4 of real min/max
- constexpr U8 LL_PCODE_PATH_IGNORE = 0x00;
- constexpr U8 LL_PCODE_PATH_MIN = 0x01; // Min/max needs to be >> 4 of real min/max
- constexpr U8 LL_PCODE_PATH_LINE = 0x10;
- constexpr U8 LL_PCODE_PATH_CIRCLE = 0x20;
- constexpr U8 LL_PCODE_PATH_CIRCLE2 = 0x30;
- constexpr U8 LL_PCODE_PATH_TEST = 0x40;
- constexpr U8 LL_PCODE_PATH_FLEXIBLE = 0x80;
- constexpr U8 LL_PCODE_PATH_MAX = 0x08;
- // Face identifiers
- typedef U16 LLFaceID;
- constexpr LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0;
- constexpr LLFaceID LL_FACE_PATH_END = 0x1 << 1;
- constexpr LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2;
- constexpr LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3;
- constexpr LLFaceID LL_FACE_PROFILE_END = 0x1 << 4;
- constexpr LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5;
- constexpr LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6;
- constexpr LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7;
- constexpr LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8;
- // Sculpt types + flags
- constexpr U8 LL_SCULPT_TYPE_NONE = 0;
- constexpr U8 LL_SCULPT_TYPE_SPHERE = 1;
- constexpr U8 LL_SCULPT_TYPE_TORUS = 2;
- constexpr U8 LL_SCULPT_TYPE_PLANE = 3;
- constexpr U8 LL_SCULPT_TYPE_CYLINDER = 4;
- constexpr U8 LL_SCULPT_TYPE_MESH = 5;
- constexpr U8 LL_SCULPT_TYPE_GLTF = 6;
- constexpr U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE |
- LL_SCULPT_TYPE_TORUS |
- LL_SCULPT_TYPE_PLANE |
- LL_SCULPT_TYPE_CYLINDER |
- LL_SCULPT_TYPE_MESH |
- LL_SCULPT_TYPE_GLTF;
- // For value checks, assign new value after adding new types
- constexpr U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_GLTF;
- constexpr U8 LL_SCULPT_FLAG_INVERT = 64;
- constexpr U8 LL_SCULPT_FLAG_MIRROR = 128;
- constexpr U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR;
- constexpr S32 LL_SCULPT_MESH_MAX_FACES = 8;
- class LLProfileParams
- {
- protected:
- LOG_CLASS(LLProfileParams);
- public:
- LLProfileParams()
- : mCurveType(LL_PCODE_PROFILE_SQUARE),
- mBegin(0.f),
- mEnd(1.f),
- mHollow(0.f),
- mCRC(0)
- {
- }
- LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow)
- : mCurveType(curve),
- mBegin(begin),
- mEnd(end),
- mHollow(hollow),
- mCRC(0)
- {
- }
- LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow)
- {
- mCurveType = curve;
- F32 temp_f32 = begin * CUT_QUANTA;
- if (temp_f32 > 1.f)
- {
- temp_f32 = 1.f;
- }
- mBegin = temp_f32;
- temp_f32 = end * CUT_QUANTA;
- if (temp_f32 > 1.f)
- {
- temp_f32 = 1.f;
- }
- mEnd = 1.f - temp_f32;
- temp_f32 = hollow * HOLLOW_QUANTA;
- if (temp_f32 > 1.f)
- {
- temp_f32 = 1.f;
- }
- mHollow = temp_f32;
- mCRC = 0;
- }
- bool operator==(const LLProfileParams& params) const;
- bool operator!=(const LLProfileParams& params) const;
- bool operator<(const LLProfileParams& params) const;
- void copyParams(const LLProfileParams& params);
- bool importFile(LLFILE* fp);
- bool exportFile(LLFILE* fp) const;
- bool importLegacyStream(std::istream& input_stream);
- bool exportLegacyStream(std::ostream& output_stream) const;
- LLSD asLLSD() const;
- LL_INLINE operator LLSD() const { return asLLSD(); }
- bool fromLLSD(LLSD& sd);
- LL_INLINE F32 getBegin() const { return mBegin; }
- LL_INLINE F32 getEnd() const { return mEnd; }
- LL_INLINE F32 getHollow() const { return mHollow; }
- LL_INLINE U8 getCurveType() const { return mCurveType; }
- LL_INLINE void setCurveType(U32 type) { mCurveType = type; }
- LL_INLINE void setBegin(F32 begin)
- {
- mBegin = begin >= 1.f ? 0.f : ((S32)(begin * 100000.f)) / 100000.f;
- }
- LL_INLINE void setEnd(F32 end)
- {
- mEnd = end <= 0.f ? 1.f : ((S32)(end * 100000.f)) / 100000.f;
- }
- LL_INLINE void setHollow(F32 hollow)
- {
- mHollow = ((S32)(hollow * 100000.f)) / 100000.f;
- }
- friend std::ostream& operator<<(std::ostream& s,
- const LLProfileParams& profile_params);
- protected:
- // Profile params
- F32 mBegin;
- F32 mEnd;
- F32 mHollow;
- U32 mCRC;
- U8 mCurveType;
- };
- LL_INLINE bool LLProfileParams::operator==(const LLProfileParams& params) const
- {
- return getCurveType() == params.getCurveType() &&
- getBegin() == params.getBegin() &&
- getEnd() == params.getEnd() &&
- getHollow() == params.getHollow();
- }
- LL_INLINE bool LLProfileParams::operator!=(const LLProfileParams& params) const
- {
- return getCurveType() != params.getCurveType() ||
- getBegin() != params.getBegin() ||
- getEnd() != params.getEnd() ||
- getHollow() != params.getHollow();
- }
- LL_INLINE bool LLProfileParams::operator<(const LLProfileParams& params) const
- {
- if (getCurveType() != params.getCurveType())
- {
- return getCurveType() < params.getCurveType();
- }
- if (getBegin() != params.getBegin())
- {
- return getBegin() < params.getBegin();
- }
- if (getEnd() != params.getEnd())
- {
- return getEnd() < params.getEnd();
- }
- return getHollow() < params.getHollow();
- }
- #define U8_TO_F32(x) (F32)(*((S8*)&x))
- class LLPathParams
- {
- protected:
- LOG_CLASS(LLPathParams);
- public:
- LLPathParams()
- : mCurveType(LL_PCODE_PATH_LINE),
- mBegin(0.f),
- mEnd(1.f),
- mScale(1.f, 1.f),
- mShear(0.f, 0.f),
- mTwistBegin(0.f),
- mTwistEnd(0.f),
- mRadiusOffset(0.f),
- mTaper(0.f, 0.f),
- mRevolutions(1.f),
- mSkew(0.f),
- mCRC(0)
- {
- }
- 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)
- : mCurveType(curve),
- mBegin(begin),
- mEnd(end),
- mScale(scx, scy),
- mShear(shx, shy),
- mTwistBegin(twistbegin),
- mTwistEnd(twistend),
- mRadiusOffset(radiusoffset),
- mTaper(tx, ty),
- mRevolutions(revolutions),
- mSkew(skew),
- mCRC(0)
- {
- }
- 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)
- {
- mCurveType = curve;
- mBegin = (F32)(begin * CUT_QUANTA);
- mEnd = (F32)(100.f - end) * CUT_QUANTA;
- if (mEnd > 1.f)
- {
- mEnd = 1.f;
- }
- mScale.set((F32)(200 - scx) * SCALE_QUANTA,
- (F32)(200 - scy) * SCALE_QUANTA);
- mShear.set(U8_TO_F32(shx) * SHEAR_QUANTA,
- U8_TO_F32(shy) * SHEAR_QUANTA);
- mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA;
- mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA;
- mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA;
- mTaper.set(U8_TO_F32(tx) * TAPER_QUANTA,
- U8_TO_F32(ty) * TAPER_QUANTA);
- mRevolutions = (F32)revolutions * REV_QUANTA + 1.f;
- mSkew = U8_TO_F32(skew) * SCALE_QUANTA;
- mCRC = 0;
- }
- bool operator==(const LLPathParams& params) const;
- bool operator!=(const LLPathParams& params) const;
- bool operator<(const LLPathParams& params) const;
- void copyParams(const LLPathParams& params);
- bool importFile(LLFILE* fp);
- bool exportFile(LLFILE* fp) const;
- bool importLegacyStream(std::istream& input_stream);
- bool exportLegacyStream(std::ostream& output_stream) const;
- LLSD asLLSD() const;
- LL_INLINE operator LLSD() const { return asLLSD(); }
- bool fromLLSD(LLSD& sd);
- LL_INLINE F32 getBegin() const { return mBegin; }
- LL_INLINE F32 getEnd() const { return mEnd; }
- LL_INLINE const LLVector2& getScale() const { return mScale; }
- LL_INLINE F32 getScaleX() const { return mScale.mV[0]; }
- LL_INLINE F32 getScaleY() const { return mScale.mV[1]; }
- LLVector2 getBeginScale() const;
- LLVector2 getEndScale() const;
- LL_INLINE const LLVector2& getShear() const { return mShear; }
- LL_INLINE F32 getShearX() const { return mShear.mV[0]; }
- LL_INLINE F32 getShearY() const { return mShear.mV[1]; }
- LL_INLINE U8 getCurveType () const { return mCurveType; }
- LL_INLINE F32 getTwistBegin() const { return mTwistBegin; }
- // Note: getTwist() has been deprecated in favour of getTwistEnd(()
- LL_INLINE F32 getTwistEnd() const { return mTwistEnd; }
- LL_INLINE F32 getRadiusOffset() const { return mRadiusOffset; }
- LL_INLINE const LLVector2& getTaper() const { return mTaper; }
- LL_INLINE F32 getTaperX() const { return mTaper.mV[0]; }
- LL_INLINE F32 getTaperY() const { return mTaper.mV[1]; }
- LL_INLINE F32 getRevolutions() const { return mRevolutions; }
- LL_INLINE F32 getSkew() const { return mSkew; }
- LL_INLINE void setCurveType(U8 type) { mCurveType = type; }
- LL_INLINE void setBegin(F32 begin) { mBegin = begin; }
- LL_INLINE void setEnd(F32 end) { mEnd = end; }
- LL_INLINE void setScale(F32 x, F32 y) { mScale.set(x, y); }
- LL_INLINE void setScaleX(F32 v) { mScale.mV[VX] = v; }
- LL_INLINE void setScaleY(F32 v) { mScale.mV[VY] = v; }
- LL_INLINE void setShear(F32 x, F32 y) { mShear.set(x, y); }
- LL_INLINE void setShearX(F32 v) { mShear.mV[VX] = v; }
- LL_INLINE void setShearY(F32 v) { mShear.mV[VY] = v; }
- LL_INLINE void setTwistBegin(F32 tbegin) { mTwistBegin = tbegin; }
- // Note: setTwist() has been deprecated in favour of setTwistEnd(()
- LL_INLINE void setTwistEnd(F32 tend) { mTwistEnd = tend; }
- LL_INLINE void setRadiusOffset(F32 roff) { mRadiusOffset = roff; }
- LL_INLINE void setTaper(F32 x, F32 y) { mTaper.set(x, y); }
- LL_INLINE void setTaperX(F32 v) { mTaper.mV[VX] = v; }
- LL_INLINE void setTaperY(F32 v) { mTaper.mV[VY] = v; }
- LL_INLINE void setRevolutions(F32 revol) { mRevolutions = revol; }
- LL_INLINE void setSkew(F32 skew) { mSkew = skew; }
- friend std::ostream& operator<<(std::ostream& s,
- const LLPathParams& path_params);
- protected:
- // Path params
- LLVector2 mScale;
- LLVector2 mShear;
- F32 mBegin;
- F32 mEnd;
- LLVector2 mTaper;
- F32 mRevolutions;
- F32 mSkew;
- F32 mTwistBegin;
- F32 mTwistEnd;
- F32 mRadiusOffset;
- U32 mCRC;
- U8 mCurveType;
- };
- LL_INLINE bool LLPathParams::operator==(const LLPathParams& params) const
- {
- return getCurveType() == params.getCurveType() &&
- getScale() == params.getScale() &&
- getBegin() == params.getBegin() &&
- getEnd() == params.getEnd() &&
- getShear() == params.getShear() &&
- getTwistEnd() == params.getTwistEnd() &&
- getTwistBegin() == params.getTwistBegin() &&
- getRadiusOffset() == params.getRadiusOffset() &&
- getTaper() == params.getTaper() &&
- getRevolutions() == params.getRevolutions() &&
- getSkew() == params.getSkew();
- }
- LL_INLINE bool LLPathParams::operator!=(const LLPathParams& params) const
- {
- return getCurveType() != params.getCurveType() ||
- getScale() != params.getScale() ||
- getBegin() != params.getBegin() ||
- getEnd() != params.getEnd() ||
- getShear() != params.getShear() ||
- getTwistEnd() != params.getTwistEnd() ||
- getTwistBegin() !=params.getTwistBegin() ||
- getRadiusOffset() != params.getRadiusOffset() ||
- getTaper() != params.getTaper() ||
- getRevolutions() != params.getRevolutions() ||
- getSkew() != params.getSkew();
- }
- LL_INLINE bool LLPathParams::operator<(const LLPathParams& params) const
- {
- if (getCurveType() != params.getCurveType())
- {
- return getCurveType() < params.getCurveType();
- }
- if (getScale() != params.getScale())
- {
- return getScale() < params.getScale();
- }
- if (getBegin() != params.getBegin())
- {
- return getBegin() < params.getBegin();
- }
- if (getEnd() != params.getEnd())
- {
- return getEnd() < params.getEnd();
- }
- if (getShear() != params.getShear())
- {
- return getShear() < params.getShear();
- }
- if (getTwistEnd() != params.getTwistEnd())
- {
- return getTwistEnd() < params.getTwistEnd();
- }
- if (getTwistBegin() != params.getTwistBegin())
- {
- return getTwistBegin() < params.getTwistBegin();
- }
- if (getRadiusOffset() != params.getRadiusOffset())
- {
- return getRadiusOffset() < params.getRadiusOffset();
- }
- if (getTaper() != params.getTaper())
- {
- return getTaper() < params.getTaper();
- }
- if (getRevolutions() != params.getRevolutions())
- {
- return getRevolutions() < params.getRevolutions();
- }
- return getSkew() < params.getSkew();
- }
- typedef LLVolumeParams* LLVolumeParamsPtr;
- typedef const LLVolumeParams* const_LLVolumeParamsPtr;
- class LLVolumeParams
- {
- protected:
- LOG_CLASS(LLVolumeParams);
- public:
- LLVolumeParams()
- : mSculptType(LL_SCULPT_TYPE_NONE)
- {
- }
- LLVolumeParams(LLProfileParams& profile, LLPathParams& path,
- LLUUID sculpt_id = LLUUID::null,
- U8 sculpt_type = LL_SCULPT_TYPE_NONE)
- : mProfileParams(profile),
- mPathParams(path),
- mSculptID(sculpt_id),
- mSculptType(sculpt_type)
- {
- }
- bool operator==(const LLVolumeParams& params) const;
- bool operator!=(const LLVolumeParams& params) const;
- bool operator<(const LLVolumeParams& params) const;
- void copyParams(const LLVolumeParams& params);
- LL_INLINE const LLProfileParams& getProfileParams() const
- {
- return mProfileParams;
- }
- LL_INLINE LLProfileParams& getProfileParams() { return mProfileParams; }
- LL_INLINE const LLPathParams& getPathParams() const { return mPathParams; }
- LL_INLINE LLPathParams& getPathParams() { return mPathParams; }
- bool importFile(LLFILE* fp);
- bool exportFile(LLFILE* fp) const;
- bool importLegacyStream(std::istream& input_stream);
- bool exportLegacyStream(std::ostream& output_stream) const;
- LLSD sculptAsLLSD() const;
- bool sculptFromLLSD(LLSD& sd);
- LLSD asLLSD() const;
- LL_INLINE operator LLSD() const { return asLLSD(); }
- bool fromLLSD(LLSD& sd);
- bool setType(U8 profile, U8 path);
- // Both range from 0 to 1, begin must be less than end
- bool setBeginAndEndS(F32 begin, F32 end);
- bool setBeginAndEndT(F32 begin, F32 end);
- bool setHollow(F32 hollow); // Range 0 to 1
- // 0 = point, 1 = same as base
- LL_INLINE bool setRatio(F32 x) { return setRatio(x, x); }
- // 0 = no movement,
- LL_INLINE bool setShear(F32 x) { return setShear(x, x); }
- bool setRatio(F32 x, F32 y); // 0 = point, 1 = same as base
- bool setShear(F32 x, F32 y); // 0 = no movement
- bool setTwistBegin(F32 twist_begin); // Range -1 to 1
- bool setTwistEnd(F32 twist_end); // Range -1 to 1
- LL_INLINE bool setTaper(F32 x, F32 y)
- {
- bool pass_x = setTaperX(x);
- bool pass_y = setTaperY(y);
- return pass_x && pass_y;
- }
- bool setTaperX(F32 v); // -1 to 1
- bool setTaperY(F32 v); // -1 to 1
- bool setRevolutions(F32 revolutions); // 1 to 4
- bool setRadiusOffset(F32 radius_offset);
- bool setSkew(F32 skew);
- bool setSculptID(const LLUUID& sculpt_id, U8 sculpt_type);
- static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end,
- F32 hollow,
- U8 path_curve, F32 path_begin, F32 path_end,
- F32 scx, F32 scy, F32 shx, F32 shy,
- F32 twistend, F32 twistbegin, F32 radiusoffset,
- F32 tx, F32 ty, F32 revolutions, F32 skew);
- LL_INLINE F32 getBeginS() const { return mProfileParams.getBegin(); }
- LL_INLINE F32 getBeginT() const { return mPathParams.getBegin(); }
- LL_INLINE F32 getEndS() const { return mProfileParams.getEnd(); }
- LL_INLINE F32 getEndT() const { return mPathParams.getEnd(); }
- LL_INLINE F32 getHollow() const { return mProfileParams.getHollow(); }
- LL_INLINE F32 getRatio() const { return mPathParams.getScaleX(); }
- LL_INLINE F32 getRatioX() const { return mPathParams.getScaleX(); }
- LL_INLINE F32 getRatioY() const { return mPathParams.getScaleY(); }
- LL_INLINE F32 getShearX() const { return mPathParams.getShearX(); }
- LL_INLINE F32 getShearY() const { return mPathParams.getShearY(); }
- LL_INLINE F32 getTwistBegin()const { return mPathParams.getTwistBegin(); }
- // Note: getTwist() has been deprecated in favour of getTwistEnd(()
- LL_INLINE F32 getTwistEnd() const { return mPathParams.getTwistEnd(); }
- LL_INLINE F32 getRadiusOffset() const { return mPathParams.getRadiusOffset(); }
- LL_INLINE F32 getTaper() const { return mPathParams.getTaperX(); }
- LL_INLINE F32 getTaperX() const { return mPathParams.getTaperX(); }
- LL_INLINE F32 getTaperY() const { return mPathParams.getTaperY(); }
- LL_INLINE F32 getRevolutions() const { return mPathParams.getRevolutions(); }
- LL_INLINE F32 getSkew() const { return mPathParams.getSkew(); }
- LL_INLINE const LLUUID& getSculptID() const { return mSculptID; }
- LL_INLINE U8 getSculptType() const { return mSculptType; }
- LL_INLINE bool isSculpt() const
- {
- return (mSculptType & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_NONE;
- }
- LL_INLINE bool isMeshSculpt() const
- {
- return (mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH;
- }
- bool isConvex() const;
- // 'begin' and 'end' should be in range [0, 1] (they will be clamped)
- // (begin, end) = (0, 1) will not change the volume
- // (begin, end) = (0, 0.5) will reduce the volume to the first half of its
- // profile/path (S/T)
- void reduceS(F32 begin, F32 end);
- void reduceT(F32 begin, F32 end);
- struct compare
- {
- LL_INLINE bool operator()(const const_LLVolumeParamsPtr& first,
- const const_LLVolumeParamsPtr& second) const
- {
- return *first < *second;
- }
- };
- friend std::ostream& operator<<(std::ostream& s,
- const LLVolumeParams& volume_params);
- // debug helper functions
- void setCube();
- protected:
- LLUUID mSculptID;
- LLProfileParams mProfileParams;
- // Note: LLProfileParams ends with an U8, so let's use the aligmenent gap with
- // another U8, at least... HB
- U8 mSculptType;
- LLPathParams mPathParams;
- };
- class LLProfile
- {
- protected:
- LOG_CLASS(LLProfile);
- public:
- LLProfile()
- : mOpen(false),
- mConcave(false),
- mDirty(true),
- mTotalOut(0),
- mTotal(2)
- {
- }
- LL_INLINE S32 getTotal() const { return mTotal; }
- // Total number of outside points:
- LL_INLINE S32 getTotalOut() const { return mTotalOut; }
- LL_INLINE bool isFlat(S32 face) const { return mFaces[face].mCount == 2; }
- LL_INLINE bool isOpen() const { return mOpen; }
- LL_INLINE bool isConcave() const { return mConcave; }
- LL_INLINE void setDirty() { mDirty = true; }
- static S32 getNumPoints(const LLProfileParams& params, bool path_open,
- F32 detail = 1.f, S32 split = 0,
- bool is_sculpted = false, S32 sculpt_size = 0);
- bool generate(const LLProfileParams& params, bool path_open,
- F32 detail = 1.f, S32 split = 0,
- bool is_sculpted = false, S32 sculpt_size = 0);
- friend std::ostream& operator<<(std::ostream& s, const LLProfile& profile);
- struct Face
- {
- LLFaceID mFaceID;
- S32 mIndex;
- S32 mCount;
- F32 mScaleU;
- bool mCap;
- bool mFlat;
- };
- protected:
- static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides,
- F32 ang_scale = 1.f, S32 split = 0);
- void genNGon(const LLProfileParams& params, S32 sides, F32 offset = 0.f,
- F32 ang_scale = 1.f, S32 split = 0);
- Face* addHole(const LLProfileParams& params, bool flat, F32 sides,
- F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
- Face* addCap(S16 face_id);
- Face* addFace(S32 index, S32 count, F32 u_scale, S16 face_id, bool flat);
- public:
- LLAlignedArray<LLVector4a, 64> mVertices;
- std::vector<Face> mFaces;
- protected:
- LLMutex mMutex;
- S32 mTotalOut;
- S32 mTotal;
- bool mOpen;
- bool mConcave;
- bool mDirty;
- };
- //-------------------------------------------------------------------
- // SWEEP/EXTRUDE PATHS
- //-------------------------------------------------------------------
- class LLPath
- {
- protected:
- LOG_CLASS(LLPath);
- public:
- #if LL_JEMALLOC
- // LLPath does not need to be 16-byte aligned but benefits from arenas
- LL_VOLUME_AREANA_NEW_DELETE
- #endif
- class alignas(16) PathPt
- {
- public:
- LLMatrix4a mRot;
- LLVector4a mPos;
- LLVector4a mScale;
- F32 mTexT;
- F32 pad[3]; // For alignment
- PathPt()
- {
- mPos.clear();
- mTexT = 0;
- mScale.clear();
- mRot.setRows(LLVector4a(1, 0, 0, 0), LLVector4a(0, 1, 0, 0),
- LLVector4a(0, 0, 1, 0));
- // Distinguished data in the pad for debugging
- pad[0] = F_PI;
- pad[1] = -F_PI;
- pad[2] = 0.585f;
- }
- };
- public:
- LLPath()
- : mOpen(false),
- mTotal(0),
- mDirty(true),
- mStep(1.f)
- {
- }
- virtual ~LLPath() = default;
- static S32 getNumPoints(const LLPathParams& params, F32 detail);
- static S32 getNumNGonPoints(const LLPathParams& params, S32 sides);
- void genNGon(const LLPathParams& params, S32 sides, F32 end_scale = 1.f,
- F32 twist_scale = 1.f);
- virtual bool generate(const LLPathParams& params, F32 detail = 1.f,
- S32 split = 0,
- bool is_sculpted = false, S32 sculpt_size = 0);
- LL_INLINE bool isOpen() const { return mOpen; }
- LL_INLINE F32 getStep() const { return mStep; }
- LL_INLINE void setDirty() { mDirty = true; }
- LL_INLINE S32 getPathLength() const { return (S32)mPath.size(); }
- LL_INLINE void resizePath(S32 length) { mPath.resize(length); }
- friend std::ostream& operator<<(std::ostream& s, const LLPath& path);
- protected:
- S32 mTotal;
- F32 mStep;
- bool mOpen;
- bool mDirty;
- public:
- LLAlignedArray<PathPt, 64> mPath;
- };
- class LLDynamicPath : public LLPath
- {
- protected:
- LOG_CLASS(LLDynamicPath);
- public:
- bool generate(const LLPathParams& params, F32 detail = 1.f, S32 split = 0,
- bool is_sculpted = false, S32 sculpt_size = 0) override;
- };
- // ----------------------------------------------------------------------------
- // LLJointRiggingInfo class.
- // Stores information related to associated rigged mesh vertices.
- // ----------------------------------------------------------------------------
- class alignas(16) LLJointRiggingInfo
- {
- public:
- LL_VOLUME_AREANA_NEW_DELETE
- LLJointRiggingInfo();
- LL_INLINE LLVector4a* getRiggedExtents() { return mRiggedExtents; }
- LL_INLINE const LLVector4a* getRiggedExtents() const
- {
- return mRiggedExtents;
- }
- LL_INLINE void setIsRiggedTo(bool val = true) { mIsRiggedTo = val; }
- LL_INLINE bool isRiggedTo() const { return mIsRiggedTo; }
- void merge(const LLJointRiggingInfo& other);
- private:
- alignas(16) LLVector4a mRiggedExtents[2];
- bool mIsRiggedTo;
- };
- // ----------------------------------------------------------------------------
- // LLJointRiggingInfoTab class.
- // For storing all the rigging info associated with a given avatar or object,
- // keyed by joint_key.
- // ----------------------------------------------------------------------------
- class LLJointRiggingInfoTab
- {
- public:
- #if LL_JEMALLOC
- // LLJointRiggingInfoTab does not need to be 16-byte aligned but benefits
- // from arenas
- LL_VOLUME_AREANA_NEW_DELETE
- #endif
- LLJointRiggingInfoTab();
- ~LLJointRiggingInfoTab();
- void clear();
- void resize(U32 size);
- LL_INLINE U32 size() const { return mSize; }
- void merge(const LLJointRiggingInfoTab& src);
- LL_INLINE LLJointRiggingInfo& operator[](S32 i) { return mRigInfoPtr[i]; }
- LL_INLINE const LLJointRiggingInfo& operator[](S32 i) const
- {
- return mRigInfoPtr[i];
- }
- LL_INLINE bool needsUpdate() { return mNeedsUpdate; }
- LL_INLINE void setNeedsUpdate(bool val = true) { mNeedsUpdate = val; }
- private:
- // Not implemented, on purpose.
- LLJointRiggingInfoTab& operator=(const LLJointRiggingInfoTab& src);
- LLJointRiggingInfoTab(const LLJointRiggingInfoTab& src);
- private:
- LLJointRiggingInfo* mRigInfoPtr;
- U32 mSize;
- bool mNeedsUpdate;
- };
- // ----------------------------------------------------------------------------
- // LLVolumeFace class.
- // Yet another "face" class - caches volume-specific, but not instance-specific
- // data for faces)
- // ----------------------------------------------------------------------------
- class LLVolumeFace
- {
- protected:
- LOG_CLASS(LLVolumeFace);
- public:
- #if LL_JEMALLOC
- // LLVolumeFace does not need to be 16-byte aligned but benefits from
- // arenas
- LL_VOLUME_AREANA_NEW_DELETE
- #endif
- class VertexData
- {
- private:
- enum
- {
- POSITION = 0,
- NORMAL = 1
- };
- void init();
- public:
- LL_INLINE VertexData() { mData = NULL; init(); }
- LL_INLINE VertexData(const VertexData& rhs) { mData = NULL; *this = rhs; }
- const VertexData& operator=(const VertexData& rhs);
- ~VertexData();
- LL_INLINE LLVector4a& getPosition() { return mData[POSITION]; }
- LL_INLINE LLVector4a& getNormal() { return mData[NORMAL]; }
- LL_INLINE const LLVector4a& getPosition() const { return mData[POSITION]; }
- LL_INLINE const LLVector4a& getNormal() const { return mData[NORMAL]; }
- LL_INLINE void setPosition(const LLVector4a& p) { mData[POSITION] = p; }
- LL_INLINE void setNormal(const LLVector4a& n) { mData[NORMAL] = n; }
- LLVector2 mTexCoord;
- bool operator<(const VertexData& rhs) const;
- LL_INLINE bool operator==(const VertexData& rhs) const;
- bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const;
- private:
- LLVector4a* mData;
- };
- LLVolumeFace();
- LLVolumeFace(const LLVolumeFace& src);
- LLVolumeFace& operator=(const LLVolumeFace& rhs);
- ~LLVolumeFace();
- static void initClass();
- bool create(LLVolume* volume, bool partial_build = false);
- void createTangents();
- bool resizeVertices(S32 num_verts);
- bool allocateTangents(S32 num_verts);
- bool allocateWeights(S32 num_verts);
- bool resizeIndices(S32 num_indices);
- void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v,
- std::vector<U16>& idx);
- // Note: max_indice is the number of indices in the unoptimized face
- void pushVertex(const VertexData& cv, S32 max_indice);
- void pushVertex(const LLVector4a& pos, const LLVector4a& norm,
- const LLVector2& tc, S32 max_indice);
- void pushIndex(const U16& idx);
- void swapData(LLVolumeFace& rhs);
- void getVertexData(U16 indx, LLVolumeFace::VertexData& cv);
- class VertexMapData : public LLVolumeFace::VertexData
- {
- public:
- bool operator==(const LLVolumeFace::VertexData& rhs) const;
- struct ComparePosition
- {
- bool operator()(const LLVector3& a, const LLVector3& b) const;
- };
- typedef std::map<LLVector3, std::vector<VertexMapData>,
- VertexMapData::ComparePosition> PointMap;
- public:
- U16 mIndex;
- };
- // Used to be a validate_face(const LLVolumeFace& face) global function in
- // llmodel.h. HB
- bool validate(bool check_nans = false) const;
- // Used to be a ll_is_degenerate() global function in llmodel.h. HB
- static bool isDegenerate(const LLVector4a& a, const LLVector4a& b,
- const LLVector4a& c);
- // Eliminates non unique triangles, taking positions, normals and texture
- // coordinates into account.
- void remap();
- void optimize(F32 angle_cutoff = 2.f);
- bool cacheOptimize(bool gen_tangents = false);
- void createOctree(F32 scaler = 0.25f,
- const LLVector4a& center = LLVector4a(0.f, 0.f, 0.f),
- const LLVector4a& size = LLVector4a(0.5f, 0.5f, 0.5f));
- enum
- {
- SINGLE_MASK = 0x0001,
- CAP_MASK = 0x0002,
- END_MASK = 0x0004,
- SIDE_MASK = 0x0008,
- INNER_MASK = 0x0010,
- OUTER_MASK = 0x0020,
- HOLLOW_MASK = 0x0040,
- OPEN_MASK = 0x0080,
- FLAT_MASK = 0x0100,
- TOP_MASK = 0x0200,
- BOTTOM_MASK = 0x0400
- };
- void destroyOctree();
- #if LL_JEMALLOC
- LL_INLINE static U32 getMallocxFlags16() { return sMallocxFlags16; }
- LL_INLINE static U32 getMallocxFlags64() { return sMallocxFlags64; }
- #endif
- private:
- void freeData();
- bool createUnCutCubeCap(LLVolume* volume, bool partial_build = false);
- bool createCap(LLVolume* volume, bool partial_build = false);
- bool createSide(LLVolume* volume, bool partial_build = false);
- private:
- #if LL_JEMALLOC
- static U32 sMallocxFlags16;
- static U32 sMallocxFlags64;
- #endif
- // NOTE: some of the member variables below would better be private, but
- // this would forbid using the offsetof() macro on LLVolumeFace (gcc error
- // "'offsetof' within non-standard-layout type 'LLVolumeFace' is
- // conditionally-supported"), and we do need the latter... HB
- public:
- // This octree stores raw pointer references to triangles in
- // mOctreeTriangles
- LLVolumeOctree* mOctree;
- LLVolumeTriangle* mOctreeTriangles;
- // List of skin weights for rigged volumes. Format is:
- // mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
- // mWeights.size() should be empty or match mVertices.size()
- LLVector4a* mWeights;
- std::vector<S32> mEdge;
- LLJointRiggingInfoTab mJointRiggingInfoTab;
- // If this is a mesh asset, scale and translation that were applied when
- // encoding the source mesh into a unit cube used for regenerating tangents
- LLVector3 mNormalizedScale;
- // Minimum and maximum of texture coordinates of the face:
- LLVector2 mTexCoordExtents[2];
- // Minimum and maximum point of face:
- LLVector4a* mExtents;
- LLVector4a* mCenter;
- // mPositions contains vertices, normals and texcoords
- LLVector4a* mPositions;
- LLVector4a* mNormals;
- LLVector4a* mTangents;
- // Pointer into mPositions
- LLVector2* mTexCoords;
- // mIndices contains mNumIndices amount of elements. It contains triangles,
- // each 3 indices describe one triangle.
- // If mIndices contains {0, 2, 3, 1, 2, 4}, it means there are 2 triangles
- // {0, 2, 3} and {1, 2, 4} with values being indexes for mPositions,
- // mNormals, mTexCoords.
- U16* mIndices;
- S32 mID;
- U32 mTypeMask;
- // Only used for INNER/OUTER faces
- S32 mBeginS;
- S32 mBeginT;
- S32 mNumS;
- S32 mNumT;
- // mNumVertices == num vertices == num normals == num texcoords
- S32 mNumVertices;
- S32 mNumAllocatedVertices;
- S32 mNumIndices;
- mutable bool mWeightsScrubbed;
- // Whether or not face has been cache optimized
- bool mOptimized;
- };
- LL_INLINE bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs) const
- {
- return mData[POSITION].equals3(rhs.getPosition()) &&
- mData[NORMAL].equals3(rhs.getNormal()) &&
- mTexCoord == rhs.mTexCoord;
- }
- class LLVolume : public LLRefCount
- {
- friend class LLVolumeLODGroup;
- protected:
- LOG_CLASS(LLVolume);
- ~LLVolume() override; // Uses unref
- public:
- #if LL_JEMALLOC
- // LLVolume does not need to be 16-byte aligned but benefits from arenas
- LL_VOLUME_AREANA_NEW_DELETE
- #endif
- typedef std::vector<LLVolumeFace> face_list_t;
- struct FaceParams
- {
- LLFaceID mFaceID;
- S32 mBeginS;
- S32 mCountS;
- S32 mBeginT;
- S32 mCountT;
- };
- LLVolume(const LLVolumeParams& params, F32 detail,
- bool generate_single_face = false, bool is_unique = false);
- LL_INLINE U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); }
- LL_INLINE U8 getPathType() const { return mParams.getPathParams().getCurveType(); }
- LL_INLINE S32 getNumFaces() const
- {
- return mIsMeshAssetLoaded ? getNumVolumeFaces()
- : (S32)mProfile.mFaces.size();
- }
- LL_INLINE S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
- LL_INLINE F32 getDetail() const { return mDetail; }
- LL_INLINE F32 getSurfaceArea() const { return mSurfaceArea; }
- LL_INLINE const LLVolumeParams& getParams() const { return mParams; }
- LL_INLINE LLVolumeParams getCopyOfParams() const { return mParams; }
- LL_INLINE const LLProfile& getProfile() const { return mProfile; }
- LL_INLINE LLPath& getPath() const { return *mPathp; }
- void resizePath(S32 length);
- LL_INLINE const LLAlignedArray<LLVector4a, 64>& getMesh() const
- {
- return mMesh;
- }
- LL_INLINE const LLVector4a& getMeshPt(U32 i) const
- {
- return mMesh[i];
- }
- LL_INLINE void setDirty()
- {
- mPathp->setDirty();
- mProfile.setDirty();
- }
- void regen();
- void genTangents(S32 face);
- // mParams.isConvex() may return false even though the final geometry is
- // actually convex due to LOD approximations.
- // *TODO: provide LLPath and LLProfile with isConvex() methods that
- // correctly determine convexity. -- Leviathan
- LL_INLINE bool isConvex() const { return mParams.isConvex(); }
- LL_INLINE bool isCap(S32 face) { return mProfile.mFaces[face].mCap; }
- LL_INLINE bool isFlat(S32 face) { return mProfile.mFaces[face].mFlat; }
- LL_INLINE bool isUnique() const { return mUnique; }
- LL_INLINE S32 getSculptLevel() const { return mSculptLevel; }
- LL_INLINE void setSculptLevel(S32 level) { mSculptLevel = level; }
- void getLoDTriangleCounts(S32* counts);
- S32 getNumTriangles(S32* vcount = NULL) const;
- void generateSilhouetteVertices(std::vector<LLVector3>& vertices,
- std::vector<LLVector3>& normals,
- const LLVector3& view_vec,
- const LLMatrix4& mat,
- const LLMatrix3& norm_mat,
- S32 face_index);
- // Gets the face index of the face that intersects with the given line
- // segment at the point closest to start. Moves end to the point of
- // intersection. Returns -1 if no intersection. Line segment must be in
- // volume space.
- S32 lineSegmentIntersect(const LLVector4a& start,
- const LLVector4a& end,
- // Which face to check, -1 = ALL_SIDES
- S32 face = -1,
- // Returns the intersection point
- LLVector4a* intersection = NULL,
- // Returns the texture coordinates at intersection
- LLVector2* tex_coord = NULL,
- // Returns the surface normal at intersection
- LLVector4a* normal = NULL,
- // Returns the surface tangent at intersection
- LLVector4a* tangent = NULL);
- LLFaceID generateFaceMask();
- bool isFaceMaskValid(LLFaceID face_mask);
- friend std::ostream& operator<<(std::ostream& s, const LLVolume& volume);
- // *HACK to bypass Windoze confusion over conversion if *(LLVolume*) to
- // LLVolume&
- friend std::ostream& operator<<(std::ostream& s, const LLVolume* volumep);
- // ------------------------------------------------------------------------
- // DO NOT DELETE VOLUME WHILE USING THESE REFERENCES, OR HOLD A POINTER TO
- // THESE VOLUMEFACES
- LL_INLINE const LLVolumeFace& getVolumeFace(S32 f) const
- {
- return mVolumeFaces[f];
- }
- LL_INLINE LLVolumeFace& getVolumeFace(S32 f)
- {
- return mVolumeFaces[f];
- }
- LL_INLINE face_list_t& getVolumeFaces() { return mVolumeFaces; }
- // ------------------------------------------------------------------------
- void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
- const U8* sculpt_data, S32 sculpt_level,
- bool visible_placeholder = false);
- LL_INLINE void copyFacesTo(std::vector<LLVolumeFace>& faces) const
- {
- faces = mVolumeFaces;
- }
- LL_INLINE void copyFacesFrom(const std::vector<LLVolumeFace>& faces)
- {
- mVolumeFaces = faces;
- mSculptLevel = 0;
- }
- LL_INLINE void copyVolumeFaces(const LLVolume* volume)
- {
- if (volume)
- {
- mVolumeFaces = volume->mVolumeFaces;
- mSculptLevel = 0;
- }
- }
- bool cacheOptimize(bool gen_tangents = false);
- bool unpackVolumeFaces(std::istream& is, S32 size);
- bool unpackVolumeFaces(const U8* in, S32 size);
- LL_INLINE void setMeshAssetLoaded(bool b) { mIsMeshAssetLoaded = b; }
- LL_INLINE bool isMeshAssetLoaded() { return mIsMeshAssetLoaded; }
- protected:
- bool generate();
- void createVolumeFaces();
- private:
- bool unpackVolumeFaces(const LLSD& mdl);
- void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height,
- S8 sculpt_components, const U8* sculpt_data,
- U8 sculpt_type);
- F32 sculptGetSurfaceArea();
- void sculptGenerateEmptyPlaceholder();
- void sculptGenerateSpherePlaceholder();
- void sculptCalcMeshResolution(U16 width, U16 height, U8 type,
- S32& s, S32& t);
- protected:
- // Note: before these variables, we find the 32 bits counter from
- // LLRefCount... HB
- F32 mDetail;
- S32 mSculptLevel;
- F32 mSurfaceArea; // Unscaled surface area
- LLPath* mPathp;
- const LLVolumeParams mParams;
- LLProfile mProfile;
- LLAlignedArray<LLVector4a, 64> mMesh;
- face_list_t mVolumeFaces;
- struct TrianglesPerLODCache
- {
- LLProfileParams mProfileParams;
- LLPathParams mPathParams;
- S32 mTriangles[4];
- };
- TrianglesPerLODCache* mTrianglesCache;
- bool mUnique;
- bool mGenerateSingleFace;
- bool mIsMeshAssetLoaded;
- public:
- // Bit array of which faces exist in this volume
- U32 mFaceMask;
- // Vector for biasing LOD based on scale
- LLVector3 mLODScaleBias;
- LLVector4a* mHullPoints;
- U16* mHullIndices;
- S32 mNumHullPoints;
- S32 mNumHullIndices;
- static U32 sLODCacheHit;
- static U32 sLODCacheMiss;
- static S32 sNumMeshPoints;
- static bool sOptimizeCache;
- };
- std::ostream& operator<<(std::ostream& s, const LLVolumeParams& volume_params);
- bool calculate_tangent_array(const U32 vertex_count, const LLVector4a* vertp,
- const LLVector4a* normp, const LLVector2* tcoordp,
- U32 triangle_count, const U16* indexp,
- LLVector4a* tangentp);
- bool LLLineSegmentBoxIntersect(const F32* start, const F32* end,
- const F32* center, const F32* size);
- bool LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end,
- const LLVector3& center, const LLVector3& size);
- bool LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end,
- const LLVector4a& center, const LLVector4a& size);
- #if 0
- bool LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1,
- const LLVector3& vert2, const LLVector3& orig,
- const LLVector3& dir,
- F32& intersection_a, F32& intersection_b,
- F32& intersection_t, bool two_sided);
- #endif
- bool LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1,
- const LLVector4a& vert2, const LLVector4a& orig,
- const LLVector4a& dir,
- F32& intersection_a, F32& intersection_b,
- F32& intersection_t);
- bool LLTriangleRayIntersectTwoSided(const LLVector4a& vert0,
- const LLVector4a& vert1,
- const LLVector4a& vert2,
- const LLVector4a& orig,
- const LLVector4a& dir,
- F32& intersection_a,
- F32& intersection_b,
- F32& intersection_t);
- F32 LLTriangleClosestPoint(const LLVector3& vert0, const LLVector3& vert1,
- const LLVector3& vert2, const LLVector3& target,
- F32& closest_a, F32& closest_b);
- // NOTE: since the memory functions below use void* pointers instead of char*
- // (because void* is the type used by malloc and jemalloc), strict aliasing is
- // not possible on structures allocated with them. Make sure you forbid your
- // compiler to optimize with strict aliasing assumption (i.e. for gcc, DO use
- // the -fno-strict-aliasing option) !
- LL_INLINE void* allocate_volume_mem(size_t size)
- {
- if (LL_UNLIKELY(size <= 0)) return NULL;
- void* addr;
- #if LL_JEMALLOC
- addr = mallocx(size, LLVolumeFace::getMallocxFlags16());
- LL_TRACY_ALLOC(addr, size, trc_mem_volume);
- #else
- addr = ll_aligned_malloc_16(size);
- #endif
- if (LL_UNLIKELY(addr == NULL))
- {
- LLMemory::allocationFailed(size);
- }
- return addr;
- }
- LL_INLINE void free_volume_mem(void* addr) noexcept
- {
- if (LL_UNLIKELY(addr == NULL)) return;
- #if LL_JEMALLOC
- LL_TRACY_FREE(addr, trc_mem_volume);
- dallocx(addr, 0);
- #else
- ll_aligned_free_16(addr);
- #endif
- }
- LL_INLINE void* realloc_volume_mem(void* ptr, size_t size, size_t old_size)
- {
- if (LL_UNLIKELY(size <= 0))
- {
- free_volume_mem(ptr);
- return NULL;
- }
- if (LL_UNLIKELY(ptr == NULL))
- {
- return allocate_volume_mem(size);
- }
- #if LL_JEMALLOC
- LL_TRACY_FREE(ptr, trc_mem_volume);
- void* addr = rallocx(ptr, size, LLVolumeFace::getMallocxFlags16());
- if (LL_UNLIKELY(addr == NULL))
- {
- LLMemory::allocationFailed(size);
- }
- LL_TRACY_ALLOC(addr, size, trc_mem_volume);
- return addr;
- #else
- return ll_aligned_realloc_16(ptr, size, old_size);
- #endif
- }
- LL_INLINE void* allocate_volume_mem_64(size_t size)
- {
- if (LL_UNLIKELY(size <= 0)) return NULL;
- void* addr;
- #if LL_JEMALLOC
- addr = mallocx(size, LLVolumeFace::getMallocxFlags64());
- LL_TRACY_ALLOC(addr, size, trc_mem_volume64);
- #else
- addr = ll_aligned_malloc(size, 64);
- #endif
- if (LL_UNLIKELY(addr == NULL))
- {
- LLMemory::allocationFailed(size);
- }
- return addr;
- }
- LL_INLINE void free_volume_mem_64(void* addr) noexcept
- {
- if (LL_LIKELY(addr))
- {
- #if LL_JEMALLOC
- LL_TRACY_FREE(addr, trc_mem_volume64);
- dallocx(addr, 0);
- #else
- ll_aligned_free(addr);
- #endif
- }
- }
- #endif
|