llfloatermodelpreview.cpp 194 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367
  1. /**
  2. * @file llfloatermodelpreview.cpp
  3. * @brief LLFloaterModelPreview class implementation
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2010, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "boost/algorithm/string.hpp"
  34. #include "tinygltf/tiny_gltf.h"
  35. #include "llfloatermodelpreview.h"
  36. #include "llanimationstates.h"
  37. #include "llbutton.h"
  38. #include "llcallbacklist.h"
  39. #include "llcheckboxctrl.h"
  40. #include "llcombobox.h"
  41. #include "llcorehttputil.h"
  42. #include "lldaeloader.h"
  43. #include "lldir.h"
  44. #include "hbfileselector.h"
  45. #include "llgltfloader.h"
  46. #include "lliconctrl.h"
  47. #include "llimagegl.h"
  48. #include "lljoint.h"
  49. #include "llmatrix4a.h"
  50. #include "llmeshoptimizer.h"
  51. #include "llnotifications.h"
  52. #include "llrender.h"
  53. #include "llscrolllistctrl.h"
  54. #include "llsdserialize.h"
  55. #include "llsdutil_math.h"
  56. #include "llsliderctrl.h"
  57. #include "llspinctrl.h"
  58. #include "lltabcontainer.h"
  59. #include "lltextbox.h"
  60. #include "lltexteditor.h"
  61. #include "lluictrlfactory.h"
  62. // Do not move upwards because conflicting definitions in that header !
  63. #include "glod/glod.h"
  64. #include "llagent.h"
  65. #include "lldrawable.h"
  66. #include "llface.h"
  67. #include "llgridmanager.h"
  68. #include "llmanipscale.h"
  69. #include "llpipeline.h"
  70. #include "llskinningutil.h"
  71. #include "lltoolmgr.h"
  72. #include "llviewercamera.h"
  73. #include "llviewercontrol.h"
  74. #include "llviewerobjectlist.h"
  75. #include "llviewershadermgr.h"
  76. #include "llviewerregion.h"
  77. #include "llviewertexturelist.h"
  78. #include "llviewerwindow.h"
  79. #include "llvoavatarself.h"
  80. #include "llweb.h"
  81. //static
  82. S32 LLFloaterModelPreview::sUploadAmount = 10;
  83. static const LLColor4 PREVIEW_CANVAS_COL(0.169f, 0.169f, 0.169f, 1.f);
  84. static const LLColor4 PREVIEW_EDGE_COL(0.4f, 0.4f, 0.4f, 1.0);
  85. static const LLColor4 PREVIEW_BASE_COL(1.f, 1.f, 1.f, 1.f);
  86. static const LLColor3 PREVIEW_BRIGHTNESS(0.9f, 0.9f, 0.9f);
  87. static const LLColor4 PREVIEW_PHYS_EDGE_COL(0.f, 0.25f, 0.5f, 0.25f);
  88. static const LLColor4 PREVIEW_PHYS_FILL_COL(0.f, 0.5f, 1.0f, 0.5f);
  89. static const LLColor4 PREVIEW_DEG_EDGE_COL(1.f, 0.f, 0.f, 1.f);
  90. static const LLColor4 PREVIEW_DEG_FILL_COL(1.f, 0.f, 0.f, 0.5f);
  91. // Note: this name must match the name of the physics shape found in
  92. // app_settings/meshes/cube.dae
  93. static const std::string DEFAULT_PHYSICS_MESH_NAME = "default_physics_shape";
  94. constexpr F32 PREVIEW_DEG_EDGE_WIDTH = 3.f;
  95. constexpr F32 PREVIEW_DEG_POINT_SIZE = 8.f;
  96. constexpr F32 PREVIEW_ZOOM_LIMIT = 20.f;
  97. constexpr U32 LIMIT_TRIANGLES = 0;
  98. // "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01
  99. // But according to the UI spec for upload model floater, this parameter
  100. // should be represented by Retain spinner with values from 1 to 100 by 1.
  101. // To achieve this, RETAIN_COEFFICIENT is used while creating spinner
  102. // and when value is requested from spinner.
  103. constexpr double RETAIN_COEFFICIENT = 100;
  104. // "Cosine%" decomp parameter has values from 0.9 to 1 by 0.001
  105. // But according to the UI spec for upload model floater, this parameter
  106. // should be represented by Smooth combobox with only 10 values.
  107. // So this const is used as a size of Smooth combobox list.
  108. constexpr S32 SMOOTH_VALUES_NUMBER = 10;
  109. // mCameraDistance. Also see: mCameraZoom
  110. constexpr F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f;
  111. const std::string lod_name[NUM_LOD + 1] =
  112. {
  113. "lowest",
  114. "low",
  115. "medium",
  116. "high",
  117. "Went off the end of the lod_name array."
  118. };
  119. const char* lod_triangles_name[NUM_LOD + 1] =
  120. {
  121. "lowest_triangles",
  122. "low_triangles",
  123. "medium_triangles",
  124. "high_triangles",
  125. "Went off the end of the lod_triangles_name array."
  126. };
  127. const char* lod_vertices_name[NUM_LOD + 1] =
  128. {
  129. "lowest_vertices",
  130. "low_vertices",
  131. "medium_vertices",
  132. "high_vertices",
  133. "Went off the end of the lod_vertices_name array."
  134. };
  135. const char* lod_status_name[NUM_LOD + 1] =
  136. {
  137. "lowest_status",
  138. "low_status",
  139. "medium_status",
  140. "high_status",
  141. "Went off the end of the lod_status_name array."
  142. };
  143. const char* lod_icon_name[NUM_LOD + 1] =
  144. {
  145. "status_icon_lowest",
  146. "status_icon_low",
  147. "status_icon_medium",
  148. "status_icon_high",
  149. "Went off the end of the lod_icon_name array."
  150. };
  151. const char* lod_status_image[NUM_LOD + 1] =
  152. {
  153. "green_checkmark.png",
  154. "lag_status_warning.tga",
  155. "red_x.png",
  156. "Went off the end of the lod_status_image array."
  157. };
  158. const char* lod_label_name[NUM_LOD + 1] =
  159. {
  160. "lowest_label",
  161. "low_label",
  162. "medium_label",
  163. "high_label",
  164. "Went off the end of the lod_label_name array."
  165. };
  166. static bool sHasGlodError = false;
  167. static bool stop_gloderror(const char* comment = NULL)
  168. {
  169. GLuint error = glodGetError();
  170. if (error != GLOD_NO_ERROR)
  171. {
  172. llwarns << "GLOD error " << std::hex << error << std::dec << ". "
  173. << (comment ? comment : "") << llendl;
  174. // Do not set the error flag when this is just a "clear GLOD errors"
  175. // call (i.e. a call without any comment). HB
  176. sHasGlodError = comment != NULL;
  177. return true;
  178. }
  179. return false;
  180. }
  181. static void model_error(const char* message)
  182. {
  183. LLSD args;
  184. args["MESSAGE"] = LLSD::String(message);
  185. gNotifications.add("GenericAlert", args);
  186. }
  187. static LLViewerFetchedTexture* bind_mat_diffuse_tex(const LLImportMaterial& mat)
  188. {
  189. LLViewerFetchedTexture* texp =
  190. LLViewerTextureManager::getFetchedTexture(mat.getDiffuseMap(),
  191. FTT_DEFAULT, true,
  192. LLGLTexture::BOOST_PREVIEW);
  193. if (texp && texp->getDiscardLevel() > -1)
  194. {
  195. gGL.getTexUnit(0)->bind(texp);
  196. return texp;
  197. }
  198. return NULL;
  199. }
  200. static std::string strip_lod_suffix(std::string name)
  201. {
  202. if (name.find("_LOD") != std::string::npos ||
  203. name.find("_PHYS") != std::string::npos)
  204. {
  205. return name.substr(0, name.rfind('_'));
  206. }
  207. return name;
  208. }
  209. static std::string get_lod_suffix(S32 lod)
  210. {
  211. std::string suffix;
  212. switch (lod)
  213. {
  214. case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break;
  215. case LLModel::LOD_LOW: suffix = "_LOD1"; break;
  216. case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break;
  217. case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break;
  218. case LLModel::LOD_HIGH: break;
  219. }
  220. return suffix;
  221. }
  222. static void find_model(LLModelLoader::scene& scene,
  223. const std::string& name_to_match,
  224. LLModel*& base_model_out, LLMatrix4& mat_out)
  225. {
  226. for (LLModelLoader::scene::iterator scene_it = scene.begin(),
  227. base_end = scene.end();
  228. scene_it != base_end; ++scene_it)
  229. {
  230. mat_out = scene_it->first;
  231. for (LLModelLoader::model_instance_list_t::iterator
  232. it = scene_it->second.begin(), end = scene_it->second.end();
  233. it != end; ++it)
  234. {
  235. LLModelInstance& base_instance = *it;
  236. LLModel* base_model = base_instance.mModel;
  237. if (base_model && base_model->mLabel == name_to_match)
  238. {
  239. base_model_out = base_model;
  240. return;
  241. }
  242. }
  243. }
  244. }
  245. //-----------------------------------------------------------------------------
  246. // LLFloaterModelUploadBase()
  247. //-----------------------------------------------------------------------------
  248. LLFloaterModelUploadBase::LLFloaterModelUploadBase()
  249. : mHasUploadPerm(false)
  250. {
  251. }
  252. void LLFloaterModelUploadBase::requestAgentUploadPermissions()
  253. {
  254. const std::string& url = gAgent.getRegionCapability("MeshUploadFlag");
  255. if (url.empty())
  256. {
  257. LLSD args;
  258. args["CAPABILITY"] = "MeshUploadFlag";
  259. gNotifications.add("RegionCapabilityRequestError", args);
  260. // *HACK: avoid being blocked by broken server side stuff
  261. mHasUploadPerm = true;
  262. return;
  263. }
  264. llinfos << "Requesting upload model permissions from: " << url
  265. << llendl;
  266. gCoros.launch("LLFloaterModelUploadBase::requestUploadPermCoro",
  267. boost::bind(&LLFloaterModelUploadBase::requestUploadPermCoro,
  268. this, url, getPermObserverHandle()));
  269. }
  270. void LLFloaterModelUploadBase::requestUploadPermCoro(std::string url,
  271. LLHandle<LLUploadPermissionsObserver> handle)
  272. {
  273. LLCoreHttpUtil::HttpCoroutineAdapter adapter("MeshUploadFlag");
  274. LLSD result = adapter.getAndSuspend(url);
  275. LLUploadPermissionsObserver* observer = handle.get();
  276. if (!observer)
  277. {
  278. llwarns << "Unable to get observer after call to '" << url
  279. << "' aborting." << llendl;
  280. return;
  281. }
  282. LLCore::HttpStatus status =
  283. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  284. if (status)
  285. {
  286. LL_DEBUGS("MeshUpload") << "Upload permissions received, calling observer."
  287. << LL_ENDL;
  288. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  289. observer->onPermissionsReceived(result);
  290. }
  291. else
  292. {
  293. LL_DEBUGS("MeshUpload") << "Upload permissions error received, calling observer."
  294. << LL_ENDL;
  295. observer->setPermissonsErrorStatus(status.getStatus(),
  296. status.getMessage());
  297. }
  298. }
  299. //-----------------------------------------------------------------------------
  300. // LLFloaterModelPreview()
  301. //-----------------------------------------------------------------------------
  302. LLFloaterModelPreview::LLFloaterModelPreview(const LLSD&)
  303. : LLFloaterModelUploadBase(),
  304. mModelPreview(NULL),
  305. mStatusLock(new LLMutex()),
  306. mLibIsHACD(false),
  307. mSentFeeRequest(false),
  308. mSentUploadRequest(false),
  309. mLastMouseX(0),
  310. mLastMouseY(0)
  311. {
  312. mLODMode[LLModel::LOD_HIGH] = LLModelPreview::LOD_FROM_FILE;
  313. for (U32 i = 0; i < LLModel::LOD_HIGH; ++i)
  314. {
  315. mLODMode[i] = LLModelPreview::GENERATE;
  316. }
  317. if (!gIsInSecondLife)
  318. {
  319. // Let's point to a known valid website page for OpenSim grids...
  320. LLGridManager* gm = LLGridManager::getInstance();
  321. mValidateURL = gm->getAccountURL(); // Sounds a reasonable default...
  322. if (mValidateURL.empty())
  323. {
  324. // Then try support
  325. mValidateURL = gm->getSupportURL();
  326. if (mValidateURL.empty())
  327. {
  328. // Then try website
  329. mValidateURL = gm->getWebsiteURL();
  330. if (mValidateURL.empty())
  331. {
  332. // Last chance !
  333. mValidateURL = gm->getLoginPageURI();
  334. }
  335. }
  336. }
  337. }
  338. else if (gIsInProductionGrid)
  339. {
  340. mValidateURL = AGNI_VALIDATE_MESH_UPLOAD_PAGE_URL;
  341. }
  342. else
  343. {
  344. mValidateURL = ADITI_VALIDATE_MESH_UPLOAD_PAGE_URL;
  345. }
  346. LLUICtrlFactory::getInstance()->buildFloater(this,
  347. "floater_model_preview.xml",
  348. NULL,
  349. false); // Do not open now
  350. }
  351. bool LLFloaterModelPreview::postBuild()
  352. {
  353. if (!LLFloater::postBuild())
  354. {
  355. return false;
  356. }
  357. mTabContainer = getChild<LLTabContainer>("import_tab");
  358. LLPanel* tabp = mTabContainer->getChild<LLPanel>("lod_panel");
  359. mTabContainer->setTabChangeCallback(tabp, onTabChanged);
  360. mTabContainer->setTabUserData(tabp, this);
  361. tabp = mTabContainer->getChild<LLPanel>("physics_panel");
  362. mTabContainer->setTabChangeCallback(tabp, onTabChanged);
  363. mTabContainer->setTabUserData(tabp, this);
  364. mModifiersPanel = mTabContainer->getChild<LLPanel>("modifiers_panel");
  365. mTabContainer->setTabChangeCallback(mModifiersPanel, onTabChanged);
  366. mTabContainer->setTabUserData(mModifiersPanel, this);
  367. mConflictsText =
  368. mModifiersPanel->getChild<LLTextBox>("conflicts_description");
  369. mOverridesLabel =
  370. mModifiersPanel->getChild<LLTextBox>("position_overrides_label");
  371. mJointsList = mModifiersPanel->getChild<LLScrollListCtrl>("joints_list");
  372. mJointsList->setCommitOnSelectionChange(true);
  373. mJointsList->setCommitCallback(onJointListSelection);
  374. mJointsList->setCallbackUserData(this);
  375. mJointsOverrides =
  376. mModifiersPanel->getChild<LLScrollListCtrl>("overrides_list");
  377. clearSkinningInfo();
  378. mLogPanel = mTabContainer->getChild<LLPanel>("log_panel");
  379. mTabContainer->setTabChangeCallback(mLogPanel, onTabChanged);
  380. mTabContainer->setTabUserData(mLogPanel, this);
  381. childSetCommitCallback("crease_angle", onGenerateNormalsCommit, this);
  382. childSetCommitCallback("gen_normals", toggleGenerateNormals, this);
  383. LLComboBox* lod_source_combo;
  384. std::string lodstr, widget_name;
  385. for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
  386. {
  387. lodstr = lod_name[lod];
  388. widget_name = "lod_source_" + lodstr;
  389. lod_source_combo = getChild<LLComboBox>(widget_name.c_str());
  390. lod_source_combo->setCommitCallback(onLoDSourceCommit);
  391. lod_source_combo->setCallbackUserData((void*)(intptr_t)lod);
  392. lod_source_combo->setCurrentByIndex(mLODMode[lod]);
  393. widget_name = "lod_browse_" + lodstr;
  394. childSetAction(widget_name.c_str(), onBrowseLOD,
  395. // *HACK: lod + 1 to avoid passing a NULL user data,
  396. // that causes to skip setting the callback data.
  397. (void*)(intptr_t)(lod + 1));
  398. widget_name = "lod_mode_" + lodstr;
  399. childSetCommitCallback(widget_name.c_str(), onLODParamCommit,
  400. (void*)(intptr_t)lod);
  401. widget_name = "lod_error_threshold_" + lodstr;
  402. childSetCommitCallback(widget_name.c_str(), onLODParamCommit,
  403. (void*)(intptr_t)lod);
  404. widget_name = "lod_triangle_limit_" + lodstr;
  405. childSetCommitCallback(widget_name.c_str(),
  406. onLODParamCommitEnforceTriLimit,
  407. (void*)(intptr_t)lod);
  408. }
  409. childSetTextArg("status", "[STATUS]", "");
  410. childSetValue("physics_status_message_text", "");
  411. mUploadBtn = getChild<LLButton>("ok_btn");
  412. mUploadBtn->setClickedCallback(onUpload, this);
  413. mUploadBtn->setEnabled(false);
  414. childSetAction("reset_btn", onReset, this);
  415. childSetAction("cancel_btn", onCancel, this);
  416. childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);
  417. childSetCommitCallback("upload_skin", onUploadSkinCommit, this);
  418. childSetCommitCallback("upload_joints", onUploadJointsCommit, this);
  419. childSetCommitCallback("lock_scale_if_joint_position",
  420. onUploadJointsCommit, this);
  421. childSetCommitCallback("upload_textures", toggleCalculateButtonCallBack,
  422. this);
  423. childSetCommitCallback("import_scale", onImportScaleCommit, this);
  424. childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
  425. childSetCommitCallback("show_edges", onViewOptionChecked, this);
  426. childSetCommitCallback("show_physics", onViewOptionChecked, this);
  427. childSetCommitCallback("show_textures", onViewOptionChecked, this);
  428. childSetCommitCallback("show_skin_weight", onViewOptionChecked, this);
  429. childSetCommitCallback("show_joint_overrides", onViewOptionChecked, this);
  430. childSetCommitCallback("show_joint_positions", onViewOptionChecked, this);
  431. childSetCommitCallback("show_collision_volumes", onViewOptionChecked, this);
  432. childDisable("upload_skin");
  433. childDisable("upload_joints");
  434. childDisable("lock_scale_if_joint_position");
  435. initDecompControls();
  436. LLView* preview_panel = getChild<LLView>("preview_panel");
  437. mPreviewRect = preview_panel->getRect();
  438. initModelPreview();
  439. // Set callbacks for left click on line editor rows
  440. for (U32 i = 0; i <= LLModel::LOD_HIGH; ++i)
  441. {
  442. LLTextBox* text = getChild<LLTextBox>(lod_label_name[i]);
  443. if (text)
  444. {
  445. text->setClickedCallback(onClickTextLOD, (void*)(intptr_t)i);
  446. }
  447. text = getChild<LLTextBox>(lod_triangles_name[i]);
  448. if (text)
  449. {
  450. text->setClickedCallback(onClickTextLOD, (void*)(intptr_t)i);
  451. }
  452. text = getChild<LLTextBox>(lod_vertices_name[i]);
  453. if (text)
  454. {
  455. text->setClickedCallback(onClickTextLOD, (void*)(intptr_t)i);
  456. }
  457. text = getChild<LLTextBox>(lod_status_name[i]);
  458. if (text)
  459. {
  460. text->setClickedCallback(onClickTextLOD, (void*)(intptr_t)i);
  461. }
  462. }
  463. mUploadLogText = getChild<LLTextEditor>("log_text");
  464. LLTextBox* warning = getChild<LLTextBox>("validate_url");
  465. warning->setClickedCallback(onClickValidateURL, this);
  466. mCalculateBtn = getChild<LLButton>("calculate_btn");
  467. mCalculateBtn->setClickedCallback(onClickCalculateBtn, this);
  468. toggleCalculateButton(true);
  469. return true;
  470. }
  471. LLFloaterModelPreview::~LLFloaterModelPreview()
  472. {
  473. if (mModelPreview)
  474. {
  475. delete mModelPreview;
  476. mModelPreview = NULL;
  477. }
  478. delete mStatusLock;
  479. mStatusLock = NULL;
  480. }
  481. void LLFloaterModelPreview::initModelPreview()
  482. {
  483. if (mModelPreview)
  484. {
  485. delete mModelPreview;
  486. }
  487. mModelPreview = new LLModelPreview(512, 512, this);
  488. mModelPreview->setPreviewTarget(SKIN_WEIGHT_CAMERA_DISTANCE);
  489. mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails,
  490. this, _1, _2, _3));
  491. mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated,
  492. this, _1));
  493. }
  494. void LLFloaterModelPreview::onViewOptionChecked(LLUICtrl* ctrl, void* userdata)
  495. {
  496. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  497. if (!self) return;
  498. LLModelPreview* mp = self->mModelPreview;
  499. if (mp)
  500. {
  501. const std::string& name = ctrl->getName();
  502. bool new_value = !mp->mViewOption[name];
  503. mp->mViewOption[name] = new_value;
  504. if (new_value)
  505. {
  506. // Cannot display both physics and skin weights... HB
  507. if (name == "show_physics")
  508. {
  509. self->childSetValue("show_skin_weight", false);
  510. mp->mViewOption["show_skin_weight"] = false;
  511. }
  512. else if (name == "show_skin_weight")
  513. {
  514. self->childSetValue("show_physics", false);
  515. mp->mViewOption["show_physics"] = false;
  516. }
  517. }
  518. mp->refresh();
  519. }
  520. }
  521. bool LLFloaterModelPreview::isViewOptionChecked(const LLSD& userdata)
  522. {
  523. return mModelPreview && mModelPreview->mViewOption[userdata.asString()];
  524. }
  525. bool LLFloaterModelPreview::isViewOptionEnabled(const LLSD& userdata)
  526. {
  527. return childIsEnabled(userdata.asString().c_str());
  528. }
  529. void LLFloaterModelPreview::setViewOptionEnabled(const char* option,
  530. bool enabled)
  531. {
  532. childSetEnabled(option, enabled);
  533. }
  534. void LLFloaterModelPreview::enableViewOption(const char* option)
  535. {
  536. setViewOptionEnabled(option, true);
  537. }
  538. void LLFloaterModelPreview::disableViewOption(const char* option)
  539. {
  540. setViewOptionEnabled(option, false);
  541. }
  542. struct LLMeshFileSelectorData
  543. {
  544. LLModelPreview* mMP;
  545. S32 mLOD;
  546. };
  547. void model_load_callback(HBFileSelector::ELoadFilter type,
  548. std::string& filename, void* user_data)
  549. {
  550. LLMeshFileSelectorData* data = (LLMeshFileSelectorData*)user_data;
  551. if (data)
  552. {
  553. data->mMP->loadModel(filename, data->mLOD);
  554. delete data;
  555. }
  556. }
  557. bool LLFloaterModelPreview::prepareToLoadModel(S32 lod)
  558. {
  559. if (!mModelPreview)
  560. {
  561. return false;
  562. }
  563. mModelPreview->mLoading = true;
  564. if (lod == LLModel::LOD_PHYSICS)
  565. {
  566. // Loading physics from file
  567. mModelPreview->mPhysicsSearchLOD = lod;
  568. mModelPreview->mWarnPhysModel = false;
  569. }
  570. return true;
  571. }
  572. void LLFloaterModelPreview::loadModel(S32 lod)
  573. {
  574. if (!prepareToLoadModel(lod))
  575. {
  576. return;
  577. }
  578. LLMeshFileSelectorData* data = new LLMeshFileSelectorData;
  579. data->mMP = mModelPreview;
  580. data->mLOD = lod;
  581. HBFileSelector::loadFile(HBFileSelector::FFLOAD_MODEL, model_load_callback,
  582. data);
  583. }
  584. void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name,
  585. bool force_disable_slm)
  586. {
  587. if (prepareToLoadModel(lod))
  588. {
  589. mModelPreview->loadModel(file_name, lod, force_disable_slm);
  590. }
  591. }
  592. //static
  593. LLModelPreview* LLFloaterModelPreview::getModelPreview()
  594. {
  595. LLModelPreview* preview = NULL;
  596. LLFloaterModelPreview* self = findInstance();
  597. if (self)
  598. {
  599. preview = self->mModelPreview;
  600. }
  601. return preview;
  602. }
  603. //static
  604. void LLFloaterModelPreview::onTabChanged(void* userdata, bool)
  605. {
  606. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  607. if (self && self->mTabContainer->getCurrentPanel() == self->mLogPanel)
  608. {
  609. self->mTabContainer->setTabPanelFlashing(self->mLogPanel, false);
  610. }
  611. }
  612. //static
  613. void LLFloaterModelPreview::onClickCalculateBtn(void* userdata)
  614. {
  615. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  616. if (!self || !self->mModelPreview) return;
  617. self->clearLog();
  618. self->mSentFeeRequest = true;
  619. self->mModelPreview->rebuildUploadData();
  620. bool upload_skinweights = self->childGetValue("upload_skin").asBoolean();
  621. bool upload_joint_pos = self->childGetValue("upload_joints").asBoolean();
  622. bool lock_scale_if_joint_pos =
  623. self->childGetValue("lock_scale_if_joint_position").asBoolean();
  624. self->mUploadModelUrl.clear();
  625. self->mModelPhysicsFee.clear();
  626. gMeshRepo.uploadModel(self->mModelPreview->mUploadData,
  627. self->mModelPreview->mPreviewScale,
  628. self->childGetValue("upload_textures").asBoolean(),
  629. upload_skinweights, upload_joint_pos,
  630. lock_scale_if_joint_pos, self->mUploadModelUrl,
  631. false, self->getWholeModelFeeObserverHandle());
  632. self->toggleCalculateButton(false);
  633. self->mUploadBtn->setEnabled(false);
  634. }
  635. //static
  636. void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*, void* userdata)
  637. {
  638. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  639. if (self && self->mModelPreview)
  640. {
  641. self->mModelPreview->mDirty = true;
  642. self->toggleCalculateButton(true);
  643. self->mModelPreview->refresh();
  644. }
  645. }
  646. //static
  647. void LLFloaterModelPreview::onPelvisOffsetCommit(LLUICtrl*, void* userdata)
  648. {
  649. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  650. if (self && self->mModelPreview)
  651. {
  652. self->mModelPreview->mDirty = true;
  653. self->toggleCalculateButton(true);
  654. self->mModelPreview->refresh();
  655. }
  656. }
  657. //static
  658. void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*, void* userdata)
  659. {
  660. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  661. if (self && self->mModelPreview)
  662. {
  663. self->mModelPreview->refresh();
  664. }
  665. }
  666. //static
  667. void LLFloaterModelPreview::onUploadSkinCommit(LLUICtrl*, void* userdata)
  668. {
  669. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  670. if (self && self->mModelPreview)
  671. {
  672. self->mModelPreview->refresh();
  673. self->mModelPreview->resetPreviewTarget();
  674. self->mModelPreview->clearBuffers();
  675. }
  676. }
  677. //static
  678. void LLFloaterModelPreview::onClickTextLOD(void* userdata)
  679. {
  680. LLFloaterModelPreview* self = findInstance();
  681. if (self && self->mModelPreview)
  682. {
  683. S32 lod = (S32)(intptr_t)userdata;
  684. self->mModelPreview->setPreviewLOD(lod);
  685. }
  686. }
  687. //static
  688. void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata)
  689. {
  690. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  691. if (self && ctrl && self->mModelPreview)
  692. {
  693. LLComboBox* combo = (LLComboBox*)ctrl;
  694. // Combo box list of lods is in reverse order
  695. S32 which_mode = NUM_LOD - 1 - combo->getFirstSelectedIndex();
  696. self->mModelPreview->setPreviewLOD(which_mode);
  697. }
  698. }
  699. //static
  700. void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl*, void* userdata)
  701. {
  702. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  703. if (self && self->mModelPreview)
  704. {
  705. self->mModelPreview->generateNormals();
  706. }
  707. }
  708. //static
  709. void LLFloaterModelPreview::toggleGenerateNormals(LLUICtrl*, void* userdata)
  710. {
  711. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  712. if (self && self->mModelPreview)
  713. {
  714. bool enabled = self->childGetValue("gen_normals").asBoolean();
  715. self->childSetEnabled("crease_label", enabled);
  716. self->childSetEnabled("crease_angle", enabled);
  717. if (enabled)
  718. {
  719. self->mModelPreview->generateNormals();
  720. }
  721. else
  722. {
  723. self->mModelPreview->restoreNormals();
  724. }
  725. }
  726. }
  727. //static
  728. void LLFloaterModelPreview::onExplodeCommit(LLUICtrl*, void* userdata)
  729. {
  730. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  731. if (self && self->mModelPreview)
  732. {
  733. self->mModelPreview->refresh();
  734. }
  735. }
  736. //static
  737. void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl*, void* userdata)
  738. {
  739. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  740. if (self && self->mModelPreview)
  741. {
  742. self->mModelPreview->queryLODs();
  743. }
  744. }
  745. //static
  746. void LLFloaterModelPreview::onLODParamCommit(LLUICtrl*, void* userdata)
  747. {
  748. LLFloaterModelPreview* self = findInstance();
  749. if (self && self->mModelPreview)
  750. {
  751. S32 lod = (S32)(intptr_t)userdata;
  752. self->mModelPreview->onLODParamCommit(lod, false);
  753. // Refresh LoDs that reference this one
  754. std::string cname;
  755. for (S32 i = lod - 1; i >= 0; --i)
  756. {
  757. cname = "lod_source_" + lod_name[i];
  758. LLComboBox* lod_combo = self->getChild<LLComboBox>(cname.c_str());
  759. if (lod_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE)
  760. {
  761. onLoDSourceCommit(NULL, (void*)(intptr_t)i);
  762. }
  763. else
  764. {
  765. break;
  766. }
  767. }
  768. }
  769. }
  770. //static
  771. void LLFloaterModelPreview::onLODParamCommitEnforceTriLimit(LLUICtrl*,
  772. void* userdata)
  773. {
  774. LLFloaterModelPreview* self = findInstance();
  775. if (self && self->mModelPreview)
  776. {
  777. S32 lod = (S32)(intptr_t)userdata;
  778. self->mModelPreview->onLODParamCommit(lod, true);
  779. // Refresh LoDs that reference this one
  780. std::string cname;
  781. for (S32 i = lod - 1; i >= 0; --i)
  782. {
  783. cname = "lod_source_" + lod_name[i];
  784. LLComboBox* lod_combo = self->getChild<LLComboBox>(cname.c_str());
  785. if (lod_combo->getCurrentIndex() != LLModelPreview::USE_LOD_ABOVE)
  786. {
  787. break;
  788. }
  789. onLoDSourceCommit(NULL, (void*)(intptr_t)i);
  790. }
  791. }
  792. }
  793. //virtual
  794. void LLFloaterModelPreview::draw()
  795. {
  796. LLFloater::draw();
  797. if (!mModelPreview) return;
  798. mModelPreview->update();
  799. if (!mModelPreview->mLoading)
  800. {
  801. if (mSentFeeRequest)
  802. {
  803. childSetTextArg("status", "[STATUS]",
  804. getString("status_waiting_server"));
  805. }
  806. else if (mSentUploadRequest)
  807. {
  808. childSetTextArg("status", "[STATUS]",
  809. getString("status_uploading"));
  810. }
  811. else if (mModelPreview->mLoadState == LLModelLoader::ERROR_MATERIALS)
  812. {
  813. childSetTextArg("status", "[STATUS]",
  814. getString("mesh_status_invalid_material_list"));
  815. }
  816. else if (mModelPreview->mLoadState > LLModelLoader::ERROR_MODEL)
  817. {
  818. childSetTextArg("status", "[STATUS]",
  819. getString(LLModel::getStatusString(mModelPreview->mLoadState -
  820. LLModelLoader::ERROR_MODEL)));
  821. }
  822. else if (mModelPreview->mLoadState == LLModelLoader::ERROR_PARSING)
  823. {
  824. childSetTextArg("status", "[STATUS]",
  825. getString("status_parse_error"));
  826. toggleCalculateButton(false);
  827. }
  828. else if (mModelPreview->mLoadState ==
  829. LLModelLoader::ERROR_HIGH_LOD_MODEL_MISSING)
  830. {
  831. childSetTextArg("status", "[STATUS]",
  832. getString("status_high_lod_model_missing"));
  833. toggleCalculateButton(false);
  834. }
  835. else if (mModelPreview->mLoadState ==
  836. LLModelLoader::ERROR_LOD_MODEL_MISMATCH)
  837. {
  838. childSetTextArg("status", "[STATUS]",
  839. getString("status_lod_model_mismatch"));
  840. toggleCalculateButton(false);
  841. }
  842. else if (mModelPreview->mLoadState ==
  843. LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION)
  844. {
  845. childSetTextArg("status", "[STATUS]",
  846. getString("status_bind_shape_orientation"));
  847. }
  848. else
  849. {
  850. childSetTextArg("status", "[STATUS]", "");
  851. }
  852. }
  853. if (!mModelPreview->lodsReady())
  854. {
  855. return;
  856. }
  857. gGL.color3f(1.f, 1.f, 1.f);
  858. LLTexUnit* unit0 = gGL.getTexUnit(0);
  859. unit0->bind(mModelPreview);
  860. LLView* preview_panel = getChild<LLView>("preview_panel");
  861. LLRect rect = preview_panel->getRect();
  862. if (rect != mPreviewRect)
  863. {
  864. mModelPreview->refresh();
  865. mPreviewRect = preview_panel->getRect();
  866. }
  867. gGL.begin(LLRender::TRIANGLES);
  868. {
  869. gGL.texCoord2f(0.f, 1.f);
  870. gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop - 1);
  871. gGL.texCoord2f(0.f, 0.f);
  872. gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom);
  873. gGL.texCoord2f(1.f, 0.f);
  874. gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mBottom);
  875. gGL.texCoord2f(0.f, 1.f);
  876. gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop - 1);
  877. gGL.texCoord2f(1.f, 0.f);
  878. gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mBottom);
  879. gGL.texCoord2f(1.f, 1.f);
  880. gGL.vertex2i(mPreviewRect.mRight - 1, mPreviewRect.mTop - 1);
  881. }
  882. gGL.end();
  883. unit0->unbind(LLTexUnit::TT_TEXTURE);
  884. }
  885. //virtual
  886. void LLFloaterModelPreview::refresh()
  887. {
  888. if (mModelPreview)
  889. {
  890. mModelPreview->mDirty = true;
  891. }
  892. }
  893. //virtual
  894. bool LLFloaterModelPreview::handleMouseDown(S32 x, S32 y, MASK mask)
  895. {
  896. if (mPreviewRect.pointInRect(x, y))
  897. {
  898. bringToFront(x, y);
  899. gFocusMgr.setMouseCapture(this);
  900. gViewerWindowp->hideCursor();
  901. mLastMouseX = x;
  902. mLastMouseY = y;
  903. return true;
  904. }
  905. return LLFloater::handleMouseDown(x, y, mask);
  906. }
  907. //virtual
  908. bool LLFloaterModelPreview::handleMouseUp(S32 x, S32 y, MASK mask)
  909. {
  910. gFocusMgr.setMouseCapture(NULL);
  911. gViewerWindowp->showCursor();
  912. return LLFloater::handleMouseUp(x, y, mask);
  913. }
  914. //virtual
  915. bool LLFloaterModelPreview::handleHover(S32 x, S32 y, MASK mask)
  916. {
  917. MASK local_mask = mask & ~MASK_ALT;
  918. if (mModelPreview && hasMouseCapture())
  919. {
  920. if (local_mask == MASK_PAN)
  921. {
  922. // pan here
  923. mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f,
  924. (F32)(y - mLastMouseY) * -0.005f);
  925. }
  926. else if (local_mask == MASK_ORBIT)
  927. {
  928. F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
  929. F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
  930. mModelPreview->rotate(yaw_radians, pitch_radians);
  931. }
  932. else
  933. {
  934. F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
  935. F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
  936. mModelPreview->rotate(yaw_radians, 0.f);
  937. mModelPreview->zoom(zoom_amt);
  938. }
  939. mModelPreview->refresh();
  940. LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
  941. }
  942. if (!mPreviewRect.pointInRect(x, y) || !mModelPreview)
  943. {
  944. return LLFloater::handleHover(x, y, mask);
  945. }
  946. else if (local_mask == MASK_ORBIT)
  947. {
  948. gViewerWindowp->setCursor(UI_CURSOR_TOOLCAMERA);
  949. }
  950. else if (local_mask == MASK_PAN)
  951. {
  952. gViewerWindowp->setCursor(UI_CURSOR_TOOLPAN);
  953. }
  954. else
  955. {
  956. gViewerWindowp->setCursor(UI_CURSOR_TOOLZOOMIN);
  957. }
  958. return true;
  959. }
  960. //virtual
  961. bool LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
  962. {
  963. if (mPreviewRect.pointInRect(x, y) && mModelPreview)
  964. {
  965. mModelPreview->zoom((F32)clicks * -0.2f);
  966. mModelPreview->refresh();
  967. return true;
  968. }
  969. return LLFloaterModelUploadBase::handleScrollWheel(x, y, clicks);
  970. }
  971. //virtual
  972. void LLFloaterModelPreview::onOpen()
  973. {
  974. requestAgentUploadPermissions();
  975. }
  976. //static
  977. void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl,
  978. void* userdata)
  979. {
  980. if (LLConvexDecomposition::getInstance() == NULL)
  981. {
  982. llwarns << "Convex decomposition tool is a stub on this platform. Cannot get decomp."
  983. << llendl;
  984. return;
  985. }
  986. LLFloaterModelPreview* self = findInstance();
  987. if (self)
  988. {
  989. LLCDParam* param = (LLCDParam*) userdata;
  990. std::string name(param->mName);
  991. LLSD value = ctrl->getValue();
  992. if ("Retain%" == name)
  993. {
  994. value = ctrl->getValue().asReal() / RETAIN_COEFFICIENT;
  995. }
  996. self->mDecompParams[name] = value;
  997. if (name == "Simplify Method")
  998. {
  999. bool show_retain = false;
  1000. bool show_detail = true;
  1001. if (ctrl->getValue().asInteger() == 0)
  1002. {
  1003. show_retain = true;
  1004. show_detail = false;
  1005. }
  1006. self->childSetVisible("Retain%", show_retain);
  1007. self->childSetVisible("Retain%_label", show_retain);
  1008. self->childSetVisible("Detail Scale", show_detail);
  1009. self->childSetVisible("Detail Scale label", show_detail);
  1010. }
  1011. }
  1012. }
  1013. //static
  1014. void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl*, void* userdata)
  1015. {
  1016. LLFloaterModelPreview* self = findInstance();
  1017. if (self && userdata)
  1018. {
  1019. LLCDStageData* stage_data = (LLCDStageData*)userdata;
  1020. std::string stage = stage_data->mName;
  1021. if (!self->mCurRequest.empty())
  1022. {
  1023. llinfos << "Decomposition request still pending." << llendl;
  1024. return;
  1025. }
  1026. if (self->mModelPreview)
  1027. {
  1028. for (S32 i = 0,
  1029. count = self->mModelPreview->mModel[LLModel::LOD_PHYSICS].size();
  1030. i < count; ++i)
  1031. {
  1032. LLModel* mdl =
  1033. self->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
  1034. DecompRequest* request = new DecompRequest(stage, mdl);
  1035. self->mCurRequest.insert(request);
  1036. gMeshRepo.mDecompThread->submitRequest(request);
  1037. }
  1038. }
  1039. if (stage == "Decompose")
  1040. {
  1041. self->setStatusMessage(self->getString("decomposing"));
  1042. self->childSetVisible("Decompose", false);
  1043. self->childSetVisible("decompose_cancel", true);
  1044. self->childDisable("Simplify");
  1045. }
  1046. else if (stage == "Simplify")
  1047. {
  1048. self->setStatusMessage(self->getString("simplifying"));
  1049. self->childSetVisible("Simplify", false);
  1050. self->childSetVisible("simplify_cancel", true);
  1051. self->childDisable("Decompose");
  1052. }
  1053. }
  1054. }
  1055. //static
  1056. void LLFloaterModelPreview::onPhysicsBrowse(void* userdata)
  1057. {
  1058. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1059. if (self)
  1060. {
  1061. self->loadModel(LLModel::LOD_PHYSICS);
  1062. }
  1063. }
  1064. //static
  1065. void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl*, void* userdata)
  1066. {
  1067. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1068. if (!self) return;
  1069. LLModelPreview* mp = self->mModelPreview;
  1070. if (!mp) return;
  1071. // 0 = no physics hull/SL default, 1 = highest LOD, ... 4 = lowest LOD,
  1072. // 5 = bounding box, 6 = from file.
  1073. static S32 previous_mode = 0;
  1074. S32 which_mode =
  1075. self->getChild<LLComboBox>("physics_lod_combo")->getCurrentIndex();
  1076. if (which_mode == 5)
  1077. {
  1078. std::string filename = gDirUtil.getFullPath(LL_PATH_APP_SETTINGS,
  1079. "meshes", "cube.dae");
  1080. mp->loadModel(filename, LLModel::LOD_PHYSICS, true, false);
  1081. mp->refresh();
  1082. mp->updateStatusMessages();
  1083. }
  1084. else
  1085. {
  1086. bool lod_to_file = previous_mode != 6 && which_mode == 6;
  1087. bool file_to_lod = previous_mode >= 5 && which_mode < 5;
  1088. if (!lod_to_file)
  1089. {
  1090. mp->setPhysicsFromLOD(4 - which_mode);
  1091. mp->refresh();
  1092. }
  1093. if (lod_to_file || file_to_lod)
  1094. {
  1095. mp->refresh();
  1096. mp->updateStatusMessages();
  1097. }
  1098. }
  1099. previous_mode = which_mode;
  1100. }
  1101. //static
  1102. void LLFloaterModelPreview::onCancel(void* userdata)
  1103. {
  1104. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1105. if (self)
  1106. {
  1107. onPhysicsStageCancel(self);
  1108. self->close();
  1109. }
  1110. }
  1111. //static
  1112. void LLFloaterModelPreview::onPhysicsStageCancel(void* userdata)
  1113. {
  1114. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1115. if (self)
  1116. {
  1117. for (std::set<LLPointer<DecompRequest> >::iterator
  1118. it = self->mCurRequest.begin(),
  1119. end = self->mCurRequest.end();
  1120. it != end; ++it)
  1121. {
  1122. DecompRequest* req = *it;
  1123. req->mContinue = 0;
  1124. }
  1125. self->mCurRequest.clear();
  1126. if (self->mModelPreview)
  1127. {
  1128. self->mModelPreview->updateStatusMessages();
  1129. }
  1130. }
  1131. }
  1132. void LLFloaterModelPreview::initDecompControls()
  1133. {
  1134. LLSD key;
  1135. childSetAction("simplify_cancel", onPhysicsStageCancel, this);
  1136. childSetAction("decompose_cancel", onPhysicsStageCancel, this);
  1137. childSetCommitCallback("physics_lod_combo", onPhysicsUseLOD, this);
  1138. childSetAction("physics_browse", onPhysicsBrowse, this);
  1139. static const LLCDStageData* stage = NULL;
  1140. static S32 stage_count = 0;
  1141. LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
  1142. if (decomp)
  1143. {
  1144. stage_count = decomp->getStages(&stage);
  1145. }
  1146. LL_DEBUGS("MeshUpload") << "stage_count = " << stage_count << LL_ENDL;
  1147. static const LLCDParam* param = NULL;
  1148. static S32 param_count = 0;
  1149. if (!param && decomp)
  1150. {
  1151. param_count = decomp->getParameters(&param);
  1152. }
  1153. LL_DEBUGS("MeshUpload") << "param_count = " << param_count << LL_ENDL;
  1154. for (S32 j = stage_count - 1; j >= 0; --j)
  1155. {
  1156. LLUICtrl* ctrl = getChild<LLUICtrl>(stage[j].mName, true, false);
  1157. if (ctrl)
  1158. {
  1159. ctrl->setCommitCallback(onPhysicsStageExecute);
  1160. ctrl->setCallbackUserData((void*)&stage[j]);
  1161. }
  1162. gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j;
  1163. // Protected against stub by stage_count being 0 for stub above
  1164. if (decomp)
  1165. {
  1166. decomp->registerCallback(j, LLPhysicsDecomp::llcdCallback);
  1167. }
  1168. LL_DEBUGS("MeshUpload") << "Physics decomp stage " << stage[j].mName
  1169. << " (" << j << ") parameters:" << LL_ENDL;
  1170. LL_DEBUGS("MeshUpload") << "------------------------------------"
  1171. << LL_ENDL;
  1172. for (S32 i = 0; i < param_count; ++i)
  1173. {
  1174. if (param[i].mStage != j)
  1175. {
  1176. continue;
  1177. }
  1178. std::string name(param[i].mName ? param[i].mName : "");
  1179. std::string description(param[i].mDescription ? param[i].mDescription
  1180. : "");
  1181. std::string type = "unknown";
  1182. LL_DEBUGS("MeshUpload") << name << " - " << description << LL_ENDL;
  1183. if (param[i].mType == LLCDParam::LLCD_FLOAT)
  1184. {
  1185. mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat);
  1186. LL_DEBUGS("MeshUpload") << "Type: float - Default: "
  1187. << param[i].mDefault.mFloat << LL_ENDL;
  1188. LLUICtrl* ctrl = getChild<LLUICtrl>(name.c_str());
  1189. if (LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl))
  1190. {
  1191. LL_DEBUGS("MeshUpload") << name
  1192. << " corresponds to a slider."
  1193. << LL_ENDL;
  1194. slider->setMinValue(param[i].mDetails.mRange.mLow.mFloat);
  1195. slider->setMaxValue(param[i].mDetails.mRange.mHigh.mFloat);
  1196. slider->setIncrement(param[i].mDetails.mRange.mDelta.mFloat);
  1197. slider->setValue(param[i].mDefault.mFloat);
  1198. slider->setCommitCallback(onPhysicsParamCommit);
  1199. slider->setCallbackUserData((void*) &param[i]);
  1200. }
  1201. else if (LLSpinCtrl* spinner = dynamic_cast<LLSpinCtrl*>(ctrl))
  1202. {
  1203. LL_DEBUGS("MeshUpload") << name
  1204. << " corresponds to a spinner."
  1205. << LL_ENDL;
  1206. bool is_retain_ctrl = "Retain%" == name;
  1207. double coefficient = is_retain_ctrl ? RETAIN_COEFFICIENT : 1.f;
  1208. spinner->setMinValue(param[i].mDetails.mRange.mLow.mFloat * coefficient);
  1209. spinner->setMaxValue(param[i].mDetails.mRange.mHigh.mFloat * coefficient);
  1210. spinner->setIncrement(param[i].mDetails.mRange.mDelta.mFloat * coefficient);
  1211. spinner->setValue(param[i].mDefault.mFloat * coefficient);
  1212. spinner->setCommitCallback(onPhysicsParamCommit);
  1213. spinner->setCallbackUserData((void*) &param[i]);
  1214. }
  1215. else if (LLComboBox* combo_box = dynamic_cast<LLComboBox*>(ctrl))
  1216. {
  1217. LL_DEBUGS("MeshUpload") << name
  1218. << " corresponds to a combo box."
  1219. << LL_ENDL;
  1220. F32 min = param[i].mDetails.mRange.mLow.mFloat;
  1221. F32 max = param[i].mDetails.mRange.mHigh.mFloat;
  1222. F32 delta = param[i].mDetails.mRange.mDelta.mFloat;
  1223. if (name == "Cosine%")
  1224. {
  1225. createSmoothComboBox(combo_box, min, max);
  1226. combo_box->setValue(0);
  1227. }
  1228. else
  1229. {
  1230. for (F32 value = min; value <= max; value += delta)
  1231. {
  1232. std::string label = llformat("%.1f", value);
  1233. combo_box->add(label, value, ADD_BOTTOM, true);
  1234. }
  1235. combo_box->setValue(param[i].mDefault.mFloat);
  1236. }
  1237. combo_box->setCommitCallback(onPhysicsParamCommit);
  1238. combo_box->setCallbackUserData((void*)&param[i]);
  1239. }
  1240. else
  1241. {
  1242. LL_DEBUGS("MeshUpload") << "WARNING: " << name
  1243. << " does not correspond to any widget !"
  1244. << LL_ENDL;
  1245. }
  1246. }
  1247. else if (param[i].mType == LLCDParam::LLCD_INTEGER)
  1248. {
  1249. mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
  1250. LL_DEBUGS("MeshUpload") << "Type: integer - Default: "
  1251. << param[i].mDefault.mIntOrEnumValue
  1252. << LL_ENDL;
  1253. LLUICtrl* ctrl = getChild<LLUICtrl>(name.c_str());
  1254. if (LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl))
  1255. {
  1256. slider->setMinValue(param[i].mDetails.mRange.mLow.mIntOrEnumValue);
  1257. slider->setMaxValue(param[i].mDetails.mRange.mHigh.mIntOrEnumValue);
  1258. slider->setIncrement(param[i].mDetails.mRange.mDelta.mIntOrEnumValue);
  1259. slider->setValue(param[i].mDefault.mIntOrEnumValue);
  1260. slider->setCommitCallback(onPhysicsParamCommit);
  1261. slider->setCallbackUserData((void*) &param[i]);
  1262. }
  1263. else if (LLComboBox* combo_box = dynamic_cast<LLComboBox*>(ctrl))
  1264. {
  1265. for (S32 k = param[i].mDetails.mRange.mLow.mIntOrEnumValue;
  1266. k <= param[i].mDetails.mRange.mHigh.mIntOrEnumValue;
  1267. k += param[i].mDetails.mRange.mDelta.mIntOrEnumValue)
  1268. {
  1269. std::string name = llformat("%.1d", k);
  1270. combo_box->add(name, k, ADD_BOTTOM, true);
  1271. }
  1272. combo_box->setValue(param[i].mDefault.mIntOrEnumValue);
  1273. combo_box->setCommitCallback(onPhysicsParamCommit);
  1274. combo_box->setCallbackUserData((void*) &param[i]);
  1275. }
  1276. else
  1277. {
  1278. LL_DEBUGS("MeshUpload") << "WARNING: " << name
  1279. << " does not correspond to any widget !"
  1280. << LL_ENDL;
  1281. }
  1282. }
  1283. else if (param[i].mType == LLCDParam::LLCD_BOOLEAN)
  1284. {
  1285. mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool);
  1286. LL_DEBUGS("MeshUpload") << "Type: boolean - Default: "
  1287. << (param[i].mDefault.mBool ? "TRUE" : "FALSE")
  1288. << LL_ENDL;
  1289. LLCheckBoxCtrl* check_box =
  1290. getChild<LLCheckBoxCtrl>(name.c_str(), true, false);
  1291. if (check_box)
  1292. {
  1293. check_box->setValue(param[i].mDefault.mBool);
  1294. check_box->setCommitCallback(onPhysicsParamCommit);
  1295. check_box->setCallbackUserData((void*)&param[i]);
  1296. }
  1297. else if (name == "nd_AlwaysNeedTriangles")
  1298. {
  1299. if (!mLibIsHACD)
  1300. {
  1301. llinfos << "HACD convex decomposition library detected. Some features will not be available."
  1302. << llendl;
  1303. mLibIsHACD = true;
  1304. }
  1305. }
  1306. else
  1307. {
  1308. LL_DEBUGS("MeshUpload") << "WARNING: " << name
  1309. << " does not correspond to any widget !"
  1310. << LL_ENDL;
  1311. }
  1312. }
  1313. else if (param[i].mType == LLCDParam::LLCD_ENUM)
  1314. {
  1315. mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
  1316. LL_DEBUGS("MeshUpload") << "Type: enum - Default: "
  1317. << param[i].mDefault.mIntOrEnumValue
  1318. << LL_ENDL;
  1319. // Plug into combo box
  1320. LL_DEBUGS("MeshUpload") << "Accepted values: " << LL_ENDL;
  1321. LLComboBox* combo_box = getChild<LLComboBox>(name.c_str(),
  1322. true, false);
  1323. if (combo_box)
  1324. {
  1325. for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k)
  1326. {
  1327. LL_DEBUGS("MeshUpload") << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue
  1328. << " - "
  1329. << param[i].mDetails.mEnumValues.mEnumsArray[k].mName
  1330. << LL_ENDL;
  1331. std::string name(param[i].mDetails.mEnumValues.mEnumsArray[k].mName);
  1332. combo_box->add(name,
  1333. LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue));
  1334. }
  1335. combo_box->setValue(param[i].mDefault.mIntOrEnumValue);
  1336. combo_box->setCommitCallback(onPhysicsParamCommit);
  1337. combo_box->setCallbackUserData((void*) &param[i]);
  1338. }
  1339. else
  1340. {
  1341. LL_DEBUGS("MeshUpload") << "WARNING: " << name
  1342. << " does not correspond to any widget !"
  1343. << LL_ENDL;
  1344. }
  1345. LL_DEBUGS("MeshUpload") << "----" << LL_ENDL;
  1346. }
  1347. LL_DEBUGS("MeshUpload") << "-----------------------------" << LL_ENDL;
  1348. }
  1349. }
  1350. childSetCommitCallback("physics_explode", onExplodeCommit, this);
  1351. }
  1352. void LLFloaterModelPreview::createSmoothComboBox(LLComboBox* combo_box,
  1353. F32 min, F32 max)
  1354. {
  1355. F32 delta = (max - min) / SMOOTH_VALUES_NUMBER;
  1356. S32 ilabel = 0;
  1357. combo_box->add("0 (none)", ADD_BOTTOM, true);
  1358. std::string label;
  1359. for (F32 value = min + delta; value < max; value += delta)
  1360. {
  1361. label = (++ilabel == SMOOTH_VALUES_NUMBER ? "10 (max)"
  1362. : llformat("%.1d", ilabel));
  1363. combo_box->add(label, value, ADD_BOTTOM, true);
  1364. }
  1365. }
  1366. void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z)
  1367. {
  1368. assert_main_thread();
  1369. childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
  1370. childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
  1371. childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
  1372. }
  1373. //virtual
  1374. void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
  1375. {
  1376. dump_llsd_to_file(result, "perm_received.xml");
  1377. std::string upload_status = result["mesh_upload_status"].asString();
  1378. // *HACK: handle "" for case that MeshUploadFlag cap is broken.
  1379. mHasUploadPerm = ("" == upload_status || "valid" == upload_status);
  1380. // isModelUploadAllowed() includes mHasUploadPerm
  1381. mUploadBtn->setEnabled(isModelUploadAllowed());
  1382. childSetVisible("warning_message", !mHasUploadPerm);
  1383. childSetVisible("validate_url", !mHasUploadPerm && !mValidateURL.empty());
  1384. }
  1385. void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status,
  1386. const std::string& reason)
  1387. {
  1388. llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status
  1389. << " : " << reason << ")" << llendl;
  1390. gNotifications.add("MeshUploadPermError");
  1391. }
  1392. void LLFloaterModelPreview::addMessageToLog(const std::string& msg,
  1393. const LLSD& args, S32 lod,
  1394. bool flash)
  1395. {
  1396. if (msg.empty())
  1397. {
  1398. return;
  1399. }
  1400. std::string line;
  1401. switch (lod)
  1402. {
  1403. case LLModel::LOD_IMPOSTOR:
  1404. line = "LOD0 ";
  1405. break;
  1406. case LLModel::LOD_LOW:
  1407. line = "LOD1 ";
  1408. break;
  1409. case LLModel::LOD_MEDIUM:
  1410. line = "LOD2 ";
  1411. break;
  1412. case LLModel::LOD_HIGH:
  1413. line = "LOD3 ";
  1414. break;
  1415. case LLModel::LOD_PHYSICS:
  1416. line = "PHYS ";
  1417. break;
  1418. default:
  1419. break;
  1420. }
  1421. LLStringUtil::format_map_t args_msg;
  1422. for (LLSD::map_const_iterator it = args.beginMap(), end = args.endMap();
  1423. it != end; ++it)
  1424. {
  1425. args_msg[it->first] = it->second.asString();
  1426. }
  1427. line += getString(msg, args_msg);
  1428. addLineToLog(line, flash);
  1429. }
  1430. void LLFloaterModelPreview::addLineToLog(const std::string& line, bool flash)
  1431. {
  1432. if (line.empty())
  1433. {
  1434. return;
  1435. }
  1436. LLWString text = utf8str_to_wstring(line);
  1437. S32 add_text_len = text.length() + 1; // newline
  1438. S32 editor_max_len = mUploadLogText->getMaxLength();
  1439. if (add_text_len > editor_max_len)
  1440. {
  1441. return;
  1442. }
  1443. // Make sure we have space for the new string
  1444. S32 editor_text_len = mUploadLogText->getLength();
  1445. while (editor_max_len < editor_text_len + add_text_len)
  1446. {
  1447. S32 shift = mUploadLogText->removeFirstLine();
  1448. if (shift <= 0)
  1449. {
  1450. mUploadLogText->clear();
  1451. break;
  1452. }
  1453. editor_text_len -= shift;
  1454. }
  1455. LL_DEBUGS("MeshUpload") << "Adding log line: " << line << LL_ENDL;
  1456. mUploadLogText->appendText(line, false, true);
  1457. if (flash)
  1458. {
  1459. if (mTabContainer->getCurrentPanel() != mLogPanel)
  1460. {
  1461. mTabContainer->setTabPanelFlashing(mLogPanel, true);
  1462. }
  1463. }
  1464. }
  1465. void LLFloaterModelPreview::clearLog()
  1466. {
  1467. mUploadLogText->clear();
  1468. mTabContainer->setTabPanelFlashing(mLogPanel, false);
  1469. }
  1470. void LLFloaterModelPreview::clearSkinningInfo()
  1471. {
  1472. mSelectedJointName.clear();
  1473. mJointsList->deleteAllItems();
  1474. mJointsList->setVisible(false);
  1475. mJointsOverrides->deleteAllItems();
  1476. mJointsOverrides->setVisible(false);
  1477. for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
  1478. {
  1479. mJointOverrides[i].clear();
  1480. }
  1481. mOverridesLabel->setVisible(false);
  1482. mConflictsText->setVisible(false);
  1483. childSetVisible("skin_too_many_joints", false);
  1484. childSetVisible("skin_unknown_joint", false);
  1485. }
  1486. void LLFloaterModelPreview::updateSkinningInfo(bool highlight_overrides)
  1487. {
  1488. if (!mModelPreview) return;
  1489. S32 display_lod = mModelPreview->mPreviewLOD;
  1490. if (mModelPreview->mModel[display_lod].empty())
  1491. {
  1492. mSelectedJointName.clear();
  1493. return;
  1494. }
  1495. // Joints are listed as long as they exist in mAlternateBindMatrix, even
  1496. // if they are for some reason identical to defaults.
  1497. // *TODO: are overrides always identical for all lods ? They should, but
  1498. // there might be situations where they are not.
  1499. if (mJointOverrides[display_lod].empty())
  1500. {
  1501. for (LLModelLoader::scene::iterator
  1502. it = mModelPreview->mScene[display_lod].begin(),
  1503. end = mModelPreview->mScene[display_lod].end();
  1504. it != end; ++it)
  1505. {
  1506. for (LLModelLoader::model_instance_list_t::iterator
  1507. mit = it->second.begin(), mend = it->second.end();
  1508. mit != mend; ++mit)
  1509. {
  1510. LLModelInstance& instance = *mit;
  1511. LLModel* model = instance.mModel;
  1512. const LLMeshSkinInfo* skin = &model->mSkinInfo;
  1513. U32 joint_count = llmin(LL_MAX_JOINTS_PER_MESH_OBJECT,
  1514. (U32)skin->mJointKeys.size());
  1515. U32 bind_count = 0;
  1516. if (highlight_overrides)
  1517. {
  1518. bind_count = skin->mAlternateBindMatrix.size();
  1519. }
  1520. if (bind_count && bind_count != joint_count)
  1521. {
  1522. std::ostringstream out;
  1523. out << "Invalid joint overrides for model: "
  1524. << model->getName() << " - Amount of joints "
  1525. << joint_count << " is different from amount of overrides "
  1526. << bind_count;
  1527. llwarns << out.str() << llendl;
  1528. addLineToLog(out.str(), true);
  1529. bind_count = 0; // Disable overrides for this model
  1530. }
  1531. if (bind_count)
  1532. {
  1533. constexpr F32 MAX_SQUARED_OFFSET =
  1534. LL_JOINT_TRESHOLD_POS_OFFSET *
  1535. LL_JOINT_TRESHOLD_POS_OFFSET;
  1536. for (U32 j = 0; j < joint_count; ++j)
  1537. {
  1538. const LLVector3& joint_pos =
  1539. skin->mAlternateBindMatrix[j].getTranslation();
  1540. const std::string& jname = skin->mJointNames[j];
  1541. JointOverrideData& data =
  1542. mJointOverrides[display_lod][jname];
  1543. LLJoint* jointp =
  1544. LLModelPreview::lookupJointByName(jname,
  1545. mModelPreview);
  1546. if (!jointp) continue;
  1547. if (jointp->aboveJointPosThreshold(joint_pos))
  1548. {
  1549. // Valid override
  1550. if (data.mPosOverrides.size() &&
  1551. (data.mPosOverrides.begin()->second -
  1552. joint_pos).lengthSquared() > MAX_SQUARED_OFFSET)
  1553. {
  1554. // File contains multiple meshes with
  1555. // conflicting joint offsets; preview may be
  1556. // incorrect, upload result might wary (depends
  1557. // onto mesh_id that is not yet generated).
  1558. data.mHasConflicts = true;
  1559. }
  1560. data.mPosOverrides[model->getName()] = joint_pos;
  1561. }
  1562. else
  1563. {
  1564. // Default value which would nott be accounted for
  1565. data.mModelsNoOverrides.insert(model->getName());
  1566. }
  1567. }
  1568. }
  1569. else
  1570. {
  1571. for (U32 j = 0; j < joint_count; ++j)
  1572. {
  1573. JointOverrideData& data =
  1574. mJointOverrides[display_lod][skin->mJointNames[j]];
  1575. data.mModelsNoOverrides.insert(model->getName());
  1576. }
  1577. }
  1578. }
  1579. }
  1580. }
  1581. U32 conflicts = 0;
  1582. if (mJointsList->isEmpty())
  1583. {
  1584. mJointsList->setVisible(true);
  1585. mJointsOverrides->setVisible(true);
  1586. JointMap joint_alias_map;
  1587. mModelPreview->getJointAliases(joint_alias_map);
  1588. for (overrides_map_t::iterator
  1589. it = mJointOverrides[display_lod].begin(),
  1590. end = mJointOverrides[display_lod].end();
  1591. it != end; ++it)
  1592. {
  1593. const std::string& jname = it->first;
  1594. LLSD element;
  1595. element["id"] = jname;
  1596. LLSD& column = element["columns"][0];
  1597. column["column"] = "name";
  1598. column["value"] = jname;
  1599. column["type"] = "text";
  1600. column["font"] = "SANSSERIF";
  1601. if (joint_alias_map.find(jname) == joint_alias_map.end())
  1602. {
  1603. // Missing joint name
  1604. column["color"] = LLColor4::red2.getValue();
  1605. }
  1606. if (it->second.mHasConflicts)
  1607. {
  1608. column["color"] = LLColor4::orange2.getValue();
  1609. ++conflicts;
  1610. }
  1611. if (highlight_overrides && it->second.mPosOverrides.size() > 0)
  1612. {
  1613. column["font-style"] = "BOLD";
  1614. }
  1615. else
  1616. {
  1617. column["font-style"] = "NORMAL";
  1618. }
  1619. mJointsList->addElement(element);
  1620. }
  1621. mJointsList->selectFirstItem();
  1622. LLScrollListItem* selected = mJointsList->getFirstSelected();
  1623. if (selected)
  1624. {
  1625. mSelectedJointName = selected->getValue().asString();
  1626. }
  1627. }
  1628. if (conflicts)
  1629. {
  1630. mConflictsText->setVisible(true);
  1631. mConflictsText->setTextArg("[CONFLICTS]", llformat("%d", conflicts));
  1632. }
  1633. }
  1634. //static
  1635. void LLFloaterModelPreview::onJointListSelection(LLUICtrl*, void* userdata)
  1636. {
  1637. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1638. if (!self || !self->mModelPreview) return;
  1639. self->mJointsOverrides->deleteAllItems();
  1640. LLScrollListItem* selected = self->mJointsList->getFirstSelected();
  1641. if (!selected)
  1642. {
  1643. self->mSelectedJointName.clear();
  1644. self->mOverridesLabel->setVisible(false);
  1645. return;
  1646. }
  1647. std::string label = selected->getValue().asString();
  1648. self->mSelectedJointName = label;
  1649. self->mOverridesLabel->setTextArg("[JOINT_NAME]", label);
  1650. self->mOverridesLabel->setVisible(true);
  1651. S32 lod = self->mModelPreview->mPreviewLOD;
  1652. const JointOverrideData& data = self->mJointOverrides[lod][label];
  1653. if (data.mModelsNoOverrides.empty() && data.mPosOverrides.empty())
  1654. {
  1655. return;
  1656. }
  1657. bool upload_joint_pos = self->childGetValue("upload_joints").asBoolean();
  1658. // This is the constant part for every row of the list
  1659. LLSD element;
  1660. element["columns"][0]["column"] = "name";
  1661. element["columns"][0]["type"] = "text";
  1662. element["columns"][0]["font"] = "SANSSERIF";
  1663. element["columns"][1]["column"] = "x";
  1664. element["columns"][1]["type"] = "text";
  1665. element["columns"][1]["font"] = "SANSSERIF";
  1666. element["columns"][2]["column"] = "y";
  1667. element["columns"][2]["type"] = "text";
  1668. element["columns"][2]["font"] = "SANSSERIF";
  1669. element["columns"][3]["column"] = "z";
  1670. element["columns"][3]["type"] = "text";
  1671. element["columns"][3]["font"] = "SANSSERIF";
  1672. for (std::map<std::string, LLVector3>::const_iterator
  1673. it = data.mPosOverrides.begin(), end = data.mPosOverrides.end();
  1674. it != end; ++it)
  1675. {
  1676. element["id"] = it->first;
  1677. element["columns"][0]["value"] = it->first;
  1678. if (upload_joint_pos)
  1679. {
  1680. element["columns"][1]["value"] = llformat("%f", it->second.mV[VX]);
  1681. element["columns"][2]["value"] = llformat("%f", it->second.mV[VY]);
  1682. element["columns"][3]["value"] = llformat("%f", it->second.mV[VZ]);
  1683. }
  1684. else
  1685. {
  1686. element["columns"][1]["value"] = "-";
  1687. element["columns"][2]["value"] = "-";
  1688. element["columns"][3]["value"] = "-";
  1689. }
  1690. self->mJointsOverrides->addElement(element);
  1691. }
  1692. element["columns"][1]["value"] = "-";
  1693. element["columns"][2]["value"] = "-";
  1694. element["columns"][3]["value"] = "-";
  1695. for (std::set<std::string>::const_iterator
  1696. it = data.mModelsNoOverrides.begin(),
  1697. end = data.mModelsNoOverrides.end();
  1698. it != end; ++it)
  1699. {
  1700. element["id"] = *it;
  1701. element["columns"][0]["value"] = *it;
  1702. self->mJointsOverrides->addElement(element);
  1703. }
  1704. }
  1705. //static
  1706. void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler*)
  1707. {
  1708. gViewerWindowp->showCursor();
  1709. }
  1710. //static
  1711. void LLFloaterModelPreview::onBrowseLOD(void* userdata)
  1712. {
  1713. LLFloaterModelPreview* self = findInstance();
  1714. if (self)
  1715. {
  1716. assert_main_thread();
  1717. S32 lod = (S32)(intptr_t)userdata - 1;
  1718. self->loadModel(lod);
  1719. }
  1720. }
  1721. //static
  1722. void LLFloaterModelPreview::onReset(void* userdata)
  1723. {
  1724. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1725. if (!self) return;
  1726. LLModelPreview* mp = self->mModelPreview;
  1727. if (!mp) return;
  1728. assert_main_thread();
  1729. self->clearLog();
  1730. self->childDisable("reset_btn");
  1731. // Make sure the physics LOD combo is reset.
  1732. LLComboBox* phys_combop = self->getChild<LLComboBox>("physics_lod_combo");
  1733. LLScrollListItem* itemp = phys_combop->getItemByIndex(0);
  1734. if (itemp)
  1735. {
  1736. itemp->setEnabled(true);
  1737. }
  1738. phys_combop->setCurrentByIndex(0);
  1739. std::string filename = mp->mLODFile[LLModel::LOD_HIGH];
  1740. self->resetDisplayOptions();
  1741. // Reset model preview
  1742. self->initModelPreview();
  1743. phys_combop->selectFirstItem();
  1744. self->childSetText("physics_file", "");
  1745. // Refesh from new model preview
  1746. mp = self->mModelPreview;
  1747. mp->loadModel(filename, LLModel::LOD_HIGH, true);
  1748. }
  1749. //static
  1750. void LLFloaterModelPreview::onUpload(void* userdata)
  1751. {
  1752. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1753. if (!self || !self->mModelPreview) return;
  1754. assert_main_thread();
  1755. self->clearLog();
  1756. self->mUploadBtn->setEnabled(false);
  1757. self->mSentUploadRequest = true;
  1758. self->mModelPreview->rebuildUploadData();
  1759. bool upload_skinweights = self->childGetValue("upload_skin").asBoolean();
  1760. bool upload_joint_pos = self->childGetValue("upload_joints").asBoolean();
  1761. bool lock_scale_if_joint_pos =
  1762. self->childGetValue("lock_scale_if_joint_position").asBoolean();
  1763. if (gSavedSettings.getBool("MeshImportUseSLM"))
  1764. {
  1765. self->mModelPreview->saveUploadData(upload_skinweights,
  1766. upload_joint_pos,
  1767. lock_scale_if_joint_pos);
  1768. }
  1769. gMeshRepo.uploadModel(self->mModelPreview->mUploadData,
  1770. self->mModelPreview->mPreviewScale,
  1771. self->childGetValue("upload_textures").asBoolean(),
  1772. upload_skinweights, upload_joint_pos,
  1773. lock_scale_if_joint_pos, self->mUploadModelUrl,
  1774. true, LLHandle<LLWholeModelFeeObserver>(),
  1775. self->getWholeModelUploadObserverHandle());
  1776. }
  1777. void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
  1778. {
  1779. mStatusLock->lock();
  1780. mStatusMessage = msg;
  1781. mStatusLock->unlock();
  1782. }
  1783. //static
  1784. void LLFloaterModelPreview::toggleCalculateButtonCallBack(LLUICtrl*,
  1785. void* userdata)
  1786. {
  1787. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1788. if (self)
  1789. {
  1790. self->toggleCalculateButton(true);
  1791. }
  1792. }
  1793. void LLFloaterModelPreview::toggleCalculateButton(bool visible)
  1794. {
  1795. mCalculateBtn->setVisible(visible);
  1796. if (childGetValue("upload_skin").asBoolean())
  1797. {
  1798. // Disable the calculate button *if* the rig is invalid, which is
  1799. // determined during the critiquing process
  1800. if (childGetValue("upload_joints").asBoolean() && mModelPreview &&
  1801. !mModelPreview->isRigValidForJointPositionUpload())
  1802. {
  1803. mCalculateBtn->setEnabled(false);
  1804. }
  1805. }
  1806. mUploadBtn->setVisible(!visible);
  1807. mUploadBtn->setEnabled(isModelUploadAllowed());
  1808. if (visible)
  1809. {
  1810. std::string tbd = getString("tbd");
  1811. childSetTextArg("prim_weight", "[EQ]", tbd);
  1812. childSetTextArg("download_weight", "[ST]", tbd);
  1813. childSetTextArg("server_weight", "[SIM]", tbd);
  1814. childSetTextArg("physics_weight", "[PH]", tbd);
  1815. childSetToolTip("physics_weight", "");
  1816. if (!mModelPhysicsFee.size() || !mModelPhysicsFee.isMap())
  1817. {
  1818. childSetTextArg("upload_fee", "[FEE]", tbd);
  1819. childSetToolTip("upload_fee", "");
  1820. }
  1821. }
  1822. }
  1823. void LLFloaterModelPreview::modelUpdated(bool visible)
  1824. {
  1825. mModelPhysicsFee.clear();
  1826. toggleCalculateButton(visible);
  1827. }
  1828. //static
  1829. void LLFloaterModelPreview::onLoDSourceCommit(LLUICtrl*, void* userdata)
  1830. {
  1831. LLFloaterModelPreview* self = findInstance();
  1832. if (self && self->mModelPreview)
  1833. {
  1834. S32 lod = (S32)(intptr_t)userdata;
  1835. self->mModelPreview->updateLodControls(lod);
  1836. self->refresh();
  1837. std::string cname = "lod_source_" + lod_name[lod];
  1838. LLComboBox* lod_combo = self->getChild<LLComboBox>(cname.c_str());
  1839. S32 index = lod_combo->getCurrentIndex();
  1840. if (index >= LLModelPreview::GENERATE &&
  1841. index < LLModelPreview::USE_LOD_ABOVE)
  1842. {
  1843. // Rebuild LoD to update triangle counts
  1844. onLODParamCommitEnforceTriLimit(lod_combo, (void*)(intptr_t)lod);
  1845. }
  1846. else if (index == LLModelPreview::USE_LOD_ABOVE)
  1847. {
  1848. // Refresh to pick triangle counts
  1849. self->mModelPreview->mDirty = true;
  1850. }
  1851. }
  1852. }
  1853. //static
  1854. void LLFloaterModelPreview::onClickValidateURL(void* userdata)
  1855. {
  1856. LLFloaterModelPreview* self = (LLFloaterModelPreview*)userdata;
  1857. if (self && !self->mValidateURL.empty())
  1858. {
  1859. LLWeb::loadURLExternal(self->mValidateURL);
  1860. }
  1861. }
  1862. void LLFloaterModelPreview::resetDisplayOptions()
  1863. {
  1864. if (!mModelPreview) return;
  1865. std::map<std::string, bool>::iterator option_it =
  1866. mModelPreview->mViewOption.begin();
  1867. for ( ; option_it != mModelPreview->mViewOption.end(); ++option_it)
  1868. {
  1869. LLUICtrl* ctrl = getChild<LLUICtrl>(option_it->first.c_str());
  1870. ctrl->setValue(false);
  1871. }
  1872. }
  1873. //virtual
  1874. void LLFloaterModelPreview::onModelPhysicsFeeReceived(const LLSD& result,
  1875. std::string upload_url)
  1876. {
  1877. mModelPhysicsFee = result;
  1878. mModelPhysicsFee["url"] = upload_url;
  1879. doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::handleModelPhysicsFeeReceived,
  1880. this));
  1881. }
  1882. void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
  1883. {
  1884. const LLSD& result = mModelPhysicsFee;
  1885. mUploadModelUrl = result["url"].asString();
  1886. mSentFeeRequest = false;
  1887. childSetTextArg("prim_weight", "[EQ]",
  1888. llformat("%0.3f", result["resource_cost"].asReal()));
  1889. childSetTextArg("download_weight", "[ST]",
  1890. llformat("%0.3f", result["model_streaming_cost"].asReal()));
  1891. childSetTextArg("server_weight", "[SIM]",
  1892. llformat("%0.3f", result["simulation_cost"].asReal()));
  1893. childSetTextArg("physics_weight", "[PH]",
  1894. llformat("%0.3f", result["physics_cost"].asReal()));
  1895. childSetTextArg("upload_fee", "[FEE]",
  1896. llformat("%d", result["upload_price"].asInteger()));
  1897. if (result.has("upload_price_breakdown"))
  1898. {
  1899. const LLSD& price = result["upload_price_breakdown"];
  1900. LLUIString tooltip = getString("price_breakdown");
  1901. tooltip.setArg("[STREAMING]",
  1902. llformat("%d", price["mesh_streaming"].asInteger()));
  1903. tooltip.setArg("[PHYSICS]",
  1904. llformat("%d", price["mesh_physics"].asInteger()));
  1905. tooltip.setArg("[INSTANCES]",
  1906. llformat("%d", price["mesh_instance"].asInteger()));
  1907. tooltip.setArg("[TEXTURES]",
  1908. llformat("%d", price["texture"].asInteger()));
  1909. tooltip.setArg("[MODEL]",
  1910. llformat("%d", price["model"].asInteger()));
  1911. childSetToolTip("upload_fee", tooltip.getString());
  1912. }
  1913. if (result.has("model_physics_cost"))
  1914. {
  1915. const LLSD& costs = result["model_physics_cost"];
  1916. LLUIString tooltip = getString("physics_breakdown");
  1917. tooltip.setArg("[PCH]", llformat("%d", costs["hull"].asInteger()));
  1918. tooltip.setArg("[PM]", llformat("%d", costs["mesh"].asInteger()));
  1919. tooltip.setArg("[PHU]",
  1920. llformat("%d", costs["decomposition"].asInteger()));
  1921. childSetToolTip("physics_weight", tooltip.getString());
  1922. }
  1923. // "Streaming breakdown numbers are available but not fully understood"...
  1924. // Dixit LL, and these numbers are not shown in their viewer. Kept as a
  1925. // debug message only. HB
  1926. if (result.has("streaming_cost") && result.has("streaming_params"))
  1927. {
  1928. const LLSD& sp = result["streaming_params"];
  1929. LL_DEBUGS("MeshUpload") << "Streaming cost breakdown: total = "
  1930. << result["streaming_cost"].asInteger()
  1931. << ", LOD3 = " << sp["high_lod"].asInteger()
  1932. << ", LOD2 = " << sp["medium_lod"].asInteger()
  1933. << ", LOD1 = " << sp["low_lod"].asInteger()
  1934. << ", LOD0 = " << sp["lowest_lod"].asInteger()
  1935. << LL_ENDL;
  1936. }
  1937. mUploadBtn->setEnabled(isModelUploadAllowed());
  1938. }
  1939. //virtual
  1940. void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status,
  1941. const std::string& reason,
  1942. const LLSD& result)
  1943. {
  1944. llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status
  1945. << " : " << reason << ")" << llendl;
  1946. mSentFeeRequest = false;
  1947. doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton,
  1948. this, true));
  1949. if (result.has("upload_price"))
  1950. {
  1951. mModelPhysicsFee = result;
  1952. childSetTextArg("upload_fee", "[FEE]",
  1953. llformat("%d", result["upload_price"].asInteger()));
  1954. }
  1955. else
  1956. {
  1957. mModelPhysicsFee.clear();
  1958. }
  1959. }
  1960. //virtual
  1961. void LLFloaterModelPreview::onModelUploadSuccess()
  1962. {
  1963. mSentUploadRequest = false;
  1964. assert_main_thread();
  1965. close();
  1966. }
  1967. //virtual
  1968. void LLFloaterModelPreview::onModelUploadFailure()
  1969. {
  1970. assert_main_thread();
  1971. mSentUploadRequest = false;
  1972. toggleCalculateButton(true);
  1973. mUploadBtn->setEnabled(true);
  1974. }
  1975. bool LLFloaterModelPreview::isModelUploadAllowed()
  1976. {
  1977. bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty();
  1978. if (mModelPreview)
  1979. {
  1980. allow_upload &= mModelPreview->mModelNoErrors;
  1981. }
  1982. LL_DEBUGS("MeshUpload") << "mHasUploadPerm = " << mHasUploadPerm
  1983. << " - mUploadModelUrl = " << mUploadModelUrl
  1984. << " - mModelNoErrors = "
  1985. << (mModelPreview ? mModelPreview->mModelNoErrors : -1)
  1986. << LL_ENDL;
  1987. return allow_upload;
  1988. }
  1989. //-----------------------------------------------------------------------------
  1990. // LLFloaterModelPreview::DecompRequest
  1991. //-----------------------------------------------------------------------------
  1992. LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage,
  1993. LLModel* mdl)
  1994. {
  1995. LLFloaterModelPreview* self = findInstance();
  1996. if (self && mdl)
  1997. {
  1998. mStage = stage;
  1999. mContinue = 1;
  2000. mModel = mdl;
  2001. mDecompID = &mdl->mDecompID;
  2002. mParams = self->mDecompParams;
  2003. // Copy out positions and indices
  2004. assignData(mdl);
  2005. }
  2006. }
  2007. S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status,
  2008. S32 p1, S32 p2)
  2009. {
  2010. if (mContinue)
  2011. {
  2012. setStatusMessage(llformat("%s: %d/%d", status, p1, p2));
  2013. }
  2014. return mContinue;
  2015. }
  2016. // Called from the main thread
  2017. void LLFloaterModelPreview::DecompRequest::completed()
  2018. {
  2019. LLFloaterModelPreview* self = LLFloaterModelPreview::findInstance();
  2020. if (mContinue)
  2021. {
  2022. mModel->setConvexHullDecomposition(mHull);
  2023. if (self)
  2024. {
  2025. if (mContinue)
  2026. {
  2027. if (self->mModelPreview)
  2028. {
  2029. self->mModelPreview->mDirty = true;
  2030. self->mModelPreview->refresh();
  2031. }
  2032. }
  2033. self->mCurRequest.erase(this);
  2034. }
  2035. }
  2036. else if (self)
  2037. {
  2038. llassert(self->mCurRequest.find(this) == self->mCurRequest.end());
  2039. }
  2040. }
  2041. //-----------------------------------------------------------------------------
  2042. // LLModelPreview
  2043. //-----------------------------------------------------------------------------
  2044. LLModelPreview::LLModelPreview(S32 width, S32 height,
  2045. LLFloaterModelPreview* fmp)
  2046. : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, false),
  2047. mFMP(fmp),
  2048. mModelLoader(NULL),
  2049. mPreviewLOD(0),
  2050. mMaxTriangleLimit(0),
  2051. mTextureName(0),
  2052. mGroup(0),
  2053. mPelvisZOffset(0.f),
  2054. mCameraZoom(1.f),
  2055. mCameraDistance(0.f),
  2056. mCameraYaw(0.f),
  2057. mCameraPitch(0.f),
  2058. mBuildShareTolerance(0.f),
  2059. mBuildQueueMode(GLOD_QUEUE_GREEDY),
  2060. mBuildBorderMode(GLOD_BORDER_UNLOCK),
  2061. mBuildOperator(GLOD_OPERATOR_EDGE_COLLAPSE),
  2062. mLegacyRigFlags(LEGACY_RIG_FLAG_INVALID),
  2063. mPhysicsSearchLOD(LLModel::LOD_PHYSICS),
  2064. mLoadState(LLModelLoader::STARTING),
  2065. mLoading(false),
  2066. mNeedsUpdate(true),
  2067. mDirty(false),
  2068. mGenLOD(false),
  2069. mLODFrozen(false),
  2070. mHasPivot(false),
  2071. mRigValidJointUpload(false),
  2072. mFirstSkinUpdate(true),
  2073. mResetJoints(false),
  2074. mLastJointUpdate(false),
  2075. mHasDegenerate(false),
  2076. mWarnPhysModel(false),
  2077. mImporterDebug(LLCachedControl<bool>(gSavedSettings, "MeshImporterDebug"))
  2078. {
  2079. for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
  2080. {
  2081. mRequestedTriangleCount[i] = 0;
  2082. mRequestedCreaseAngle[i] = -1.f;
  2083. mRequestedLoDMode[i] = 0;
  2084. mRequestedErrorThreshold[i] = 0.f;
  2085. mRequestedBuildOperator[i] = 0;
  2086. mRequestedQueueMode[i] = 0;
  2087. mRequestedBorderMode[i] = 0;
  2088. mRequestedShareTolerance[i] = 0.f;
  2089. }
  2090. mViewOption["show_textures"] = false;
  2091. glodInit();
  2092. createPreviewAvatar();
  2093. }
  2094. LLModelPreview::~LLModelPreview()
  2095. {
  2096. if (mModelLoader)
  2097. {
  2098. mModelLoader->shutdown();
  2099. mModelLoader = NULL;
  2100. }
  2101. if (mPreviewAvatar)
  2102. {
  2103. mPreviewAvatar->markDead();
  2104. }
  2105. mUploadData.clear();
  2106. mTextureSet.clear();
  2107. for (S32 i = 0; i < LLModel::NUM_LODS; ++i)
  2108. {
  2109. clearModel(i);
  2110. }
  2111. mBaseModel.clear();
  2112. mBaseScene.clear();
  2113. // Must call clearGLODGroup() before shutting GLOD down, else we get
  2114. // crashes later on in LLVOCachePartition/LLOctreeNode ! HB
  2115. clearGLODGroup();
  2116. // Note: I fixed GLOD to avoid yet another crash when calling this... HB
  2117. glodShutdown();
  2118. }
  2119. void LLModelPreview::updateDimentionsAndOffsets()
  2120. {
  2121. assert_main_thread();
  2122. if (!mFMP)
  2123. {
  2124. return;
  2125. }
  2126. rebuildUploadData();
  2127. mPelvisZOffset = mFMP->childGetValue("pelvis_offset").asReal();
  2128. if (mPreviewAvatar && mFMP->childGetValue("upload_joints").asBoolean())
  2129. {
  2130. // *FIXME: if preview avatar ever gets reused, this fake mesh Id stuff
  2131. // will fail. See also call to addAttachmentPosOverride().
  2132. LLUUID fake_mesh_id;
  2133. fake_mesh_id.generate();
  2134. mPreviewAvatar->addPelvisFixup(mPelvisZOffset, fake_mesh_id);
  2135. }
  2136. std::set<LLModel*> accounted;
  2137. for (U32 i = 0; i < mUploadData.size(); ++i)
  2138. {
  2139. LLModelInstance& instance = mUploadData[i];
  2140. if (accounted.find(instance.mModel) == accounted.end())
  2141. {
  2142. accounted.insert(instance.mModel);
  2143. // Update instance skin info for each lods pelvisZoffset
  2144. for (S32 j = 0; j < LLModel::NUM_LODS; ++j)
  2145. {
  2146. if (instance.mLOD[j])
  2147. {
  2148. instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;
  2149. }
  2150. }
  2151. }
  2152. }
  2153. F32 scale = mFMP->childGetValue("import_scale").asReal() * 2.f;
  2154. mDetailsSignal(mPreviewScale[0] * scale, mPreviewScale[1] * scale,
  2155. mPreviewScale[2] * scale);
  2156. updateStatusMessages();
  2157. }
  2158. bool LLModelPreview::matchMaterialOrder(LLModel* lod, LLModel* ref,
  2159. S32& ref_face_cnt, S32& model_face_cnt)
  2160. {
  2161. // Is this a subset ?
  2162. // LODs cannot currently add new materials, e.g.
  2163. // 1. ref = a,b,c lod1 = d,e => This is not permitted
  2164. // 2. ref = a,b,c lod1 = c => This would be permitted
  2165. if (!lod->isMaterialListSubset(ref))
  2166. {
  2167. std::ostringstream out;
  2168. out << "Materials of LOD model '" << lod->mLabel
  2169. << "' are not a subset of the High LOD (reference) model '"
  2170. << ref->mLabel << "'";
  2171. llwarns << out.str() << llendl;
  2172. mFMP->addLineToLog(out.str());
  2173. return false;
  2174. }
  2175. LL_DEBUGS("MeshUpload") << "Subset check passed." << LL_ENDL;
  2176. // Build a map of material slot names to face indexes
  2177. std::map<std::string, U32> index_map;
  2178. bool reorder = false;
  2179. auto max_lod_mats = lod->mMaterialList.size();
  2180. for (U32 i = 0, count = ref->mMaterialList.size(); i < count; ++i)
  2181. {
  2182. // Create the reference map for later
  2183. index_map[ref->mMaterialList[i]] = i;
  2184. LL_DEBUGS("MeshUpload") << "Setting reference material "
  2185. << ref->mMaterialList[i] << " as index " << i
  2186. << LL_ENDL;
  2187. if (i >= max_lod_mats ||
  2188. lod->mMaterialList[i] != ref->mMaterialList[i])
  2189. {
  2190. // i is already out of range of the original material sets in this
  2191. // LOD or is not matching.
  2192. LL_DEBUGS("MeshUpload") << "Mismatch at " << i << " "
  2193. << ref->mMaterialList[i] << " != "
  2194. << (i >= max_lod_mats ? "Out-of-range"
  2195. : lod->mMaterialList[i])
  2196. << LL_ENDL;
  2197. // We have a misalignment/ordering; check that ref[i] is in cur and
  2198. // if not add a blank.
  2199. U32 j = 0;
  2200. for ( ; j < max_lod_mats; ++j)
  2201. {
  2202. if (i != j && lod->mMaterialList[j] == ref->mMaterialList[i])
  2203. {
  2204. LL_DEBUGS("MeshUpload") << "Material "
  2205. << ref->mMaterialList[i]
  2206. << " found at " << j << LL_ENDL;
  2207. // We found it but in the wrong place.
  2208. reorder = true;
  2209. break;
  2210. }
  2211. }
  2212. if (j >= max_lod_mats)
  2213. {
  2214. std::ostringstream out;
  2215. out << "Material " << ref->mMaterialList[i]
  2216. << " not found in lod adding placeholder.";
  2217. LL_DEBUGS("MeshUpload") << out.str() << LL_ENDL;
  2218. if (mImporterDebug)
  2219. {
  2220. mFMP->addLineToLog(out.str());
  2221. }
  2222. // The material is not in the sub-mesh, add a placeholder.
  2223. // This is appended to the existing data so we will need to
  2224. // reorder. Note that this placeholder will be eliminated on
  2225. // upload and replaced with "NoGeometry" in the LLSD.
  2226. reorder = true;
  2227. LLVolumeFace face;
  2228. face.resizeIndices(3);
  2229. face.resizeVertices(1);
  2230. face.mPositions->clear();
  2231. face.mNormals->clear();
  2232. face.mTexCoords->clear();
  2233. memset((void*)face.mIndices, 0, sizeof(U16)*3);
  2234. lod->addFace(face);
  2235. lod->mMaterialList.push_back(ref->mMaterialList[i]);
  2236. }
  2237. }
  2238. // If any material name does not match reference, we need to reorder
  2239. }
  2240. LL_DEBUGS("MeshUpload") << "Finished parsing materials";
  2241. for (U32 i = 0, count = lod->mMaterialList.size(); i < count; ++i)
  2242. {
  2243. LL_CONT << "LOD material " << lod->mMaterialList[i] << " has index "
  2244. << i;
  2245. }
  2246. LL_CONT << LL_ENDL;
  2247. // Sanity check. We have added placeholders for any mats in ref that are
  2248. // not in this. The mat count MUST be equal now.
  2249. if (lod->mMaterialList.size() != ref->mMaterialList.size())
  2250. {
  2251. std::ostringstream out;
  2252. out << "Materials of LOD model '" << lod->mLabel
  2253. << "' has more materials than the reference '"
  2254. << ref->mLabel << "'";
  2255. llwarns << out.str() << llendl;
  2256. mFMP->addLineToLog(out.str());
  2257. return false;
  2258. }
  2259. if (reorder)
  2260. {
  2261. LL_DEBUGS("MeshUpload") << "Re-ordering." << LL_ENDL;
  2262. lod->sortVolumeFacesByMaterialName();
  2263. lod->mMaterialList = ref->mMaterialList;
  2264. }
  2265. return true;
  2266. }
  2267. void LLModelPreview::rebuildUploadData()
  2268. {
  2269. assert_main_thread();
  2270. if (!mFMP)
  2271. {
  2272. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  2273. return;
  2274. }
  2275. mUploadData.clear();
  2276. mTextureSet.clear();
  2277. // Fill uploaddata instance vectors from scene data
  2278. std::string requested_name =
  2279. mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
  2280. LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
  2281. F32 scale = scale_spinner->getValue().asReal();
  2282. LLMatrix4 scale_mat;
  2283. scale_mat.initScale(LLVector3(scale, scale, scale));
  2284. F32 max_scale = 0.f;
  2285. U32 load_state = 0;
  2286. mFMP->mCalculateBtn->setEnabled(true);
  2287. bool legacy_matching = gSavedSettings.getBool("ImporterLegacyMatching");
  2288. for (LLModelLoader::scene::iterator iter = mBaseScene.begin();
  2289. iter != mBaseScene.end(); ++iter)
  2290. {
  2291. // For each transform in scene
  2292. LLMatrix4 mat = iter->first;
  2293. // Compute position
  2294. LLVector3 position = LLVector3::zero * mat;
  2295. // Compute scale
  2296. LLVector3 x_tf = LLVector3::x_axis * mat - position;
  2297. LLVector3 y_tf = LLVector3::y_axis * mat - position;
  2298. LLVector3 z_tf = LLVector3::z_axis * mat - position;
  2299. F32 x_length = x_tf.normalize();
  2300. if (x_length > max_scale)
  2301. {
  2302. max_scale = x_length;
  2303. }
  2304. F32 y_length = y_tf.normalize();
  2305. if (y_length > max_scale)
  2306. {
  2307. max_scale = y_length;
  2308. }
  2309. F32 z_length = z_tf.normalize();
  2310. if (z_length > max_scale)
  2311. {
  2312. max_scale = z_length;
  2313. }
  2314. mat *= scale_mat;
  2315. for (LLModelLoader::model_instance_list_t::iterator
  2316. mit = iter->second.begin();
  2317. mit != iter->second.end(); )
  2318. {
  2319. // For each instance with said transform applied
  2320. LLModelInstance instance = *mit++;
  2321. LLModel* base_model = instance.mModel;
  2322. if (base_model && !requested_name.empty())
  2323. {
  2324. base_model->mRequestedLabel = requested_name;
  2325. }
  2326. for (S32 i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR;
  2327. --i)
  2328. {
  2329. LLModel* lod_model = NULL;
  2330. if (!legacy_matching)
  2331. {
  2332. // Fill LOD slots by finding matching meshes by label with
  2333. // name extensions in the appropriate scene for each LOD.
  2334. // This fixes all kinds of issues where the indexed method
  2335. // below fails in spectacular fashion. If you do not take
  2336. // the time to name your LOD and PHYS meshes with the name
  2337. // of their corresponding mesh in the HIGH LOD, then the
  2338. // indexed method will be attempted below.
  2339. std::string name_to_match = instance.mLabel;
  2340. llassert(!name_to_match.empty());
  2341. S32 extension_lod;
  2342. if (i != LLModel::LOD_PHYSICS ||
  2343. mModel[LLModel::LOD_PHYSICS].empty())
  2344. {
  2345. extension_lod = i;
  2346. }
  2347. else
  2348. {
  2349. // Physics can be inherited from other LODs or loaded,
  2350. // so we need to adjust what extension we are searching
  2351. // for
  2352. extension_lod = mPhysicsSearchLOD;
  2353. }
  2354. std::string suffix = get_lod_suffix(extension_lod);
  2355. if (name_to_match.find(suffix) == std::string::npos)
  2356. {
  2357. name_to_match += suffix;
  2358. }
  2359. LLMatrix4 transform;
  2360. find_model(mScene[i], name_to_match, lod_model, transform);
  2361. if (!lod_model && i != LLModel::LOD_PHYSICS)
  2362. {
  2363. if (mImporterDebug)
  2364. {
  2365. std::ostringstream out;
  2366. out << "Search of " << name_to_match
  2367. << " in LOD" << i
  2368. << " list failed. Searching for alternative among LOD lists.";
  2369. llinfos << out.str() << llendl;
  2370. mFMP->addLineToLog(out.str());
  2371. }
  2372. S32 search_lod = i > LLModel::LOD_HIGH ? LLModel::LOD_HIGH
  2373. : i;
  2374. while (search_lod <= LLModel::LOD_HIGH && !lod_model)
  2375. {
  2376. std::string name_to_match = instance.mLabel;
  2377. llassert(!name_to_match.empty());
  2378. suffix = get_lod_suffix(search_lod);
  2379. if (name_to_match.find(suffix) == std::string::npos)
  2380. {
  2381. name_to_match += suffix;
  2382. }
  2383. // See if we can find an appropriately named model
  2384. // in LOD 'search_lod'
  2385. find_model(mScene[search_lod], name_to_match,
  2386. lod_model, transform);
  2387. ++search_lod;
  2388. }
  2389. }
  2390. }
  2391. else
  2392. {
  2393. // Use old method of index-based association
  2394. S32 idx = 0;
  2395. S32 count = mBaseModel.size();
  2396. for (idx = 0; idx < count; ++idx)
  2397. {
  2398. // Find reference instance for this model
  2399. if (mBaseModel[idx] == base_model)
  2400. {
  2401. if (mImporterDebug)
  2402. {
  2403. std::ostringstream out;
  2404. out << "Attempting to use model index "
  2405. << idx << " for LOD " << i << " of "
  2406. << instance.mLabel;
  2407. llinfos << out.str() << llendl;
  2408. mFMP->addLineToLog(out.str());
  2409. }
  2410. break;
  2411. }
  2412. }
  2413. // If the model list for the current LOD includes that index...
  2414. if ((S32)mModel[i].size() > idx)
  2415. {
  2416. // Assign that index from the model list for our LOD as
  2417. // the LOD model for this instance
  2418. lod_model = mModel[i][idx];
  2419. if (mImporterDebug)
  2420. {
  2421. std::ostringstream out;
  2422. out << "Indexed match of model index " << idx
  2423. << " at LOD " << i << " to model named "
  2424. << lod_model->mLabel;
  2425. llinfos << out.str() << llendl;
  2426. mFMP->addLineToLog(out.str());
  2427. }
  2428. }
  2429. else if (mImporterDebug)
  2430. {
  2431. std::ostringstream out;
  2432. out << "List of models does not include index " << idx;
  2433. llinfos << out.str() << llendl;
  2434. mFMP->addLineToLog(out.str());
  2435. }
  2436. }
  2437. if (!lod_model && i == LLModel::LOD_PHYSICS && mWarnPhysModel)
  2438. {
  2439. // Despite the various strategies above, if we do not now
  2440. // have a physics model, we are going to end up with the
  2441. // decomposition. It is OK, but might not be what they
  2442. // wanted. Use default_physics_shape instead if found.
  2443. std::ostringstream out;
  2444. out << "No physics model specified for: "
  2445. << instance.mLabel;
  2446. if (mDefaultPhysModel.notNull())
  2447. {
  2448. out << ". Using: " << DEFAULT_PHYSICS_MESH_NAME;
  2449. lod_model = mDefaultPhysModel;
  2450. }
  2451. llwarns << out.str() << llendl;
  2452. // Flash log tab if no default available.
  2453. mFMP->addLineToLog(out.str(), mDefaultPhysModel.isNull());
  2454. }
  2455. if (lod_model)
  2456. {
  2457. if (mImporterDebug)
  2458. {
  2459. std::ostringstream out;
  2460. if (i == LLModel::LOD_PHYSICS)
  2461. {
  2462. out << "Assigning collision for "
  2463. << instance.mLabel << " to match "
  2464. << lod_model->mLabel;
  2465. }
  2466. else
  2467. {
  2468. out << "Assigning LOD" << i << " for "
  2469. << instance.mLabel << " to found match "
  2470. << lod_model->mLabel;
  2471. }
  2472. llinfos << out.str() << llendl;
  2473. mFMP->addLineToLog(out.str());
  2474. }
  2475. instance.mLOD[i] = lod_model;
  2476. }
  2477. else
  2478. {
  2479. if (i < LLModel::LOD_HIGH && !lodsReady())
  2480. {
  2481. // Assign a placeholder from previous LOD until lod
  2482. // generation is complete. Note: we might need to
  2483. // assign it regardless of conditions like named search
  2484. // does, to prevent crashes.
  2485. instance.mLOD[i] = instance.mLOD[i + 1];
  2486. }
  2487. if (mImporterDebug)
  2488. {
  2489. std::ostringstream out;
  2490. out << "List of models does not include "
  2491. << instance.mLabel;
  2492. llinfos << out.str() << llendl;
  2493. mFMP->addLineToLog(out.str());
  2494. }
  2495. }
  2496. }
  2497. LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH];
  2498. if (!high_lod_model)
  2499. {
  2500. load_state = LLModelLoader::ERROR_HIGH_LOD_MODEL_MISSING;
  2501. mFMP->mCalculateBtn->setEnabled(false);
  2502. mFMP->addLineToLog("Model " + instance.mLabel +
  2503. " has no High Lod (LOD3).", true);
  2504. }
  2505. else
  2506. {
  2507. for (S32 i = 0; i < LLModel::NUM_LODS - 1; ++i)
  2508. {
  2509. if (!instance.mLOD[i])
  2510. {
  2511. llwarns << "NULL LOD" << i << " found ! Skipping."
  2512. << llendl;
  2513. llassert(false);
  2514. continue;
  2515. }
  2516. S32 ref_face_cnt = 0;
  2517. S32 model_face_cnt = 0;
  2518. if (!matchMaterialOrder(instance.mLOD[i], high_lod_model,
  2519. ref_face_cnt, model_face_cnt))
  2520. {
  2521. load_state = LLModelLoader::ERROR_MATERIALS;
  2522. mFMP->mCalculateBtn->setEnabled(false);
  2523. mFMP->addLineToLog("Model " + instance.mLabel +
  2524. " has mismatching materials between LODs.",
  2525. true);
  2526. }
  2527. }
  2528. }
  2529. if (mFMP->childGetValue("upload_skin").asBoolean() &&
  2530. high_lod_model->mSkinInfo.mJointNames.size() > 0)
  2531. {
  2532. const LLMatrix4& bind_shape_mat =
  2533. high_lod_model->mSkinInfo.mBindShapeMatrix;
  2534. LLQuaternion bind_rot =
  2535. LLSkinningUtil::getUnscaledQuaternion(bind_shape_mat);
  2536. LLQuaternion identity;
  2537. if (!bind_rot.isEqualEps(identity, 0.01f))
  2538. {
  2539. std::ostringstream out;
  2540. out << "Non-identity bind shape rotation matrix is: "
  2541. << bind_shape_mat << " - bind_rot = " << bind_rot;
  2542. mFMP->addLineToLog(out.str(), true);
  2543. llwarns << out.str() << llendl;
  2544. load_state = LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION;
  2545. }
  2546. }
  2547. instance.mTransform = mat;
  2548. mUploadData.push_back(instance);
  2549. }
  2550. }
  2551. for (S32 lod = 0; lod < LLModel::NUM_LODS - 1; ++lod)
  2552. {
  2553. // Search for models that are not included into upload data. If we find
  2554. // any, that means something we loaded is not a sub-model.
  2555. for (S32 model_ind = 0, model_cnt = mModel[lod].size();
  2556. model_ind < model_cnt; ++model_ind)
  2557. {
  2558. bool found_model = false;
  2559. for (LLMeshUploadThread::instance_list_t::iterator
  2560. iter = mUploadData.begin(), end = mUploadData.end();
  2561. iter != end; ++iter)
  2562. {
  2563. LLModelInstance& instance = *iter;
  2564. if (instance.mLOD[lod] == mModel[lod][model_ind])
  2565. {
  2566. found_model = true;
  2567. break;
  2568. }
  2569. }
  2570. if (!found_model && mModel[lod][model_ind] &&
  2571. !mModel[lod][model_ind]->mSubmodelID)
  2572. {
  2573. if (mImporterDebug)
  2574. {
  2575. std::ostringstream out;
  2576. out << "Model " << mModel[lod][model_ind]->mLabel
  2577. << " was not used; mismatching lod models.";
  2578. llinfos << out.str() << llendl;
  2579. mFMP->addLineToLog(out.str());
  2580. }
  2581. load_state = LLModelLoader::ERROR_MATERIALS;
  2582. mFMP->mCalculateBtn->setEnabled(false);
  2583. }
  2584. }
  2585. }
  2586. F32 max_import_scale;
  2587. if (max_scale > 0.f)
  2588. {
  2589. max_import_scale = (LLManipScale::maxPrimScale() - 0.1f) / max_scale;
  2590. }
  2591. else
  2592. {
  2593. max_import_scale = 1.f;
  2594. }
  2595. F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
  2596. max_axis = llmax(max_axis, mPreviewScale.mV[2]);
  2597. max_axis *= 2.f;
  2598. // Clamp scale so that total imported model bounding box is smaller than
  2599. // 240m on a side
  2600. max_import_scale = llmin(max_import_scale, 240.f / max_axis);
  2601. scale_spinner->setMaxValue(max_import_scale);
  2602. if (max_import_scale < scale)
  2603. {
  2604. scale_spinner->setValue(max_import_scale);
  2605. }
  2606. if (load_state)
  2607. {
  2608. // We Encountered an issue during this call
  2609. setLoadState(load_state);
  2610. //updateStatusMessages();
  2611. }
  2612. else //if (mModelNoErrors)
  2613. {
  2614. // No issue now: was there an issue last time ?
  2615. load_state = getLoadState();
  2616. if (load_state == LLModelLoader::ERROR_MATERIALS ||
  2617. load_state == LLModelLoader::ERROR_HIGH_LOD_MODEL_MISSING ||
  2618. load_state == LLModelLoader::ERROR_LOD_MODEL_MISMATCH ||
  2619. load_state == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION)
  2620. {
  2621. // In these specific cases, this should now be fixed since no
  2622. // error was detected at this call...
  2623. setLoadState(LLModelLoader::DONE);
  2624. //updateStatusMessages();
  2625. }
  2626. }
  2627. }
  2628. void LLModelPreview::saveUploadData(bool save_skinweights,
  2629. bool save_joint_positions,
  2630. bool lock_scale_if_joint_pos)
  2631. {
  2632. if (!mLODFile[LLModel::LOD_HIGH].empty())
  2633. {
  2634. std::string filename = mLODFile[LLModel::LOD_HIGH];
  2635. std::string slm_filename;
  2636. if (LLModelLoader::getSLMFilename(filename, slm_filename))
  2637. {
  2638. saveUploadData(slm_filename, save_skinweights,
  2639. save_joint_positions, lock_scale_if_joint_pos);
  2640. }
  2641. }
  2642. }
  2643. void LLModelPreview::saveUploadData(const std::string& filename,
  2644. bool save_skinweights,
  2645. bool save_joint_positions,
  2646. bool lock_scale_if_joint_pos)
  2647. {
  2648. std::set<LLPointer<LLModel> > meshes;
  2649. std::map<LLModel*, std::string> mesh_binary;
  2650. LLModel::hull empty_hull;
  2651. LLSD data;
  2652. data["version"] = SLM_SUPPORTED_VERSION;
  2653. if (!mBaseModel.empty())
  2654. {
  2655. data["name"] = mBaseModel[0]->getName();
  2656. }
  2657. S32 mesh_id = 0;
  2658. // Build list of unique models and initialize local id
  2659. for (U32 i = 0; i < mUploadData.size(); ++i)
  2660. {
  2661. LLModelInstance& instance = mUploadData[i];
  2662. if (meshes.find(instance.mModel) == meshes.end())
  2663. {
  2664. instance.mModel->mLocalID = mesh_id++;
  2665. meshes.emplace(instance.mModel);
  2666. std::stringstream str;
  2667. LLModel::Decomposition& decomp =
  2668. instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
  2669. instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
  2670. instance.mModel->mPhysics;
  2671. LLModel::writeModel(str,
  2672. instance.mLOD[LLModel::LOD_PHYSICS],
  2673. instance.mLOD[LLModel::LOD_HIGH],
  2674. instance.mLOD[LLModel::LOD_MEDIUM],
  2675. instance.mLOD[LLModel::LOD_LOW],
  2676. instance.mLOD[LLModel::LOD_IMPOSTOR],
  2677. decomp, save_skinweights, save_joint_positions,
  2678. lock_scale_if_joint_pos, false, true,
  2679. instance.mModel->mSubmodelID);
  2680. data["mesh"][instance.mModel->mLocalID] = str.str();
  2681. }
  2682. data["instance"][i] = instance.asLLSD();
  2683. }
  2684. llofstream out(filename.c_str(),
  2685. std::ios_base::out | std::ios_base::binary);
  2686. if (out.is_open())
  2687. {
  2688. LLSDSerialize::toBinary(data, out);
  2689. out.flush();
  2690. out.close();
  2691. }
  2692. else
  2693. {
  2694. llwarns << "Could not open file '" << filename << "' for writing."
  2695. << llendl;
  2696. }
  2697. }
  2698. void LLModelPreview::clearModel(S32 lod)
  2699. {
  2700. if (lod >= 0 && lod <= LLModel::LOD_PHYSICS)
  2701. {
  2702. mVertexBuffer[lod].clear();
  2703. mModel[lod].clear();
  2704. mScene[lod].clear();
  2705. }
  2706. }
  2707. // Gets all standard skeleton joints from the preview avatar.
  2708. void LLModelPreview::getJointAliases(JointMap& joint_map)
  2709. {
  2710. if (!mPreviewAvatar)
  2711. {
  2712. joint_map.clear();
  2713. return;
  2714. }
  2715. joint_map = mPreviewAvatar->getJointAliases();
  2716. std::vector<std::string> joint_names;
  2717. mPreviewAvatar->getSortedJointNames(1, joint_names);
  2718. for (S32 i = 0, count = joint_names.size(); i < count; ++i)
  2719. {
  2720. const std::string& name = joint_names[i];
  2721. joint_map[name] = name;
  2722. }
  2723. mPreviewAvatar->getSortedJointNames(2, joint_names);
  2724. for (S32 i = 0, count = joint_names.size(); i < count; ++i)
  2725. {
  2726. const std::string& name = joint_names[i];
  2727. joint_map[name] = name;
  2728. }
  2729. }
  2730. void LLModelPreview::loadModel(std::string filename, S32 lod,
  2731. bool force_disable_slm, bool allow_preprocess)
  2732. {
  2733. assert_main_thread();
  2734. if (!mFMP)
  2735. {
  2736. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  2737. return;
  2738. }
  2739. LLMutexLock lock(this);
  2740. if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::NUM_LODS - 1)
  2741. {
  2742. std::ostringstream out;
  2743. out << "Invalid level of detail: " << lod;
  2744. llwarns << out.str() << llendl;
  2745. llassert(false);
  2746. mFMP->addLineToLog(out.str());
  2747. return;
  2748. }
  2749. bool init_decomp = mBaseModel.empty();
  2750. // This triggers if you bring up the file selector and then hit CANCEL.
  2751. // Just use the previous model (if any) and ignore that you brought up the
  2752. // file selector.
  2753. if (filename.empty())
  2754. {
  2755. if (init_decomp)
  2756. {
  2757. // This is the initial file picking. Close the whole floater if we
  2758. // do not have a base model to show for high LOD.
  2759. mFMP->close();
  2760. mLoading = false;
  2761. }
  2762. return;
  2763. }
  2764. if (mModelLoader)
  2765. {
  2766. llwarns << "Incompleted model load operation pending." << llendl;
  2767. return;
  2768. }
  2769. mLODFile[lod] = filename;
  2770. if (lod == LLModel::LOD_HIGH)
  2771. {
  2772. clearGLODGroup();
  2773. }
  2774. std::map<std::string, std::string> joint_alias_map;
  2775. getJointAliases(joint_alias_map);
  2776. if (gDirUtil.getExtension(filename) == "dae")
  2777. {
  2778. bool preprocess = allow_preprocess &&
  2779. gSavedSettings.getBool("ImporterPreprocessDAE");
  2780. U32 model_limit = gSavedSettings.getU32("ImporterModelLimit");
  2781. mModelLoader = new LLDAELoader(filename, lod, loadedCallback,
  2782. lookupJointByName, loadTextures,
  2783. stateChangedCallback, this,
  2784. mJointTransformMap, mJointsFromNode,
  2785. joint_alias_map,
  2786. LL_MAX_JOINTS_PER_MESH_OBJECT,
  2787. model_limit, preprocess);
  2788. }
  2789. else
  2790. {
  2791. mModelLoader = new LLGLTFLoader(filename, lod, loadedCallback,
  2792. lookupJointByName, loadTextures,
  2793. stateChangedCallback, this,
  2794. mJointTransformMap, mJointsFromNode,
  2795. joint_alias_map,
  2796. LL_MAX_JOINTS_PER_MESH_OBJECT);
  2797. }
  2798. if (force_disable_slm)
  2799. {
  2800. mModelLoader->mTrySLM = false;
  2801. }
  2802. else
  2803. {
  2804. // Only try to load from slm if viewer is configured to do so and this
  2805. // is the initial model load (not an LoD or physics shape).
  2806. // Note: trying to re-use SLM files has never worked properly; in
  2807. // particular, it tends to force the UI into strange checkbox options
  2808. // which cannot be altered. So better keeping MeshImportUseSLM false...
  2809. mModelLoader->mTrySLM = gSavedSettings.getBool("MeshImportUseSLM") &&
  2810. mUploadData.empty();
  2811. }
  2812. mModelLoader->start();
  2813. mFMP->childSetTextArg("status", "[STATUS]",
  2814. mFMP->getString("status_reading_file"));
  2815. setPreviewLOD(lod);
  2816. if (mLoadState >= LLModelLoader::ERROR_PARSING)
  2817. {
  2818. mFMP->mUploadBtn->setEnabled(false);
  2819. mFMP->mCalculateBtn->setEnabled(false);
  2820. }
  2821. if (lod == mPreviewLOD)
  2822. {
  2823. std::string wname = "lod_file_" + lod_name[lod];
  2824. mFMP->childSetText(wname.c_str(), mLODFile[lod]);
  2825. }
  2826. else if (lod == LLModel::LOD_PHYSICS)
  2827. {
  2828. mFMP->childSetText("physics_file", mLODFile[lod]);
  2829. }
  2830. // Pre-fill a default name for the uploaded model
  2831. if (lod != LLModel::LOD_PHYSICS)
  2832. {
  2833. LLLineEditor* desc = mFMP->getChild<LLLineEditor>("description_form");
  2834. desc->setValue(gDirUtil.getBaseFileName(filename, true));
  2835. }
  2836. mFMP->open();
  2837. }
  2838. void LLModelPreview::setPhysicsFromLOD(S32 lod)
  2839. {
  2840. assert_main_thread();
  2841. if (!mFMP) return;
  2842. #if 0 // *TODO: find a way to get rid of the loaded physics decomp when
  2843. // reverting to no LOD ("Choose" entry in the physics combo). The
  2844. // following code is insufficient.
  2845. if (lod < 0)
  2846. {
  2847. mPhysicsSearchLOD = LLModel::LOD_PHYSICS;
  2848. mModel[LLModel::LOD_PHYSICS].clear();
  2849. mScene[LLModel::LOD_PHYSICS].clear();
  2850. mVertexBuffer[LLModel::LOD_PHYSICS].clear();
  2851. mFMP->childSetText("physics_file", "");
  2852. rebuildUploadData();
  2853. refresh();
  2854. updateStatusMessages();
  2855. }
  2856. else if (lod <= 3)
  2857. #else
  2858. if (lod >= 0 && lod <= 3)
  2859. #endif
  2860. {
  2861. mPhysicsSearchLOD = lod;
  2862. mModel[LLModel::LOD_PHYSICS] = mModel[lod];
  2863. mScene[LLModel::LOD_PHYSICS] = mScene[lod];
  2864. mLODFile[LLModel::LOD_PHYSICS].clear();
  2865. mFMP->childSetText("physics_file", mLODFile[LLModel::LOD_PHYSICS]);
  2866. mVertexBuffer[LLModel::LOD_PHYSICS].clear();
  2867. rebuildUploadData();
  2868. refresh();
  2869. updateStatusMessages();
  2870. }
  2871. }
  2872. void LLModelPreview::clearIncompatible(S32 lod)
  2873. {
  2874. // Do not discard models if specified model is the physic rep
  2875. if (lod == LLModel::LOD_PHYSICS)
  2876. {
  2877. return;
  2878. }
  2879. bool replaced_base_model = lod == LLModel::LOD_HIGH;
  2880. // At this point we do not care about sub-models, different amount of
  2881. // sub-models means face count mismatch, not incompatibility
  2882. U32 lod_size = countRootModels(mModel[lod]);
  2883. for (S32 i = 0; i <= LLModel::LOD_HIGH; ++i)
  2884. {
  2885. // Clear out any entries that are not compatible with this model
  2886. if (i != lod)
  2887. {
  2888. if (countRootModels(mModel[i]) != lod_size)
  2889. {
  2890. mModel[i].clear();
  2891. mScene[i].clear();
  2892. mVertexBuffer[i].clear();
  2893. if (i == LLModel::LOD_HIGH)
  2894. {
  2895. mBaseModel = mModel[lod];
  2896. clearGLODGroup();
  2897. mBaseScene = mScene[lod];
  2898. mVertexBuffer[5].clear();
  2899. replaced_base_model = true;
  2900. }
  2901. }
  2902. }
  2903. }
  2904. if (!replaced_base_model || mGenLOD)
  2905. {
  2906. return;
  2907. }
  2908. // Remove any previously scheduled work
  2909. mLodsQuery.clear();
  2910. std::string cname;
  2911. for (S32 i = LLModel::LOD_HIGH; i >= 0; --i)
  2912. {
  2913. if ((replaced_base_model && i != lod) ||
  2914. (!replaced_base_model && mModel[i].empty()))
  2915. {
  2916. // Base model was replaced, regenerate this lod if applicable
  2917. cname = "lod_source_" + lod_name[i];
  2918. S32 lod_mode =
  2919. mFMP->getChild<LLComboBox>(cname.c_str())->getCurrentIndex();
  2920. if (lod_mode != LOD_FROM_FILE)
  2921. {
  2922. mLodsQuery.push_back(i);
  2923. }
  2924. }
  2925. }
  2926. if (!mLodsQuery.empty())
  2927. {
  2928. doOnIdleRepeating(lodQueryCallback);
  2929. }
  2930. }
  2931. void LLModelPreview::clearGLODGroup()
  2932. {
  2933. if (!mGroup) return;
  2934. for (std::map<LLPointer<LLModel>, U32>::iterator it = mObject.begin(),
  2935. end = mObject.end();
  2936. it != end; ++it)
  2937. {
  2938. glodDeleteObject(it->second);
  2939. stop_gloderror();
  2940. }
  2941. mObject.clear();
  2942. glodDeleteGroup(mGroup);
  2943. stop_gloderror();
  2944. mGroup = 0;
  2945. }
  2946. void LLModelPreview::loadModelCallback(S32 lod)
  2947. {
  2948. assert_main_thread();
  2949. if (!mFMP)
  2950. {
  2951. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  2952. return;
  2953. }
  2954. LLMutexLock lock(this);
  2955. if (!mModelLoader)
  2956. {
  2957. mLoading = false;
  2958. return;
  2959. }
  2960. const LLSD& log = mModelLoader->logOut();
  2961. for (LLSD::array_const_iterator it = log.beginArray(),
  2962. end = log.endArray();
  2963. it != end; ++it)
  2964. {
  2965. if (it->has("Message"))
  2966. {
  2967. mFMP->addMessageToLog(it->get("Message"), *it, lod, true);
  2968. }
  2969. }
  2970. mModelLoader->clearLog();
  2971. if (mLoadState >= LLModelLoader::ERROR_PARSING)
  2972. {
  2973. mLoading = false;
  2974. mModelLoader = NULL;
  2975. mLodsWithParsingError.push_back(lod);
  2976. return;
  2977. }
  2978. mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(),
  2979. mLodsWithParsingError.end(), lod),
  2980. mLodsWithParsingError.end());
  2981. if (mLodsWithParsingError.empty())
  2982. {
  2983. mFMP->mCalculateBtn->setEnabled(true);
  2984. }
  2985. // Copy determinations about rig so UI will reflect them
  2986. mRigValidJointUpload = mModelLoader->isRigValidForJointPositionUpload();
  2987. mLegacyRigFlags = mModelLoader->getLegacyRigFlags();
  2988. mModelLoader->loadTextures();
  2989. if (lod == -1)
  2990. {
  2991. // Populate all LoDs from model loader scene
  2992. mBaseModel.clear();
  2993. mBaseScene.clear();
  2994. bool skin_weights = false;
  2995. bool joint_positions = false;
  2996. bool lock_scale_if_joint_pos = false;
  2997. // For each LoD
  2998. for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
  2999. {
  3000. // Clear scene and model info
  3001. mScene[lod].clear();
  3002. mModel[lod].clear();
  3003. mVertexBuffer[lod].clear();
  3004. if (mModelLoader->mScene.begin()->second[0].mLOD[lod].notNull())
  3005. {
  3006. // If this LoD exists in the loaded scene, copy scene to
  3007. // current LoD
  3008. mScene[lod] = mModelLoader->mScene;
  3009. // Touch up copied scene to look like current LoD
  3010. for (LLModelLoader::scene::iterator iter = mScene[lod].begin();
  3011. iter != mScene[lod].end(); ++iter)
  3012. {
  3013. LLModelLoader::model_instance_list_t& list = iter->second;
  3014. for (LLModelLoader::model_instance_list_t::iterator
  3015. list_iter = list.begin();
  3016. list_iter != list.end(); ++list_iter)
  3017. {
  3018. // Override displayed model with current LoD
  3019. list_iter->mModel = list_iter->mLOD[lod];
  3020. if (!list_iter->mModel) continue;
  3021. // Add current model to current LoD's model list
  3022. // (LLModel::mLocalID makes a good vector index)
  3023. S32 idx = list_iter->mModel->mLocalID;
  3024. if ((S32)mModel[lod].size() <= idx)
  3025. {
  3026. // Stretch model list to fit model at given index
  3027. mModel[lod].resize(idx + 1);
  3028. }
  3029. mModel[lod][idx] = list_iter->mModel;
  3030. if (!list_iter->mModel->mSkinWeights.empty())
  3031. {
  3032. skin_weights = true;
  3033. if (!list_iter->mModel->mSkinInfo.mAlternateBindMatrix.empty())
  3034. {
  3035. joint_positions = true;
  3036. }
  3037. if (list_iter->mModel->mSkinInfo.mLockScaleIfJointPosition)
  3038. {
  3039. lock_scale_if_joint_pos = true;
  3040. }
  3041. }
  3042. }
  3043. }
  3044. }
  3045. }
  3046. if (skin_weights)
  3047. {
  3048. // Enable uploading/previewing of skin weights if present in the
  3049. // .slm file
  3050. mFMP->enableViewOption("show_skin_weight");
  3051. mViewOption["show_skin_weight"] = true;
  3052. mFMP->childSetValue("upload_skin", true);
  3053. }
  3054. if (joint_positions)
  3055. {
  3056. mFMP->enableViewOption("show_joint_overrides");
  3057. mViewOption["show_joint_overrides"] = true;
  3058. mFMP->enableViewOption("show_joint_positions");
  3059. mViewOption["show_joint_positions"] = true;
  3060. mFMP->enableViewOption("show_collision_volumes");
  3061. mViewOption["show_collision_volumes"] = true;
  3062. mFMP->childSetValue("upload_joints", true);
  3063. }
  3064. if (lock_scale_if_joint_pos)
  3065. {
  3066. mFMP->enableViewOption("lock_scale_if_joint_position");
  3067. mViewOption["lock_scale_if_joint_position"] = true;
  3068. mFMP->childSetValue("lock_scale_if_joint_position", true);
  3069. }
  3070. // Copy high lod to base scene for LoD generation
  3071. mBaseScene = mScene[LLModel::LOD_HIGH];
  3072. mBaseModel = mModel[LLModel::LOD_HIGH];
  3073. mDirty = true;
  3074. resetPreviewTarget();
  3075. }
  3076. else
  3077. {
  3078. // Only replace given LoD
  3079. mModel[lod] = mModelLoader->mModelList;
  3080. mScene[lod] = mModelLoader->mScene;
  3081. // Duplicate the model if it is an internal bounding box model
  3082. if (lod == LLModel::LOD_PHYSICS &&
  3083. // This makes sense for multiple models only
  3084. mBaseModel.size() > 1 &&
  3085. // Just on the off-chance
  3086. mModelLoader->mModelList.size() == 1 &&
  3087. mModelLoader->mScene.size() == 1 &&
  3088. gDirUtil.getBaseFileName(mModelLoader->mFilename) == "cube.dae")
  3089. {
  3090. // Create a copy of the just loaded model for each model in
  3091. // mBaseModel
  3092. const LLModel* origp = mModelLoader->mModelList.front();
  3093. const LLModelInstance& mi = mModelLoader->mScene.begin()->second.front();
  3094. for (size_t i = 1, count = mBaseModel.size(); i < count; ++i)
  3095. {
  3096. LLPointer<LLModel> modelp(new LLModel(origp->getParams(),
  3097. origp->getDetail()));
  3098. modelp->mLabel = origp->mLabel;
  3099. modelp->copyVolumeFaces(origp);
  3100. modelp->mPosition = origp->mPosition;
  3101. modelp->mMaterialList = origp->mMaterialList;
  3102. mModel[lod].push_back(modelp);
  3103. mScene[lod][mi.mTransform].push_back(LLModelInstance(modelp,
  3104. modelp->mLabel,
  3105. mi.mTransform,
  3106. mi.mMaterial));
  3107. }
  3108. }
  3109. mVertexBuffer[lod].clear();
  3110. setPreviewLOD(lod);
  3111. if (lod == LLModel::LOD_HIGH)
  3112. {
  3113. // Save a copy of the highest LOD for automatic LOD manipulation
  3114. if (mBaseModel.empty())
  3115. {
  3116. // First time we have loaded a model, auto-gen LoD
  3117. mGenLOD = true;
  3118. }
  3119. mBaseModel = mModel[lod];
  3120. clearGLODGroup();
  3121. mBaseScene = mScene[lod];
  3122. mVertexBuffer[5].clear();
  3123. }
  3124. else
  3125. {
  3126. LLMatrix4 t; // For ignored transform matrix
  3127. if (lod == LLModel::LOD_PHYSICS)
  3128. {
  3129. // Explicitly loading physics. See if there is a default mesh.
  3130. LLModel* out_model = NULL;
  3131. std::string name = DEFAULT_PHYSICS_MESH_NAME +
  3132. get_lod_suffix(lod);
  3133. find_model(mScene[lod], name, out_model, t);
  3134. mDefaultPhysModel = out_model;
  3135. mWarnPhysModel = true;
  3136. }
  3137. if (!mBaseModel.empty() &&
  3138. !gSavedSettings.getBool("ImporterLegacyMatching"))
  3139. {
  3140. bool name_based = false;
  3141. bool has_submodels = false;
  3142. for (S32 idx = 0, cnt = mBaseModel.size(); idx < cnt; ++idx)
  3143. {
  3144. if (mBaseModel[idx]->mSubmodelID)
  3145. {
  3146. // Do not do index-based renaming when the base model
  3147. // has sub-models
  3148. has_submodels = true;
  3149. if (mImporterDebug)
  3150. {
  3151. llinfos << "High LOD has submodels" << llendl;
  3152. mFMP->addLineToLog("High LOD has submodels");
  3153. }
  3154. break;
  3155. }
  3156. }
  3157. for (S32 idx = 0, cnt = mModel[lod].size(); idx < cnt; ++idx)
  3158. {
  3159. std::string loaded_name =
  3160. strip_lod_suffix(mModel[lod][idx]->mLabel);
  3161. LLModel* found_model = NULL;
  3162. find_model(mBaseScene, loaded_name, found_model, t);
  3163. if (found_model)
  3164. {
  3165. // Do not rename correctly named models (even if they
  3166. // are placed in a wrong order)
  3167. name_based = true;
  3168. }
  3169. if (mModel[lod][idx]->mSubmodelID)
  3170. {
  3171. // Do not rename the models when loaded LOD model has
  3172. // sub-models
  3173. has_submodels = true;
  3174. }
  3175. }
  3176. if (mImporterDebug)
  3177. {
  3178. std::ostringstream out;
  3179. out << "Loaded LOD" << lod << ": correct names"
  3180. << (name_based ? "" : "NOT ") << "found; submodels "
  3181. << (has_submodels ? "" : "NOT ") << "found.";
  3182. llinfos << out.str() << llendl;
  3183. mFMP->addLineToLog(out.str());
  3184. }
  3185. if (!name_based && !has_submodels)
  3186. {
  3187. // Replace the name of the model loaded for any non HIGH
  3188. // LOD to match the others (MAINT-5601); this actually
  3189. // works like "ImporterLegacyMatching" for this particular
  3190. // LOD
  3191. std::string name, loaded_name;
  3192. for (size_t idx = 0;
  3193. idx < mModel[lod].size() && idx < mBaseModel.size();
  3194. ++idx)
  3195. {
  3196. name = mBaseModel[idx]->mLabel;
  3197. loaded_name =
  3198. strip_lod_suffix(mModel[lod][idx]->mLabel);
  3199. if (loaded_name != name)
  3200. {
  3201. name += get_lod_suffix(lod);
  3202. if (mImporterDebug)
  3203. {
  3204. std::ostringstream out;
  3205. out << "Loded model name "
  3206. << mModel[lod][idx]->mLabel
  3207. << " for LOD" << lod
  3208. << " does not match the base model. Renaming to "
  3209. << name;
  3210. llinfos << out.str() << llendl;
  3211. mFMP->addLineToLog(out.str());
  3212. }
  3213. mModel[lod][idx]->mLabel = name;
  3214. // Rename the corresponding instance as well
  3215. bool found = false;
  3216. for (auto& p : mScene[lod])
  3217. {
  3218. for (auto& i : p.second)
  3219. {
  3220. if (i.mModel == mModel[lod][idx])
  3221. {
  3222. i.mLabel = name;
  3223. found = true;
  3224. break;
  3225. }
  3226. }
  3227. if (found)
  3228. {
  3229. break;
  3230. }
  3231. }
  3232. }
  3233. }
  3234. }
  3235. }
  3236. }
  3237. clearIncompatible(lod);
  3238. mDirty = true;
  3239. if (lod == LLModel::LOD_HIGH)
  3240. {
  3241. resetPreviewTarget();
  3242. }
  3243. }
  3244. mLoading = false;
  3245. if (!mBaseModel.empty())
  3246. {
  3247. // Add info to log that loading is complete (purpose: separator
  3248. // between loading and other logs).
  3249. LLSD args;
  3250. args["MODEL_NAME"] = mBaseModel[0]->getName();
  3251. mFMP->addMessageToLog("ModelLoaded", args, lod);
  3252. }
  3253. refresh();
  3254. mModelLoadedSignal();
  3255. mModelLoader = NULL;
  3256. }
  3257. void LLModelPreview::resetPreviewTarget()
  3258. {
  3259. if (mModelLoader)
  3260. {
  3261. mPreviewTarget = (mModelLoader->mExtents[0] +
  3262. mModelLoader->mExtents[1]) * 0.5f;
  3263. mPreviewScale = (mModelLoader->mExtents[1] -
  3264. mModelLoader->mExtents[0]) * 0.5f;
  3265. }
  3266. setPreviewTarget(mPreviewScale.length() * 10.f);
  3267. }
  3268. void LLModelPreview::generateNormals()
  3269. {
  3270. assert_main_thread();
  3271. S32 which_lod = mPreviewLOD;
  3272. if (!mFMP || which_lod > 4 || which_lod < 0 || mModel[which_lod].empty())
  3273. {
  3274. return;
  3275. }
  3276. F32 angle_cutoff = mFMP->childGetValue("crease_angle").asReal();
  3277. mRequestedCreaseAngle[which_lod] = angle_cutoff;
  3278. angle_cutoff *= DEG_TO_RAD;
  3279. if (which_lod == 3 && !mBaseModel.empty())
  3280. {
  3281. if (mBaseModelFacesCopy.empty())
  3282. {
  3283. mBaseModelFacesCopy.reserve(mBaseModel.size());
  3284. for (LLModelLoader::model_list::iterator it = mBaseModel.begin(),
  3285. end = mBaseModel.end();
  3286. it != end; ++it)
  3287. {
  3288. v_LLVolumeFace_t faces;
  3289. (*it)->copyFacesTo(faces);
  3290. mBaseModelFacesCopy.emplace_back(faces);
  3291. }
  3292. }
  3293. for (LLModelLoader::model_list::iterator it = mBaseModel.begin(),
  3294. end = mBaseModel.end();
  3295. it != end; ++it)
  3296. {
  3297. (*it)->generateNormals(angle_cutoff);
  3298. }
  3299. mVertexBuffer[5].clear();
  3300. }
  3301. bool perform_copy = mModelFacesCopy[which_lod].empty();
  3302. if (perform_copy)
  3303. {
  3304. mModelFacesCopy[which_lod].reserve(mModel[which_lod].size());
  3305. }
  3306. for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(),
  3307. end = mModel[which_lod].end();
  3308. it != end; ++it)
  3309. {
  3310. if (perform_copy)
  3311. {
  3312. v_LLVolumeFace_t faces;
  3313. (*it)->copyFacesTo(faces);
  3314. mModelFacesCopy[which_lod].emplace_back(faces);
  3315. }
  3316. (*it)->generateNormals(angle_cutoff);
  3317. }
  3318. mVertexBuffer[which_lod].clear();
  3319. refresh();
  3320. updateStatusMessages();
  3321. }
  3322. void LLModelPreview::restoreNormals()
  3323. {
  3324. S32 which_lod = mPreviewLOD;
  3325. if (which_lod > 4 || which_lod < 0 || mModel[which_lod].empty())
  3326. {
  3327. return;
  3328. }
  3329. if (!mBaseModelFacesCopy.empty())
  3330. {
  3331. llassert(mBaseModelFacesCopy.size() == mBaseModel.size());
  3332. vv_LLVolumeFace_t::const_iterator itf = mBaseModelFacesCopy.begin();
  3333. for (LLModelLoader::model_list::iterator it = mBaseModel.begin(),
  3334. end = mBaseModel.end();
  3335. it != end; ++it, ++itf)
  3336. {
  3337. (*it)->copyFacesFrom((*itf));
  3338. }
  3339. mBaseModelFacesCopy.clear();
  3340. }
  3341. if (!mModelFacesCopy[which_lod].empty())
  3342. {
  3343. vv_LLVolumeFace_t::const_iterator itf = mModelFacesCopy[which_lod].begin();
  3344. for (LLModelLoader::model_list::iterator
  3345. it = mModel[which_lod].begin(), end = mModel[which_lod].end();
  3346. it != end; ++it, ++itf)
  3347. {
  3348. (*it)->copyFacesFrom((*itf));
  3349. }
  3350. mModelFacesCopy[which_lod].clear();
  3351. }
  3352. mVertexBuffer[which_lod].clear();
  3353. refresh();
  3354. updateStatusMessages();
  3355. }
  3356. // Helper class for GLOD setup and error recovery. HB
  3357. class HBGlodHelper
  3358. {
  3359. public:
  3360. HBGlodHelper(LLModelPreview* previewp)
  3361. : mPreviewp(previewp),
  3362. mShaderp(LLGLSLShader::sCurBoundShaderPtr)
  3363. {
  3364. LLVertexBuffer::unbind();
  3365. if (mShaderp)
  3366. {
  3367. mShaderp->unbind();
  3368. }
  3369. }
  3370. ~HBGlodHelper()
  3371. {
  3372. LLVertexBuffer::unbind();
  3373. if (mShaderp)
  3374. {
  3375. mShaderp->bind();
  3376. }
  3377. // *HACK: in case of error, cleanup GLOD and reinitialize it. HB
  3378. if (sHasGlodError)
  3379. {
  3380. // Must call clearGLODGroup() before shutting GLOD down, else we
  3381. // get crashes later on in LLVOCachePartition/LLOctreeNode ! HB
  3382. mPreviewp->clearGLODGroup();
  3383. // Note: I fixed GLOD to avoid yet another crash when calling
  3384. // this... HB
  3385. glodShutdown();
  3386. // Re-initialize GLOD
  3387. glodInit();
  3388. }
  3389. }
  3390. private:
  3391. LLModelPreview* mPreviewp;
  3392. LLGLSLShader* mShaderp;
  3393. };
  3394. // Helper function to setup the vertex buffer used by Nicky Dasmijn's modified
  3395. // (non-fixed GL functions) GLOD library. Returns true when successful, false
  3396. // otherwise. HB
  3397. bool setup_glob_vbo(glodVBO& vbo, LLVertexBuffer* buff,
  3398. LLStrider<U16>& index_strider,
  3399. LLStrider<LLVector3>& vertex_strider,
  3400. LLStrider<LLVector3>& normal_strider,
  3401. LLStrider<LLVector2>& tc_strider)
  3402. {
  3403. if (!buff->getIndexStrider(index_strider))
  3404. {
  3405. llwarns << "Failed to get index strider. Aborted." << llendl;
  3406. return false;
  3407. }
  3408. if (buff->hasDataType(LLVertexBuffer::TYPE_VERTEX))
  3409. {
  3410. if (!buff->getVertexStrider(vertex_strider))
  3411. {
  3412. llwarns << "Failed to get vertex strider. Aborted." << llendl;
  3413. return false;
  3414. }
  3415. vbo.mV.p = vertex_strider.get();
  3416. vbo.mV.size = 3;
  3417. vbo.mV.stride = LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX];
  3418. vbo.mV.type = GL_FLOAT;
  3419. }
  3420. if (buff->hasDataType(LLVertexBuffer::TYPE_NORMAL))
  3421. {
  3422. if (!buff->getNormalStrider(normal_strider))
  3423. {
  3424. llwarns << "Failed to get normal strider. Aborted." << llendl;
  3425. return false;
  3426. }
  3427. vbo.mN.p = normal_strider.get();
  3428. vbo.mN.stride = LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_NORMAL];
  3429. vbo.mN.type = GL_FLOAT;
  3430. }
  3431. if (buff->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0))
  3432. {
  3433. if (!buff->getTexCoord0Strider(tc_strider))
  3434. {
  3435. llwarns << "Failed to get texcoord strider. Aborted." << llendl;
  3436. return false;
  3437. }
  3438. vbo.mT.p = tc_strider.get();
  3439. vbo.mT.size = 2;
  3440. vbo.mT.stride =
  3441. LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_TEXCOORD0];
  3442. vbo.mT.type = GL_FLOAT;
  3443. }
  3444. return true;
  3445. }
  3446. bool LLModelPreview::genGlodLODs(S32 which_lod, U32 decimation,
  3447. bool enforce_tri_limit)
  3448. {
  3449. if (!mFMP)
  3450. {
  3451. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  3452. return true; // Do not try the meshoptimizer method !
  3453. }
  3454. llinfos << "Generating lod " << which_lod << " using GLOD." << llendl;
  3455. // Allow LoD from -1 to LLModel::LOD_PHYSICS
  3456. if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
  3457. {
  3458. std::ostringstream out;
  3459. out << "Invalid level of detail: " << which_lod;
  3460. llwarns << out.str() << llendl;
  3461. llassert(false);
  3462. mFMP->addLineToLog(out.str());
  3463. return true; // Do not try the meshoptimizer method !
  3464. }
  3465. if (mBaseModel.empty())
  3466. {
  3467. return true; // Do not try the meshoptimizer method !
  3468. }
  3469. stop_gloderror();
  3470. HBGlodHelper helper(this);
  3471. static U32 cur_name = 1;
  3472. S32 limit = -1;
  3473. U32 triangle_count = 0;
  3474. U32 instanced_triangle_count = 0;
  3475. // Get the triangle count for the whole scene
  3476. for (LLModelLoader::scene::iterator iter = mBaseScene.begin(),
  3477. endIter = mBaseScene.end();
  3478. iter != endIter; ++iter)
  3479. {
  3480. for (LLModelLoader::model_instance_list_t::iterator
  3481. instance = iter->second.begin(),
  3482. end_instance = iter->second.end();
  3483. instance != end_instance; ++instance)
  3484. {
  3485. LLModel* mdl = instance->mModel;
  3486. if (mdl)
  3487. {
  3488. instanced_triangle_count += mdl->getNumTriangles();
  3489. }
  3490. }
  3491. }
  3492. // Get the triangle count for the non-instanced set of models
  3493. for (U32 i = 0; i < mBaseModel.size(); ++i)
  3494. {
  3495. triangle_count += mBaseModel[i]->getNumTriangles();
  3496. }
  3497. // Get ratio of uninstanced triangles to instanced triangles
  3498. F32 triangle_ratio = (F32)triangle_count / (F32)instanced_triangle_count;
  3499. U32 base_triangle_count = triangle_count;
  3500. U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL |
  3501. LLVertexBuffer::MAP_TEXCOORD0;
  3502. U32 lod_mode = LIMIT_TRIANGLES;
  3503. F32 lod_err_thres = 0.f;
  3504. // The LoD should be in range from Lowest to High
  3505. if (which_lod > -1 && which_lod < NUM_LOD)
  3506. {
  3507. std::string cname = "lod_mode_" + lod_name[which_lod];
  3508. lod_mode =
  3509. mFMP->getChild<LLComboBox>(cname.c_str())->getCurrentIndex();
  3510. cname = "lod_error_threshold_" + lod_name[which_lod];
  3511. lod_err_thres = mFMP->childGetValue(cname.c_str()).asReal();
  3512. }
  3513. if (which_lod != -1)
  3514. {
  3515. mRequestedLoDMode[which_lod] = lod_mode;
  3516. }
  3517. if (lod_mode == LIMIT_TRIANGLES)
  3518. {
  3519. lod_mode = GLOD_TRIANGLE_BUDGET;
  3520. // The LoD should be in range from Lowest to High
  3521. if (which_lod > -1 && which_lod < NUM_LOD)
  3522. {
  3523. std::string wname = "lod_triangle_limit_" + lod_name[which_lod];
  3524. limit = mFMP->childGetValue(wname.c_str()).asInteger();
  3525. // Convert from "scene wide" to "non-instanced" triangle limit
  3526. limit = (S32)((F32)limit * triangle_ratio);
  3527. }
  3528. }
  3529. else
  3530. {
  3531. lod_mode = GLOD_ERROR_THRESHOLD;
  3532. }
  3533. bool object_dirty = false;
  3534. if (mGroup == 0)
  3535. {
  3536. object_dirty = true;
  3537. mGroup = cur_name++;
  3538. glodNewGroup(mGroup);
  3539. }
  3540. if (object_dirty)
  3541. {
  3542. for (LLModelLoader::model_list::iterator iter = mBaseModel.begin();
  3543. iter != mBaseModel.end(); ++iter)
  3544. {
  3545. // Build GLOD objects for each model in base model list
  3546. LLModel* mdl = *iter;
  3547. if (mObject[mdl] != 0)
  3548. {
  3549. glodDeleteObject(mObject[mdl]);
  3550. }
  3551. mObject[mdl] = cur_name++;
  3552. glodNewObject(mObject[mdl], mGroup, GLOD_DISCRETE);
  3553. if (stop_gloderror("glodNewObject"))
  3554. {
  3555. return false;
  3556. }
  3557. if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty())
  3558. {
  3559. // Regenerate vertex buffer for skinned models to prevent
  3560. // animation feedback during LOD generation
  3561. mVertexBuffer[5].clear();
  3562. }
  3563. if (mVertexBuffer[5].empty())
  3564. {
  3565. genBuffers(5, false);
  3566. }
  3567. for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)
  3568. {
  3569. LLVertexBuffer* buff = mVertexBuffer[5][mdl][i];
  3570. buff->setBufferNoShader(type_mask & buff->getTypeMask());
  3571. U32 num_indices = buff->getNumIndices();
  3572. if (num_indices < 2)
  3573. {
  3574. continue;
  3575. }
  3576. // Vertex buffer based code for Nicky Dasmijn's modified
  3577. // GLOD library.
  3578. glodVBO vbo = {};
  3579. LLStrider<LLVector3> vertex_strider, normal_strider;
  3580. LLStrider<LLVector2> tc_strider;
  3581. LLStrider<U16> index_strider;
  3582. if (!setup_glob_vbo(vbo, buff, index_strider, vertex_strider,
  3583. normal_strider, tc_strider))
  3584. {
  3585. return false;
  3586. }
  3587. glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices,
  3588. GL_UNSIGNED_SHORT,
  3589. (U8*)index_strider.get(), 0, 0.f, &vbo);
  3590. if (stop_gloderror("glodInsertElements"))
  3591. {
  3592. return false;
  3593. }
  3594. }
  3595. glodBuildObject(mObject[mdl]);
  3596. if (stop_gloderror("glodBuildObject"))
  3597. {
  3598. return false;
  3599. }
  3600. }
  3601. }
  3602. mMaxTriangleLimit = base_triangle_count;
  3603. S32 start = LLModel::LOD_HIGH;
  3604. S32 end = 0;
  3605. if (which_lod != -1)
  3606. {
  3607. start = end = which_lod;
  3608. }
  3609. for (S32 lod = start; lod >= end; --lod)
  3610. {
  3611. if (which_lod == -1)
  3612. {
  3613. if (lod < start)
  3614. {
  3615. triangle_count /= decimation;
  3616. }
  3617. }
  3618. else
  3619. {
  3620. if (enforce_tri_limit)
  3621. {
  3622. triangle_count = limit;
  3623. }
  3624. else
  3625. {
  3626. for (S32 j = LLModel::LOD_HIGH; j > which_lod; --j)
  3627. {
  3628. triangle_count /= decimation;
  3629. }
  3630. }
  3631. }
  3632. mModel[lod].clear();
  3633. mModel[lod].resize(mBaseModel.size());
  3634. mVertexBuffer[lod].clear();
  3635. mRequestedTriangleCount[lod] = F32(triangle_count) / triangle_ratio;
  3636. mRequestedErrorThreshold[lod] = lod_err_thres;
  3637. glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
  3638. if (stop_gloderror("glodGroupParameteri - ADAPT_MODE"))
  3639. {
  3640. return false;
  3641. }
  3642. glodGroupParameteri(mGroup, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR);
  3643. if (stop_gloderror("glodGroupParameteri - ERROR_MODE"))
  3644. {
  3645. return false;
  3646. }
  3647. glodGroupParameterf(mGroup, GLOD_OBJECT_SPACE_ERROR_THRESHOLD,
  3648. lod_err_thres);
  3649. if (stop_gloderror("glodGroupParameterf - SPACE_ERROR_THRESHOLD"))
  3650. {
  3651. return false;
  3652. }
  3653. if (lod_mode != GLOD_TRIANGLE_BUDGET)
  3654. {
  3655. glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, 0);
  3656. }
  3657. else
  3658. {
  3659. // SH-632: always add 1 to desired amount to avoid decimating below
  3660. // desired amount
  3661. glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES,
  3662. triangle_count + 1);
  3663. }
  3664. if (stop_gloderror("glodGroupParameterf - MAX_TRIANGLES"))
  3665. {
  3666. return false;
  3667. }
  3668. glodAdaptGroup(mGroup);
  3669. if (stop_gloderror("glodAdaptGroup"))
  3670. {
  3671. return false;
  3672. }
  3673. for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
  3674. {
  3675. LLModel* base = mBaseModel[mdl_idx];
  3676. GLint patch_count = 0;
  3677. glodGetObjectParameteriv(mObject[base], GLOD_NUM_PATCHES,
  3678. &patch_count);
  3679. if (stop_gloderror("glodGetObjectParameteriv - NUM_PATCHES"))
  3680. {
  3681. return false;
  3682. }
  3683. LLVolumeParams volume_params;
  3684. volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
  3685. mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
  3686. std::string name = base->mLabel + get_lod_suffix(lod);
  3687. mModel[lod][mdl_idx]->mLabel = name;
  3688. mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
  3689. GLint* sizes = new GLint[patch_count * 2];
  3690. glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
  3691. if (stop_gloderror("glodGetObjectParameteriv - PATCH_SIZES"))
  3692. {
  3693. delete[] sizes;
  3694. return false;
  3695. }
  3696. GLint* names = new GLint[patch_count];
  3697. glodGetObjectParameteriv(mObject[base], GLOD_PATCH_NAMES, names);
  3698. if (stop_gloderror("glodGetObjectParameteriv - PATCH_NAMES"))
  3699. {
  3700. delete[] sizes;
  3701. delete[] names;
  3702. return false;
  3703. }
  3704. mModel[lod][mdl_idx]->setNumVolumeFaces(patch_count);
  3705. LLModel* target_model = mModel[lod][mdl_idx];
  3706. for (GLint i = 0; i < patch_count; ++i)
  3707. {
  3708. type_mask = mVertexBuffer[5][base][i]->getTypeMask();
  3709. LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask);
  3710. if (buff.isNull())
  3711. {
  3712. llwarns << "Failure to allocate a new vertex buffer !"
  3713. << llendl;
  3714. delete[] sizes;
  3715. delete[] names;
  3716. return false;
  3717. }
  3718. if (sizes[i * 2 + 1] > 0 && sizes[i * 2] > 0)
  3719. {
  3720. if (!buff->allocateBuffer(sizes[i * 2 + 1], sizes[i * 2]))
  3721. {
  3722. llwarns << "Failed buffer allocation during preview "
  3723. << " LOD generation for " << sizes[i * 2 + 1]
  3724. << " vertices and " << sizes[i * 2]
  3725. << " indices" << llendl;
  3726. delete[] sizes;
  3727. delete[] names;
  3728. mFMP->close();
  3729. return true; // Do not try the meshoptimizer method !
  3730. }
  3731. buff->setBufferNoShader(type_mask);
  3732. // Vertex buffer based code for Nicky Dasmijn's modified
  3733. // GLOD library.
  3734. glodVBO vbo = {};
  3735. LLStrider<LLVector3> vertex_strider, normal_strider;
  3736. LLStrider<LLVector2> tc_strider;
  3737. LLStrider<U16> index_strider;
  3738. if (!setup_glob_vbo(vbo, buff, index_strider, vertex_strider,
  3739. normal_strider, tc_strider))
  3740. {
  3741. return true; // Do not try the meshoptimizer method !
  3742. }
  3743. glodFillElements(mObject[base], names[i],
  3744. GL_UNSIGNED_SHORT,
  3745. (U8*)index_strider.get(), &vbo);
  3746. if (stop_gloderror("glodFillElements"))
  3747. {
  3748. delete[] names;
  3749. delete[] sizes;
  3750. return false;
  3751. }
  3752. }
  3753. else
  3754. {
  3755. // This face was eliminated, create a dummy triangle (one
  3756. // vertex, 3 indices, all 0)
  3757. buff->allocateBuffer(1, 3);
  3758. buff->resetVertexData();
  3759. buff->resetIndexData();
  3760. LLStrider<U16> index_strider;
  3761. if (!buff->getIndexStrider(index_strider))
  3762. {
  3763. llwarns << "Failed to get index strider range, aborted !"
  3764. << llendl;
  3765. delete[] names;
  3766. delete[] sizes;
  3767. return false;
  3768. }
  3769. }
  3770. if (!buff->validateRange(0, buff->getNumVerts() - 1,
  3771. buff->getNumIndices(), 0))
  3772. {
  3773. llwarns << "Invalid range, aborted !" << llendl;
  3774. delete[] sizes;
  3775. delete[] names;
  3776. mFMP->close();
  3777. return true; // Do not try the meshoptimizer method !
  3778. }
  3779. LLStrider<LLVector3> pos, norm;
  3780. LLStrider<LLVector2> tc;
  3781. LLStrider<U16> index;
  3782. if (!buff->getVertexStrider(pos))
  3783. {
  3784. llwarns << "Could not allocate vertex strider, aborting !"
  3785. << llendl;
  3786. delete[] sizes;
  3787. delete[] names;
  3788. mFMP->close();
  3789. return true; // Do not try the meshoptimizer method !
  3790. }
  3791. if (type_mask & LLVertexBuffer::MAP_NORMAL)
  3792. {
  3793. if (!buff->getNormalStrider(norm))
  3794. {
  3795. llwarns << "Could not allocate normal strider, aborting !"
  3796. << llendl;
  3797. delete[] sizes;
  3798. delete[] names;
  3799. mFMP->close();
  3800. return true; // Do not try the meshoptimizer method !
  3801. }
  3802. }
  3803. if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
  3804. {
  3805. if (!buff->getTexCoord0Strider(tc))
  3806. {
  3807. llwarns << "Could not allocate coord strider, aborting !"
  3808. << llendl;
  3809. delete[] sizes;
  3810. delete[] names;
  3811. mFMP->close();
  3812. return true; // Do not try the meshoptimizer method !
  3813. }
  3814. }
  3815. if (!buff->getIndexStrider(index))
  3816. {
  3817. llwarns << "Could not allocate index strider, aborting !"
  3818. << llendl;
  3819. delete[] sizes;
  3820. delete[] names;
  3821. mFMP->close();
  3822. return true; // Do not try the meshoptimizer method !
  3823. }
  3824. if (type_mask & LLVertexBuffer::MAP_NORMAL)
  3825. target_model->setVolumeFaceData(names[i], pos, norm, tc, index,
  3826. buff->getNumVerts(),
  3827. buff->getNumIndices());
  3828. if (!target_model->getVolumeFace(names[i]).validate(true))
  3829. {
  3830. model_error("Invalid face generated during LOD generation.");
  3831. delete[] sizes;
  3832. delete[] names;
  3833. return false;
  3834. }
  3835. }
  3836. // Blind copy skin weights and just take closest skin weight to
  3837. // point on decimated mesh for now (auto-generating LODs with skin
  3838. // weights is still a bit of an open problem).
  3839. target_model->mPosition = base->mPosition;
  3840. target_model->mSkinWeights = base->mSkinWeights;
  3841. target_model->mSkinInfo.clone(base->mSkinInfo);
  3842. // Copy material list
  3843. target_model->mMaterialList = base->mMaterialList;
  3844. delete[] sizes;
  3845. delete[] names;
  3846. if (!target_model->validate())
  3847. {
  3848. model_error("Invalid GLOD model generated when creating LODs.");
  3849. return false;
  3850. }
  3851. }
  3852. // Rebuild scene based on mBaseScene
  3853. mScene[lod].clear();
  3854. mScene[lod] = mBaseScene;
  3855. for (U32 i = 0; i < mBaseModel.size(); ++i)
  3856. {
  3857. LLModel* mdl = mBaseModel[i];
  3858. LLModel* target = mModel[lod][i];
  3859. if (!target) continue;
  3860. for (LLModelLoader::scene::iterator iter = mScene[lod].begin(),
  3861. end = mScene[lod].end();
  3862. iter != end; ++iter)
  3863. {
  3864. for (U32 j = 0, count = iter->second.size(); j < count; ++j)
  3865. {
  3866. if (iter->second[j].mModel == mdl)
  3867. {
  3868. iter->second[j].mModel = target;
  3869. }
  3870. }
  3871. }
  3872. }
  3873. }
  3874. updateDimentionsAndOffsets();
  3875. return true;
  3876. }
  3877. F32 LLModelPreview::genMeshOptimizerPerModel(LLModel* base_model,
  3878. LLModel* target_model,
  3879. F32 indices_decim,
  3880. F32 error_threshold,
  3881. S32 simplification_mode)
  3882. {
  3883. U32 num_vol_faces = base_model->getNumVolumeFaces();
  3884. // Figure out buffer size
  3885. S32 size_indices = 0;
  3886. S32 size_vertices = 0;
  3887. for (U32 i = 0; i < num_vol_faces; ++i)
  3888. {
  3889. const LLVolumeFace& face = base_model->getVolumeFace(i);
  3890. size_indices += face.mNumIndices;
  3891. size_vertices += face.mNumVertices;
  3892. }
  3893. if (size_indices < 3)
  3894. {
  3895. return -1.f;
  3896. }
  3897. // Allocate buffers; note that we are using U32 buffer instead of U16.
  3898. size_t indices_bytes = size_indices * sizeof(U32);
  3899. U32* output_indices = (U32*)allocate_volume_mem(indices_bytes);
  3900. U32* combined_indices = (U32*)allocate_volume_mem(indices_bytes);
  3901. // Extra space for normals and text coords
  3902. S32 tc_bytes_size = (size_vertices * sizeof(LLVector2) + 0xF) & ~0xF;
  3903. LLVector4a* combined_positions =
  3904. (LLVector4a*)allocate_volume_mem_64(sizeof(LLVector4a) * 3 *
  3905. size_vertices + tc_bytes_size);
  3906. LLVector4a* combined_normals = combined_positions + size_vertices;
  3907. LLVector2* combined_tex_coords = (LLVector2*)(combined_normals +
  3908. size_vertices);
  3909. // Copy indices and vertices into new buffers
  3910. S32 combined_positions_shift = 0;
  3911. S32 indices_idx_shift = 0;
  3912. S32 combined_indices_shift = 0;
  3913. for (U32 i = 0; i < num_vol_faces; ++i)
  3914. {
  3915. const LLVolumeFace& face = base_model->getVolumeFace(i);
  3916. // Vertices
  3917. S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a);
  3918. LLVector4a::memcpyNonAliased16((F32*)(combined_positions +
  3919. combined_positions_shift),
  3920. (F32*)face.mPositions, copy_bytes);
  3921. // Normals
  3922. LLVector4a::memcpyNonAliased16((F32*)(combined_normals +
  3923. combined_positions_shift),
  3924. (F32*)face.mNormals, copy_bytes);
  3925. // Texture coords
  3926. copy_bytes = face.mNumVertices * sizeof(LLVector2);
  3927. memcpy((void*)(combined_tex_coords + combined_positions_shift),
  3928. (void*)face.mTexCoords, copy_bytes);
  3929. combined_positions_shift += face.mNumVertices;
  3930. // Sadly, indices cannot use a simple memcpy; we need to adjust each
  3931. // value...
  3932. for (U32 j = 0, count = face.mNumIndices; j < count; ++j)
  3933. {
  3934. combined_indices[combined_indices_shift++] = face.mIndices[j] +
  3935. indices_idx_shift;
  3936. }
  3937. indices_idx_shift += face.mNumVertices;
  3938. }
  3939. // Generate a shadow buffer if necessary. Welds vertices together if
  3940. // possible.
  3941. U32* shadow_indices = NULL;
  3942. // If MESH_OPTIMIZER_FULL, just leave as is, since model was remaped on a
  3943. // per face basis. Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it is pointless
  3944. // since sloppy simplification ignores all topology, including normals and
  3945. // UVs (which can be significantly affected).
  3946. if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS)
  3947. {
  3948. // Strip normals, reflections should restore relatively correctly.
  3949. shadow_indices = (U32*)allocate_volume_mem(indices_bytes);
  3950. LLMeshOptimizer::generateShadowIndexBuffer32(shadow_indices,
  3951. combined_indices,
  3952. size_indices,
  3953. combined_positions, NULL,
  3954. combined_tex_coords,
  3955. size_vertices);
  3956. }
  3957. else if (simplification_mode == MESH_OPTIMIZER_NO_UVS)
  3958. {
  3959. // Strip UVs, which can heavily affect textures
  3960. shadow_indices = (U32*)allocate_volume_mem(indices_bytes);
  3961. LLMeshOptimizer::generateShadowIndexBuffer32(shadow_indices,
  3962. combined_indices,
  3963. size_indices,
  3964. combined_positions,
  3965. NULL, NULL,
  3966. size_vertices);
  3967. }
  3968. U32* source_indices = shadow_indices ? shadow_indices : combined_indices;
  3969. // Now that we have buffers, optimize
  3970. // How far from original the model is, 1.f == 100%
  3971. F32 result_code = 0.f;
  3972. S32 target_indices;
  3973. if (indices_decim > 0.f)
  3974. {
  3975. // Leave at least one triangle
  3976. target_indices = llmax(3, llfloor(size_indices / indices_decim));
  3977. }
  3978. else
  3979. {
  3980. // Indices_decimator can be zero for error_threshold based calculations
  3981. target_indices = 3;
  3982. }
  3983. S32 type_size = LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX];
  3984. bool sloppy = simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY;
  3985. S32 new_indices = LLMeshOptimizer::simplify32(output_indices,
  3986. source_indices,
  3987. size_indices,
  3988. combined_positions,
  3989. size_vertices, type_size,
  3990. target_indices,
  3991. error_threshold, sloppy,
  3992. &result_code);
  3993. if (result_code < 0)
  3994. {
  3995. llwarns << "Negative result code from meshoptimizer for model: "
  3996. << target_model->mLabel << " - Target indices: "
  3997. << target_indices << " - New indices: " << new_indices
  3998. << " - Original count: " << size_indices << llendl;
  3999. }
  4000. // Free unused buffers
  4001. free_volume_mem(combined_indices);
  4002. free_volume_mem(shadow_indices);
  4003. combined_indices = shadow_indices = NULL;
  4004. if (new_indices < 3)
  4005. {
  4006. // Model should have at least one visible triangle
  4007. free_volume_mem(output_indices);
  4008. free_volume_mem_64(combined_positions);
  4009. return -1.f;
  4010. }
  4011. // Repack back into individual faces
  4012. LLVector4a* buffer_positions =
  4013. (LLVector4a*)allocate_volume_mem_64(sizeof(LLVector4a) * 3 *
  4014. size_vertices + tc_bytes_size);
  4015. LLVector4a* buffer_normals = buffer_positions + size_vertices;
  4016. LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals +
  4017. size_vertices);
  4018. size_t buffer_idx_size = (size_indices * sizeof(U16) + 0xF) & ~0xF;
  4019. U16* buffer_indices = (U16*)allocate_volume_mem(buffer_idx_size);
  4020. S32* old_to_new_positions_map = new S32[size_vertices];
  4021. indices_idx_shift = 0;
  4022. U32 valid_faces = 0;
  4023. // Crude method to copy indices back into face
  4024. for (U32 i = 0; i < num_vol_faces; ++i)
  4025. {
  4026. const LLVolumeFace& face = base_model->getVolumeFace(i);
  4027. S32 range = indices_idx_shift + face.mNumVertices;
  4028. S32 buf_positions_copied = 0;
  4029. S32 buf_indices_copied = 0;
  4030. bool copy_triangle = false;
  4031. for (S32 j = 0; j < size_vertices; ++j)
  4032. {
  4033. old_to_new_positions_map[j] = -1;
  4034. }
  4035. // Copy relevant indices and vertices
  4036. for (S32 j = 0; j < new_indices; ++j)
  4037. {
  4038. U32 idx = output_indices[j];
  4039. if (j % 3 == 0)
  4040. {
  4041. copy_triangle = idx >= (U32)indices_idx_shift &&
  4042. idx < (U32)range;
  4043. }
  4044. if (!copy_triangle)
  4045. {
  4046. continue;
  4047. }
  4048. // If it is a new position, we need to copy it
  4049. if (old_to_new_positions_map[idx] == -1)
  4050. {
  4051. // Validate size
  4052. if (buf_positions_copied >= (S32)U16_MAX)
  4053. {
  4054. llwarns << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for model: "
  4055. << target_model->mLabel << " - Target indices: "
  4056. << target_indices << " - New indices: "
  4057. << new_indices << " - Original count: "
  4058. << size_indices << " - Error threshold: "
  4059. << error_threshold << llendl;
  4060. // Abort as cleanly as possible (i.e. properly release
  4061. // temp buffers, unlike what happens in LL's code). HB
  4062. new_indices = -1; // Forces a 'return -1;' at the end.
  4063. // This will force a clean exit from the outer loop. HB
  4064. buf_positions_copied = U16_MAX;
  4065. break;
  4066. }
  4067. // Copy everything
  4068. buffer_positions[buf_positions_copied] =
  4069. combined_positions[idx];
  4070. buffer_normals[buf_positions_copied] = combined_normals[idx];
  4071. buffer_tex_coords[buf_positions_copied] =
  4072. combined_tex_coords[idx];
  4073. old_to_new_positions_map[idx] = buf_positions_copied;
  4074. buffer_indices[buf_indices_copied++] = buf_positions_copied++;
  4075. }
  4076. else // Existing position
  4077. {
  4078. buffer_indices[buf_indices_copied++] =
  4079. old_to_new_positions_map[idx];
  4080. }
  4081. }
  4082. if (buf_positions_copied >= U16_MAX)
  4083. {
  4084. break;
  4085. }
  4086. LLVolumeFace& new_face = target_model->getVolumeFace(i);
  4087. if (buf_indices_copied < 3)
  4088. {
  4089. // Face was optimized away
  4090. new_face.resizeIndices(3);
  4091. new_face.resizeVertices(1);
  4092. memset((void*)new_face.mIndices, 0, sizeof(U16) * 3);
  4093. new_face.mPositions[0].clear(); // Set first vertice to 0
  4094. new_face.mNormals[0].clear();
  4095. new_face.mTexCoords[0].clear();
  4096. }
  4097. else
  4098. {
  4099. new_face.resizeIndices(buf_indices_copied);
  4100. new_face.resizeVertices(buf_positions_copied);
  4101. new_face.allocateTangents(buf_positions_copied);
  4102. S32 idx_size = (buf_indices_copied * sizeof(U16) + 0xF) & ~0xF;
  4103. LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices,
  4104. (F32*)buffer_indices, idx_size);
  4105. S32 vert_size = buf_positions_copied * sizeof(LLVector4a);
  4106. LLVector4a::memcpyNonAliased16((F32*)new_face.mPositions,
  4107. (F32*)buffer_positions, vert_size);
  4108. LLVector4a::memcpyNonAliased16((F32*)new_face.mNormals,
  4109. (F32*)buffer_normals, vert_size);
  4110. U32 tex_size = (buf_positions_copied * sizeof(LLVector2) +
  4111. 0xF) & ~0xF;
  4112. LLVector4a::memcpyNonAliased16((F32*)new_face.mTexCoords,
  4113. (F32*)buffer_tex_coords, tex_size);
  4114. ++valid_faces;
  4115. }
  4116. indices_idx_shift += face.mNumVertices;
  4117. }
  4118. delete[] old_to_new_positions_map;
  4119. free_volume_mem(output_indices);
  4120. free_volume_mem_64(combined_positions);
  4121. free_volume_mem_64(buffer_positions);
  4122. free_volume_mem(buffer_indices);
  4123. if (new_indices < 3 || !valid_faces)
  4124. {
  4125. // Model should have at least one visible triangle
  4126. if (!sloppy)
  4127. {
  4128. // Should only happen with sloppy; non sloppy should not be capable
  4129. // of optimizing mesh away.
  4130. llwarns << "Failed to generate triangles for model: "
  4131. << target_model->mLabel << " - Target Indices: "
  4132. << target_indices << " - Original count: " << size_indices
  4133. << " - Error treshold: " << error_threshold << llendl;
  4134. }
  4135. return -1.f;
  4136. }
  4137. return (F32)size_indices / (F32)new_indices;
  4138. }
  4139. F32 LLModelPreview::genMeshOptimizerPerFace(LLModel* base_model,
  4140. LLModel* target_model,
  4141. U32 face_idx, F32 indices_ratio,
  4142. F32 err_threshold,
  4143. S32 simplification_mode)
  4144. {
  4145. const LLVolumeFace& face = base_model->getVolumeFace(face_idx);
  4146. S32 size_indices = face.mNumIndices;
  4147. if (size_indices < 3)
  4148. {
  4149. return -1.f;
  4150. }
  4151. size_t size = (size_indices * sizeof(U16) + 0xF) & ~0xF;
  4152. U16* output = (U16*)allocate_volume_mem(size);
  4153. // Generate a shadow buffer if necessary. Welds vertices together if
  4154. // possible.
  4155. U16* shadow_indices = NULL;
  4156. // If MESH_OPTIMIZER_FULL, just leave as is, since model was remaped on a
  4157. // per face basis. Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it is pointless
  4158. // since sloppy simplification ignores all topology, including normals and
  4159. // UVs (which can be significantly affected).
  4160. if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS)
  4161. {
  4162. // Strip normals, reflections should restore relatively correctly.
  4163. shadow_indices = (U16*)allocate_volume_mem(size);
  4164. LLMeshOptimizer::generateShadowIndexBuffer16(shadow_indices,
  4165. face.mIndices,
  4166. size_indices,
  4167. face.mPositions, NULL,
  4168. face.mTexCoords,
  4169. face.mNumVertices);
  4170. }
  4171. else if (simplification_mode == MESH_OPTIMIZER_NO_UVS)
  4172. {
  4173. // Strip UVs, which can heavily affect textures
  4174. shadow_indices = (U16*)allocate_volume_mem(size);
  4175. LLMeshOptimizer::generateShadowIndexBuffer16(shadow_indices,
  4176. face.mIndices,
  4177. size_indices,
  4178. face.mPositions, NULL,
  4179. NULL, face.mNumVertices);
  4180. }
  4181. U16* source_indices = shadow_indices ? shadow_indices : face.mIndices;
  4182. // How far from original the model is, with 1.f == 100%.
  4183. F32 result_code = 0.f;
  4184. S32 target_indices;
  4185. if (indices_ratio > 0.f)
  4186. {
  4187. // Leave at least one triangle
  4188. target_indices = llmax(3, llfloor(size_indices / indices_ratio));
  4189. }
  4190. else
  4191. {
  4192. target_indices = 3;
  4193. }
  4194. S32 type_size = LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX];
  4195. bool sloppy = simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY;
  4196. S32 new_indices = LLMeshOptimizer::simplify16(output, source_indices,
  4197. size_indices,
  4198. face.mPositions,
  4199. face.mNumVertices, type_size,
  4200. target_indices,
  4201. err_threshold, sloppy,
  4202. &result_code);
  4203. if (result_code < 0)
  4204. {
  4205. llwarns << "Negative result code from meshoptimizer for face "
  4206. << face_idx << " of model: " << target_model->mLabel
  4207. << " - Target indices: " << target_indices
  4208. << " - New indices: " << new_indices << " - Original count: "
  4209. << size_indices << " - Error treshold: " << err_threshold
  4210. << llendl;
  4211. }
  4212. LLVolumeFace& new_face = target_model->getVolumeFace(face_idx);
  4213. new_face = face; // Copy old values
  4214. if (new_indices < 3)
  4215. {
  4216. if (!sloppy)
  4217. {
  4218. // meshopt_optimizeSloppy() can optimize triangles away even if
  4219. // target_indices is > 2, but optimize() is not supposed to...
  4220. std::ostringstream out;
  4221. out << "No indices generated by meshoptimizer for face "
  4222. << face_idx << " of model: " << target_model->mLabel
  4223. << " - Target indices: " << target_indices
  4224. << " - Original count: " << size_indices
  4225. << " - Error treshold: " << err_threshold;
  4226. llinfos << out.str() << llendl;
  4227. mFMP->addLineToLog(out.str());
  4228. // Face got optimized away; generate an empty triangle.
  4229. new_face.resizeIndices(3);
  4230. new_face.resizeVertices(1);
  4231. memset((void*)new_face.mIndices, 0, sizeof(U16) * 3);
  4232. new_face.mPositions[0].clear();
  4233. new_face.mNormals[0].clear();
  4234. new_face.mTexCoords[0].clear();
  4235. }
  4236. }
  4237. else // Assign new values
  4238. {
  4239. // Wipes out mIndices, so new_face cannot substitute output
  4240. new_face.resizeIndices(new_indices);
  4241. S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF;
  4242. LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output,
  4243. idx_size);
  4244. // Clear unused values
  4245. new_face.optimize();
  4246. }
  4247. free_volume_mem(output);
  4248. free_volume_mem(shadow_indices);
  4249. return new_indices < 3 ? -1.f : (F32)size_indices / (F32)new_indices;
  4250. }
  4251. void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode,
  4252. U32 decimation, bool with_tri_limit)
  4253. {
  4254. if (!mFMP)
  4255. {
  4256. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  4257. return;
  4258. }
  4259. llinfos << "Generating lod " << which_lod << " using meshoptimizer."
  4260. << llendl;
  4261. // Allow LoD from -1 to LLModel::LOD_PHYSICS
  4262. if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
  4263. {
  4264. std::ostringstream out;
  4265. out << "Invalid level of detail: " << which_lod;
  4266. llwarns << out.str() << llendl;
  4267. llassert(false);
  4268. mFMP->addLineToLog(out.str());
  4269. return;
  4270. }
  4271. if (mBaseModel.empty())
  4272. {
  4273. return;
  4274. }
  4275. // Get the triangle count for all base models
  4276. S32 base_triangle_count = 0;
  4277. for (U32 i = 0, count = mBaseModel.size(); i < count; ++i)
  4278. {
  4279. base_triangle_count += mBaseModel[i]->getNumTriangles();
  4280. }
  4281. U32 lod_mode = LIMIT_TRIANGLES;
  4282. F32 indices_decim = 0.f;
  4283. F32 tri_limit = 0.f;
  4284. F32 lod_err_thres = 1.f; // 100%
  4285. // If requesting a single LOD
  4286. if (which_lod > -1 && which_lod < NUM_LOD)
  4287. {
  4288. std::string cname = "lod_mode_" + lod_name[which_lod];
  4289. lod_mode =
  4290. mFMP->getChild<LLComboBox>(cname.c_str())->getCurrentIndex();
  4291. if (lod_mode == LIMIT_TRIANGLES)
  4292. {
  4293. if (with_tri_limit)
  4294. {
  4295. std::string wname = "lod_triangle_limit_" +
  4296. lod_name[which_lod];
  4297. tri_limit = mFMP->childGetValue(wname.c_str()).asInteger();
  4298. }
  4299. else
  4300. {
  4301. tri_limit = base_triangle_count /
  4302. powf((F32)decimation,
  4303. (F32)(LLModel::LOD_HIGH - which_lod));
  4304. }
  4305. if (tri_limit <= 0.f)
  4306. {
  4307. tri_limit = 1.f;
  4308. }
  4309. // meshoptimizer does not use triangle limit but indices limit, so
  4310. // convert it to an aproximate ratio. Also, tri_limit can be 0.
  4311. indices_decim = (F32)base_triangle_count / llmax(tri_limit, 1.f);
  4312. }
  4313. else
  4314. {
  4315. cname = "lod_error_threshold_" + lod_name[which_lod];
  4316. lod_err_thres =
  4317. // UI shows 0 to 100%, but meshoptimizer works with 0.f to 1.f
  4318. mFMP->childGetValue(cname.c_str()).asReal() * 0.01f;
  4319. }
  4320. }
  4321. else
  4322. {
  4323. // We are generating all LODs and each LOD will get its own
  4324. // indices_decim
  4325. indices_decim = 1.f;
  4326. tri_limit = base_triangle_count;
  4327. }
  4328. mMaxTriangleLimit = base_triangle_count;
  4329. LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
  4330. if (shader)
  4331. {
  4332. shader->unbind();
  4333. }
  4334. // Build models
  4335. S32 start = LLModel::LOD_HIGH;
  4336. S32 end = 0;
  4337. if (which_lod != -1)
  4338. {
  4339. start = end = which_lod;
  4340. }
  4341. for (S32 lod = start; lod >= end; --lod)
  4342. {
  4343. if (which_lod == -1)
  4344. {
  4345. // We are generating all LODs, each with its own indices_ratio
  4346. indices_decim *= decimation;
  4347. tri_limit /= decimation;
  4348. }
  4349. mRequestedTriangleCount[lod] = tri_limit;
  4350. mRequestedErrorThreshold[lod] = lod_err_thres * 100.f;
  4351. mRequestedLoDMode[lod] = lod_mode;
  4352. mModel[lod].clear();
  4353. mModel[lod].resize(mBaseModel.size());
  4354. mVertexBuffer[lod].clear();
  4355. constexpr F32 allowed_ratio_drift = 1.8f;
  4356. for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
  4357. {
  4358. LLModel* base = mBaseModel[mdl_idx];
  4359. LLVolumeParams volume_params;
  4360. volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
  4361. mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
  4362. std::string name = base->mLabel + get_lod_suffix(lod);
  4363. mModel[lod][mdl_idx]->mLabel = name;
  4364. mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
  4365. mModel[lod][mdl_idx]->setNumVolumeFaces(base->getNumVolumeFaces());
  4366. LLModel* target_model = mModel[lod][mdl_idx];
  4367. // Carry over normalized transform into simplified model
  4368. for (U32 i = 0, count = base->getNumVolumeFaces(); i < count; ++i)
  4369. {
  4370. LLVolumeFace& src = base->getVolumeFace(i);
  4371. LLVolumeFace& dst = target_model->getVolumeFace(i);
  4372. dst.mNormalizedScale = src.mNormalizedScale;
  4373. }
  4374. S32 model_meshopt_mode = meshopt_mode;
  4375. std::ostringstream out;
  4376. out << "Model " << target_model->mLabel << " - LOD" << lod;
  4377. F32 ratio = 0.f;
  4378. // Ideally this should run not per model, but combine all sub-
  4379. // models with origin model as well.
  4380. if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE)
  4381. {
  4382. // Run meshoptimizer for each face
  4383. for (U32 face_idx = 0, count = base->getNumVolumeFaces();
  4384. face_idx < count; ++face_idx)
  4385. {
  4386. ratio = genMeshOptimizerPerFace(base, target_model,
  4387. face_idx, indices_decim,
  4388. lod_err_thres,
  4389. MESH_OPTIMIZER_FULL);
  4390. if (ratio < 0.f)
  4391. {
  4392. break;
  4393. }
  4394. }
  4395. if (ratio < 0.f)
  4396. {
  4397. model_meshopt_mode = MESH_OPTIMIZER_AUTO;
  4398. }
  4399. else
  4400. {
  4401. out << " simplified using per face method.";
  4402. }
  4403. }
  4404. if (model_meshopt_mode == MESH_OPTIMIZER_AUTO)
  4405. {
  4406. // Remove progressively more data if we cannot reach the target
  4407. // Run meshoptimizer for each model/object, up to 8 faces in
  4408. // one model.
  4409. ratio = genMeshOptimizerPerModel(base, target_model,
  4410. indices_decim, lod_err_thres,
  4411. MESH_OPTIMIZER_FULL);
  4412. bool done = ratio * allowed_ratio_drift >= indices_decim;
  4413. if (done)
  4414. {
  4415. out << " simplified using per model method.";
  4416. }
  4417. else
  4418. {
  4419. ratio =
  4420. genMeshOptimizerPerModel(base, target_model,
  4421. indices_decim, lod_err_thres,
  4422. MESH_OPTIMIZER_NO_NORMALS);
  4423. done = ratio * allowed_ratio_drift >= indices_decim;
  4424. if (done)
  4425. {
  4426. out << " simplified using per model method without normals.";
  4427. }
  4428. }
  4429. if (!done)
  4430. {
  4431. ratio =
  4432. genMeshOptimizerPerModel(base, target_model,
  4433. indices_decim, lod_err_thres,
  4434. MESH_OPTIMIZER_NO_UVS);
  4435. done = ratio * allowed_ratio_drift >= indices_decim;
  4436. if (done)
  4437. {
  4438. out << " simplified using per model method without UVs.";
  4439. }
  4440. }
  4441. if (!done)
  4442. {
  4443. // Try sloppy variant if normal one failed to simplify
  4444. // model enough. Use per-model, sloppy optimization
  4445. ratio = genMeshOptimizerPerModel(base, target_model,
  4446. indices_decim,
  4447. lod_err_thres,
  4448. MESH_OPTIMIZER_NO_TOPOLOGY);
  4449. // Sloppy has a tendency to error into lower side, so a
  4450. // request for 100 triangles turns into ~70; check for
  4451. // significant difference from target decimation.
  4452. constexpr F32 sloppy_ratio_drift = 1.4f;
  4453. if (lod_mode == LIMIT_TRIANGLES &&
  4454. (ratio < 0.f ||
  4455. ratio > indices_decim * sloppy_ratio_drift))
  4456. {
  4457. // Apply a correction to compensate.
  4458. // (indices_decim / res_ratio) by itself is likely
  4459. // to overshoot to a different side due to overal lack
  4460. // of precision, and we do not need an ideal result,
  4461. // which likely does not exist, just a better one, so a
  4462. // partial correction is enough.
  4463. F32 sloppy_decimator = indices_decim * 0.5f *
  4464. (indices_decim / ratio + 1.f);
  4465. ratio = genMeshOptimizerPerModel(base, target_model,
  4466. sloppy_decimator,
  4467. lod_err_thres,
  4468. MESH_OPTIMIZER_NO_TOPOLOGY);
  4469. }
  4470. if (ratio < 0.f)
  4471. {
  4472. // Sloppy variant failed to generate triangles. Can
  4473. // happen with models that are too simple as is.
  4474. // Fallback to normal method.
  4475. if (genMeshOptimizerPerModel(base, target_model,
  4476. indices_decim,
  4477. lod_err_thres,
  4478. MESH_OPTIMIZER_FULL) < 0.f)
  4479. {
  4480. // Failed again ! Fall back to sloppy per face
  4481. // method
  4482. model_meshopt_mode = MESH_OPTIMIZER_SLOPPY;
  4483. }
  4484. else
  4485. {
  4486. out << " simplified using per model sloppy method.";
  4487. }
  4488. }
  4489. }
  4490. }
  4491. if (model_meshopt_mode == MESH_OPTIMIZER_SLOPPY)
  4492. {
  4493. for (U32 face_idx = 0, count = base->getNumVolumeFaces();
  4494. face_idx < count; ++face_idx)
  4495. {
  4496. if (genMeshOptimizerPerFace(base, target_model, face_idx,
  4497. indices_decim, lod_err_thres,
  4498. MESH_OPTIMIZER_NO_TOPOLOGY) < 0)
  4499. {
  4500. genMeshOptimizerPerFace(base, target_model, face_idx,
  4501. indices_decim, lod_err_thres,
  4502. MESH_OPTIMIZER_FULL);
  4503. }
  4504. }
  4505. out << " simplified using per face sloppy method.";
  4506. }
  4507. llinfos << out.str() << llendl;
  4508. mFMP->addLineToLog(out.str());
  4509. // Blind-copy skin weights and just take closest skin weight to
  4510. // point on decimated mesh for now (auto-generating LODs with skin
  4511. // weights is still a bit of an open problem).
  4512. target_model->mPosition = base->mPosition;
  4513. target_model->mSkinWeights = base->mSkinWeights;
  4514. target_model->mSkinInfo.clone(base->mSkinInfo);
  4515. // Copy materials list
  4516. target_model->mMaterialList = base->mMaterialList;
  4517. if (!target_model->validate())
  4518. {
  4519. model_error("Invalid meshoptimizer model generated when creating LODs.");
  4520. mFMP->close();
  4521. return;
  4522. }
  4523. }
  4524. // Rebuild scene based on mBaseScene
  4525. mScene[lod].clear();
  4526. mScene[lod] = mBaseScene;
  4527. for (U32 i = 0; i < mBaseModel.size(); ++i)
  4528. {
  4529. LLModel* mdl = mBaseModel[i];
  4530. LLModel* target = mModel[lod][i];
  4531. if (!target) continue;
  4532. for (LLModelLoader::scene::iterator iter = mScene[lod].begin(),
  4533. end = mScene[lod].end();
  4534. iter != end; ++iter)
  4535. {
  4536. for (U32 j = 0, count = iter->second.size(); j < count; ++j)
  4537. {
  4538. if (iter->second[j].mModel == mdl)
  4539. {
  4540. iter->second[j].mModel = target;
  4541. }
  4542. }
  4543. }
  4544. }
  4545. }
  4546. updateDimentionsAndOffsets();
  4547. LLVertexBuffer::unbind();
  4548. if (shader)
  4549. {
  4550. shader->bind();
  4551. }
  4552. }
  4553. void LLModelPreview::updateStatusMessages()
  4554. {
  4555. assert_main_thread();
  4556. if (!mFMP)
  4557. {
  4558. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  4559. return;
  4560. }
  4561. // Triangle/vertex/submesh count for each mesh asset for each lod
  4562. std::vector<S32> tris[LLModel::NUM_LODS];
  4563. std::vector<S32> verts[LLModel::NUM_LODS];
  4564. std::vector<S32> submeshes[LLModel::NUM_LODS];
  4565. // Total triangle/vertex/submesh count for each lod
  4566. S32 total_tris[LLModel::NUM_LODS];
  4567. S32 total_verts[LLModel::NUM_LODS];
  4568. S32 total_submeshes[LLModel::NUM_LODS];
  4569. for (U32 i = 0; i < LLModel::NUM_LODS - 1; ++i)
  4570. {
  4571. total_tris[i] = 0;
  4572. total_verts[i] = 0;
  4573. total_submeshes[i] = 0;
  4574. }
  4575. mFMP->mCalculateBtn->setEnabled(true);
  4576. for (LLMeshUploadThread::instance_list_t::iterator
  4577. iter = mUploadData.begin(), end = mUploadData.end();
  4578. iter != end; ++iter)
  4579. {
  4580. LLModelInstance& instance = *iter;
  4581. LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH];
  4582. if (!model_high_lod)
  4583. {
  4584. setLoadState(LLModelLoader::ERROR_HIGH_LOD_MODEL_MISSING);
  4585. mFMP->mCalculateBtn->setEnabled(false);
  4586. continue;
  4587. }
  4588. for (S32 i = 0; i < LLModel::NUM_LODS - 1; ++i)
  4589. {
  4590. LLModel* lod_model = instance.mLOD[i];
  4591. if (!lod_model)
  4592. {
  4593. setLoadState(LLModelLoader::ERROR_LOD_MODEL_MISMATCH);
  4594. mFMP->mCalculateBtn->setEnabled(false);
  4595. continue;
  4596. }
  4597. // For each model in the lod
  4598. S32 cur_tris = 0;
  4599. S32 cur_verts = 0;
  4600. S32 cur_submeshes = lod_model->getNumVolumeFaces();
  4601. for (S32 j = 0; j < cur_submeshes; ++j)
  4602. {
  4603. // For each submesh (face), add triangles and vertices to
  4604. // current total
  4605. const LLVolumeFace& face = lod_model->getVolumeFace(j);
  4606. cur_tris += face.mNumIndices / 3;
  4607. cur_verts += face.mNumVertices;
  4608. }
  4609. // Useful for debugging generalized complaints below about total
  4610. // sub-meshes which do not have enough context to address exactly
  4611. // what needs to be fixed to move towards compliance with the rules
  4612. if (mImporterDebug)
  4613. {
  4614. std::ostringstream out;
  4615. out << "Instance: " << lod_model->mLabel << " - LOD" << i
  4616. << " - Verts: " << cur_verts << " - Tris: " << cur_tris
  4617. << " - Faces: " << cur_submeshes;
  4618. for (LLModel::material_list::iterator
  4619. it = lod_model->mMaterialList.begin(),
  4620. end = lod_model->mMaterialList.end();
  4621. it != end; ++it)
  4622. {
  4623. out << " - Material: " << *it;
  4624. }
  4625. llinfos << out.str() << llendl;
  4626. mFMP->addLineToLog(out.str());
  4627. }
  4628. // Add this model to the lod total
  4629. total_tris[i] += cur_tris;
  4630. total_verts[i] += cur_verts;
  4631. total_submeshes[i] += cur_submeshes;
  4632. // Store this model's counts to asset data
  4633. tris[i].push_back(cur_tris);
  4634. verts[i].push_back(cur_verts);
  4635. submeshes[i].push_back(cur_submeshes);
  4636. }
  4637. }
  4638. if (mMaxTriangleLimit == 0)
  4639. {
  4640. mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
  4641. }
  4642. mHasDegenerate = false;
  4643. // Check for degenerate triangles in physics mesh
  4644. U32 lod = LLModel::LOD_PHYSICS;
  4645. const LLVector4a scale(0.5f);
  4646. LLVector4a v1, v2, v3;
  4647. for (U32 i = 0; i < mModel[lod].size() && !mHasDegenerate; ++i)
  4648. {
  4649. // For each model in the lod
  4650. if (!mModel[lod][i] || !mModel[lod][i]->mPhysics.mHull.empty())
  4651. {
  4652. continue;
  4653. }
  4654. // No decomp exists
  4655. S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
  4656. for (S32 j = 0; j < cur_submeshes && !mHasDegenerate; ++j)
  4657. {
  4658. // For each submesh (face), add triangles and vertices to current
  4659. // total
  4660. LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
  4661. for (S32 k = 0; k < face.mNumIndices; k += 3)
  4662. {
  4663. U16 index_a = face.mIndices[k];
  4664. v1.setMul(face.mPositions[index_a], scale);
  4665. U16 index_b = face.mIndices[k + 1];
  4666. v2.setMul(face.mPositions[index_b], scale);
  4667. U16 index_c = face.mIndices[k + 2];
  4668. v3.setMul(face.mPositions[index_c], scale);
  4669. if (LLVolumeFace::isDegenerate(v1, v2, v3))
  4670. {
  4671. mHasDegenerate = true;
  4672. break;
  4673. }
  4674. }
  4675. }
  4676. }
  4677. std::string mesh_status_na = mFMP->getString("mesh_status_na");
  4678. S32 upload_status[LLModel::LOD_HIGH + 1];
  4679. mModelNoErrors = true;
  4680. constexpr S32 lod_high = LLModel::LOD_HIGH;
  4681. U32 high_submodel_count = mModel[lod_high].size() -
  4682. countRootModels(mModel[lod_high]);
  4683. for (S32 lod = 0; lod <= lod_high; ++lod)
  4684. {
  4685. upload_status[lod] = 0;
  4686. std::string message = "mesh_status_good";
  4687. if (total_tris[lod] > 0)
  4688. {
  4689. mFMP->childSetText(lod_triangles_name[lod],
  4690. llformat("%d", total_tris[lod]));
  4691. mFMP->childSetText(lod_vertices_name[lod],
  4692. llformat("%d", total_verts[lod]));
  4693. }
  4694. else
  4695. {
  4696. if (lod == lod_high)
  4697. {
  4698. upload_status[lod] = 2;
  4699. message = "mesh_status_missing_lod";
  4700. }
  4701. else
  4702. {
  4703. for (S32 i = lod - 1; i >= 0; --i)
  4704. {
  4705. if (total_tris[i] > 0)
  4706. {
  4707. upload_status[lod] = 2;
  4708. message = "mesh_status_missing_lod";
  4709. }
  4710. }
  4711. }
  4712. mFMP->childSetText(lod_triangles_name[lod], mesh_status_na);
  4713. mFMP->childSetText(lod_vertices_name[lod], mesh_status_na);
  4714. }
  4715. if (lod != lod_high)
  4716. {
  4717. if (total_submeshes[lod] &&
  4718. total_submeshes[lod] > total_submeshes[lod_high])
  4719. {
  4720. // Number of submeshes is different
  4721. message = "mesh_status_submesh_mismatch";
  4722. upload_status[lod] = 2;
  4723. }
  4724. else if (mModel[lod].size() -
  4725. countRootModels(mModel[lod]) != high_submodel_count)
  4726. {
  4727. // Number of submodels is different, not all faces are matched
  4728. // correctly.
  4729. message = "mesh_status_submesh_mismatch";
  4730. upload_status[lod] = 2;
  4731. // Note: Submodels in instance were loaded from higher LOD and
  4732. // as result face count returns same value and
  4733. // total_submeshes[lod] is identical to high_lod one.
  4734. }
  4735. else if (!tris[lod].empty() &&
  4736. tris[lod].size() != tris[lod_high].size())
  4737. {
  4738. // Number of meshes is different
  4739. message = "mesh_status_mesh_mismatch";
  4740. upload_status[lod] = 2;
  4741. }
  4742. else if (!verts[lod].empty())
  4743. {
  4744. S32 sum_verts_higher_lod = 0;
  4745. S32 sum_verts_this_lod = 0;
  4746. S32 max = verts[lod + 1].size();
  4747. for (S32 i = 0, count = verts[lod].size(); i < count; ++i)
  4748. {
  4749. if (i < max)
  4750. {
  4751. sum_verts_higher_lod += verts[lod + 1][i];
  4752. }
  4753. sum_verts_this_lod += verts[lod][i];
  4754. }
  4755. if (sum_verts_higher_lod > 0 &&
  4756. sum_verts_this_lod > sum_verts_higher_lod)
  4757. {
  4758. // Too many vertices in this lod
  4759. message = "mesh_status_too_many_vertices";
  4760. upload_status[lod] = 1;
  4761. }
  4762. }
  4763. }
  4764. std::string img = lod_status_image[upload_status[lod]];
  4765. LLIconCtrl* icon = mFMP->getChild<LLIconCtrl>(lod_icon_name[lod]);
  4766. icon->setVisible(true);
  4767. icon->setImage(img);
  4768. if (upload_status[lod] >= 2)
  4769. {
  4770. mModelNoErrors = false;
  4771. }
  4772. if (lod == mPreviewLOD)
  4773. {
  4774. mFMP->childSetText("lod_status_message_text",
  4775. mFMP->getString(message));
  4776. icon = mFMP->getChild<LLIconCtrl>("lod_status_message_icon");
  4777. icon->setImage(img);
  4778. }
  4779. updateLodControls(lod);
  4780. }
  4781. // Warn if hulls have more than 256 points in them
  4782. bool physics_off_limit = false;
  4783. for (U32 i = 0, count1 = mModel[LLModel::LOD_PHYSICS].size();
  4784. mModelNoErrors && i < count1; ++i)
  4785. {
  4786. LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
  4787. if (mdl)
  4788. {
  4789. for (U32 j = 0, count2 = mdl->mPhysics.mHull.size(); j < count2;
  4790. ++j)
  4791. {
  4792. if (mdl->mPhysics.mHull[j].size() > 256)
  4793. {
  4794. physics_off_limit = true;
  4795. llwarns << "Physical model " << mdl->mLabel
  4796. << " exceeds vertex per hull limitations."
  4797. << llendl;
  4798. break;
  4799. }
  4800. }
  4801. }
  4802. }
  4803. std::string phys_status;
  4804. if (mHasDegenerate)
  4805. {
  4806. phys_status = mFMP->getString("phys_status_degenerate_triangles");
  4807. }
  4808. else if (physics_off_limit)
  4809. {
  4810. phys_status = mFMP->getString("phys_status_vertex_limit_exceeded");
  4811. }
  4812. mFMP->childSetValue("physics_status_message_text", phys_status);
  4813. if (mLoadState >= LLModelLoader::ERROR_PARSING)
  4814. {
  4815. mModelNoErrors = false;
  4816. llinfos << "Loader returned errors, model cannot be uploaded"
  4817. << llendl;
  4818. }
  4819. if (mFMP->childGetValue("upload_skin").asBoolean() &&
  4820. mFMP->childGetValue("upload_joints").asBoolean() &&
  4821. !mRigValidJointUpload)
  4822. {
  4823. mModelNoErrors = false;
  4824. llinfos << "Invalid rig; there might be issues with uploading joint positions"
  4825. << llendl;
  4826. }
  4827. if (mModelNoErrors && mModelLoader && !mModelLoader->areTexturesReady() &&
  4828. mFMP->childGetValue("upload_textures").asBoolean())
  4829. {
  4830. mModelNoErrors = false;
  4831. }
  4832. // *TODO: investigate use of mHasDegenerate and include into mModelNoErrors
  4833. // upload blocking mechanics; current use of mHasDegenerate would not block
  4834. // upload permanently: later checks will restore the button.
  4835. if (!mModelNoErrors || mHasDegenerate)
  4836. {
  4837. mFMP->mUploadBtn->setEnabled(false);
  4838. }
  4839. mFMP->mCalculateBtn->setEnabled(mModelNoErrors && !mHasDegenerate &&
  4840. mLodsWithParsingError.empty());
  4841. // Add up physics triangles etc
  4842. S32 phys_tris = 0;
  4843. S32 phys_hulls = 0;
  4844. S32 phys_points = 0;
  4845. // Get the triangle count for the whole scene
  4846. for (LLModelLoader::scene::iterator
  4847. iter = mScene[LLModel::LOD_PHYSICS].begin(),
  4848. end = mScene[LLModel::LOD_PHYSICS].end();
  4849. iter != end; ++iter)
  4850. {
  4851. for (LLModelLoader::model_instance_list_t::iterator
  4852. instance = iter->second.begin(),
  4853. end_instance = iter->second.end();
  4854. instance != end_instance; ++instance)
  4855. {
  4856. LLModel* model = instance->mModel;
  4857. if (!model)
  4858. {
  4859. continue;
  4860. }
  4861. S32 cur_submeshes = model->getNumVolumeFaces();
  4862. LLModel::hull_decomp& decomp = model->mPhysics.mHull;
  4863. if (decomp.empty())
  4864. {
  4865. // Choose physics shape OR decomposition, cannot use both
  4866. for (S32 j = 0; j < cur_submeshes; ++j)
  4867. {
  4868. // For each submesh (face), add triangles and vertices to
  4869. // current total
  4870. const LLVolumeFace& face = model->getVolumeFace(j);
  4871. phys_tris += face.mNumIndices / 3;
  4872. }
  4873. }
  4874. else
  4875. {
  4876. phys_hulls += decomp.size();
  4877. for (U32 i = 0, count = decomp.size(); i < count; ++i)
  4878. {
  4879. phys_points += decomp[i].size();
  4880. }
  4881. }
  4882. }
  4883. }
  4884. if (phys_tris > 0)
  4885. {
  4886. mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]",
  4887. llformat("%d", phys_tris));
  4888. }
  4889. else
  4890. {
  4891. mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]",
  4892. mesh_status_na);
  4893. }
  4894. if (phys_hulls > 0)
  4895. {
  4896. mFMP->childSetTextArg("physics_hulls", "[HULLS]",
  4897. llformat("%d", phys_hulls));
  4898. mFMP->childSetTextArg("physics_points", "[POINTS]",
  4899. llformat("%d", phys_points));
  4900. }
  4901. else
  4902. {
  4903. mFMP->childSetTextArg("physics_hulls", "[HULLS]", mesh_status_na);
  4904. mFMP->childSetTextArg("physics_points", "[POINTS]", mesh_status_na);
  4905. }
  4906. if (phys_tris > 0 || phys_hulls > 0)
  4907. {
  4908. if (!mFMP->isViewOptionEnabled("show_physics"))
  4909. {
  4910. mFMP->enableViewOption("show_physics");
  4911. // Cannot display both physics and skin weights... HB
  4912. if (!mFMP->childGetValue("show_skin_weight"))
  4913. {
  4914. mViewOption["show_physics"] = true;
  4915. mFMP->childSetValue("show_physics", true);
  4916. }
  4917. }
  4918. }
  4919. else
  4920. {
  4921. mFMP->disableViewOption("show_physics");
  4922. mViewOption["show_physics"] = false;
  4923. mFMP->childSetValue("show_physics", false);
  4924. }
  4925. // See *TODO in setPhysicsFromLOD(). Since we cannot remove any loaded
  4926. // physics hull mode, we must disable the default phys hull item in the
  4927. // combo if one got loaded at any point...
  4928. LLScrollListItem* itemp =
  4929. mFMP->getChild<LLComboBox>("physics_lod_combo")->getItemByIndex(0);
  4930. if (itemp && (phys_tris || phys_hulls))
  4931. {
  4932. itemp->setEnabled(false);
  4933. }
  4934. // Enable/disable "analysis" UI
  4935. bool enable = phys_tris > 0 || phys_hulls > 0;
  4936. bool enable_full = enable && !mFMP->mLibIsHACD;
  4937. LLPanel* panel = mFMP->getChild<LLPanel>("physics analysis");
  4938. LLView* child = panel->getFirstChild();
  4939. while (child)
  4940. {
  4941. child->setEnabled(enable_full);
  4942. child = panel->findNextSibling(child);
  4943. }
  4944. mFMP->childSetEnabled("physics_explode_label", enable);
  4945. mFMP->childSetEnabled("physics_explode", enable);
  4946. if (enable_full != enable)
  4947. {
  4948. mFMP->childSetEnabled("second_step_label", enable);
  4949. mFMP->childSetEnabled("Decompose", enable);
  4950. }
  4951. // Enable/disable "simplification" UI
  4952. enable = phys_hulls > 0 && mFMP->mCurRequest.empty() && !mFMP->mLibIsHACD;
  4953. panel = mFMP->getChild<LLPanel>("physics simplification");
  4954. child = panel->getFirstChild();
  4955. while (child)
  4956. {
  4957. child->setEnabled(enable);
  4958. child = panel->findNextSibling(child);
  4959. }
  4960. mFMP->childSetVisible("hacd_limits", mFMP->mLibIsHACD);
  4961. if (mFMP->mCurRequest.empty())
  4962. {
  4963. mFMP->childSetVisible("Simplify", true);
  4964. mFMP->childSetVisible("Decompose", true);
  4965. if (!mFMP->mLibIsHACD && phys_hulls > 0)
  4966. {
  4967. mFMP->childEnable("Simplify");
  4968. }
  4969. if (phys_tris || phys_hulls > 0)
  4970. {
  4971. mFMP->childEnable("Decompose");
  4972. }
  4973. mFMP->childSetVisible("simplify_cancel", false);
  4974. mFMP->childSetVisible("decompose_cancel", false);
  4975. }
  4976. else
  4977. {
  4978. if (!mFMP->mLibIsHACD)
  4979. {
  4980. mFMP->childEnable("simplify_cancel");
  4981. }
  4982. mFMP->childEnable("decompose_cancel");
  4983. }
  4984. S32 which_mode =
  4985. mFMP->getChild<LLComboBox>("physics_lod_combo")->getCurrentIndex();
  4986. if (which_mode == 6)
  4987. {
  4988. mFMP->childEnable("physics_file");
  4989. mFMP->childEnable("physics_browse");
  4990. }
  4991. else
  4992. {
  4993. mFMP->childDisable("physics_file");
  4994. mFMP->childDisable("physics_browse");
  4995. }
  4996. LLSpinCtrl* crease = mFMP->getChild<LLSpinCtrl>("crease_angle");
  4997. if (mRequestedCreaseAngle[mPreviewLOD] == -1.f)
  4998. {
  4999. mFMP->childSetColor("crease_label", LLColor4::grey);
  5000. crease->forceSetValue(75.f);
  5001. }
  5002. else
  5003. {
  5004. mFMP->childSetColor("crease_label", LLColor4::white);
  5005. crease->forceSetValue(mRequestedCreaseAngle[mPreviewLOD]);
  5006. }
  5007. mModelUpdatedSignal(true);
  5008. }
  5009. void LLModelPreview::updateLodControls(S32 lod)
  5010. {
  5011. if (!mFMP)
  5012. {
  5013. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  5014. return;
  5015. }
  5016. if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::LOD_HIGH)
  5017. {
  5018. llwarns << "Invalid level of detail: " << lod << llendl;
  5019. llassert(false);
  5020. return;
  5021. }
  5022. static const char* lod_controls[] =
  5023. {
  5024. "lod_mode_",
  5025. "lod_triangle_limit_",
  5026. "lod_error_threshold_"
  5027. };
  5028. constexpr U32 num_lod_controls = LL_ARRAY_SIZE(lod_controls);
  5029. static const char* file_controls[] =
  5030. {
  5031. "lod_browse_",
  5032. "lod_file_",
  5033. };
  5034. constexpr U32 num_file_controls = LL_ARRAY_SIZE(file_controls);
  5035. if (!mFMP) return;
  5036. std::string lodstr = lod_name[lod];
  5037. std::string wname = "lod_source_" + lodstr;
  5038. LLComboBox* lod_combo = mFMP->getChild<LLComboBox>(wname.c_str(),
  5039. true, false);
  5040. if (!lod_combo) return;
  5041. S32 lod_mode = lod_combo->getCurrentIndex();
  5042. if (lod_mode == LOD_FROM_FILE) // LoD from file
  5043. {
  5044. mFMP->mLODMode[lod] = lod_mode;
  5045. for (U32 i = 0; i < num_file_controls; ++i)
  5046. {
  5047. wname = file_controls[i] + lodstr;
  5048. mFMP->childShow(wname.c_str());
  5049. }
  5050. for (U32 i = 0; i < num_lod_controls; ++i)
  5051. {
  5052. wname = lod_controls[i] + lodstr;
  5053. mFMP->childHide(wname.c_str());
  5054. }
  5055. }
  5056. else if (lod_mode == USE_LOD_ABOVE) // use LoD above
  5057. {
  5058. mFMP->mLODMode[lod] = lod_mode;
  5059. for (U32 i = 0; i < num_file_controls; ++i)
  5060. {
  5061. wname = file_controls[i] + lodstr;
  5062. mFMP->childHide(wname.c_str());
  5063. }
  5064. for (U32 i = 0; i < num_lod_controls; ++i)
  5065. {
  5066. wname = lod_controls[i] + lodstr;
  5067. mFMP->childHide(wname.c_str());
  5068. }
  5069. if (lod < LLModel::LOD_HIGH)
  5070. {
  5071. mModel[lod] = mModel[lod + 1];
  5072. mScene[lod] = mScene[lod + 1];
  5073. mVertexBuffer[lod].clear();
  5074. // Also update lower LoD
  5075. if (lod > LLModel::LOD_IMPOSTOR)
  5076. {
  5077. updateLodControls(lod - 1);
  5078. }
  5079. }
  5080. }
  5081. else // Auto generate, the default case for all LoDs except High
  5082. {
  5083. mFMP->mLODMode[lod] = 1;
  5084. // Do not actually regenerate lod when refreshing UI
  5085. mLODFrozen = true;
  5086. for (U32 i = 0; i < num_file_controls; ++i)
  5087. {
  5088. wname = file_controls[i] + lodstr;
  5089. mFMP->childHide(wname.c_str());
  5090. }
  5091. for (U32 i = 0; i < num_lod_controls; ++i)
  5092. {
  5093. wname = lod_controls[i] + lodstr;
  5094. mFMP->childShow(wname.c_str());
  5095. }
  5096. std::string wname = "lod_error_threshold_" + lodstr;
  5097. LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>(wname.c_str());
  5098. wname = "lod_triangle_limit_" + lodstr;
  5099. LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>(wname.c_str());
  5100. limit->setMaxValue(mMaxTriangleLimit);
  5101. limit->forceSetValue(mRequestedTriangleCount[lod]);
  5102. threshold->forceSetValue(mRequestedErrorThreshold[lod]);
  5103. wname = "lod_mode_" + lodstr;
  5104. LLComboBox* combo = mFMP->getChild<LLComboBox>(wname.c_str());
  5105. combo->selectNthItem(mRequestedLoDMode[lod]);
  5106. if (mRequestedLoDMode[lod] == 0)
  5107. {
  5108. limit->setVisible(true);
  5109. threshold->setVisible(false);
  5110. limit->setMaxValue(mMaxTriangleLimit);
  5111. limit->setIncrement(llmax(1U, mMaxTriangleLimit / 32U));
  5112. }
  5113. else
  5114. {
  5115. limit->setVisible(false);
  5116. threshold->setVisible(true);
  5117. }
  5118. mLODFrozen = false;
  5119. }
  5120. }
  5121. void LLModelPreview::setPreviewTarget(F32 distance)
  5122. {
  5123. mCameraDistance = distance;
  5124. mCameraZoom = 1.f;
  5125. mCameraPitch = 0.f;
  5126. mCameraYaw = 0.f;
  5127. mCameraOffset.clear();
  5128. }
  5129. void LLModelPreview::clearBuffers()
  5130. {
  5131. for (U32 i = 0; i < 6; ++i)
  5132. {
  5133. mVertexBuffer[i].clear();
  5134. }
  5135. }
  5136. #if defined(GCC_VERSION)
  5137. // Work-around for a spurious "mat_normal maybe uninitialized", with warning,
  5138. // even though mat_normal is never used when not actually initialized (see
  5139. // the 'skinned' boolean test. HB
  5140. # pragma GCC diagnostic ignored "-Wuninitialized"
  5141. # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  5142. #endif
  5143. void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
  5144. {
  5145. LLModelLoader::model_list* model = NULL;
  5146. if (lod < 0 || lod > 4)
  5147. {
  5148. model = &mBaseModel;
  5149. lod = 5;
  5150. }
  5151. else
  5152. {
  5153. model = &(mModel[lod]);
  5154. }
  5155. mVertexBuffer[lod].clear();
  5156. LLModelLoader::model_list::iterator base_iter = mBaseModel.begin();
  5157. for (LLModelLoader::model_list::iterator iter = model->begin();
  5158. iter != model->end(); ++iter)
  5159. {
  5160. LLModel* mdl = *iter;
  5161. if (!mdl) continue;
  5162. ++base_iter;
  5163. bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
  5164. LLMatrix4a mat_normal;
  5165. if (skinned)
  5166. {
  5167. mat_normal.loadu(mdl->mSkinInfo.mBindShapeMatrix);
  5168. mat_normal.invert();
  5169. mat_normal.transpose();
  5170. }
  5171. for (S32 i = 0, count = mdl->getNumVolumeFaces(); i < count; ++i)
  5172. {
  5173. const LLVolumeFace& vf = mdl->getVolumeFace(i);
  5174. U32 num_vertices = vf.mNumVertices;
  5175. U32 num_indices = vf.mNumIndices;
  5176. if (!num_vertices || !num_indices)
  5177. {
  5178. continue;
  5179. }
  5180. U32 mask = LLVertexBuffer::MAP_VERTEX |
  5181. LLVertexBuffer::MAP_NORMAL |
  5182. LLVertexBuffer::MAP_TEXCOORD0;
  5183. if (skinned)
  5184. {
  5185. mask |= LLVertexBuffer::MAP_WEIGHT4;
  5186. }
  5187. LLPointer<LLVertexBuffer> vb = new LLVertexBuffer(mask);
  5188. if (!vb->allocateBuffer(num_vertices, num_indices))
  5189. {
  5190. llwarns << "Failed to allocate vertex buffer with "
  5191. << num_vertices << " vertices and " << num_indices
  5192. << " indices" << llendl;
  5193. return;
  5194. }
  5195. LLStrider<LLVector4a> vertex_strider, normal_strider,
  5196. weights_strider;
  5197. LLStrider<LLVector2> tc_strider;
  5198. LLStrider<U16> index_strider;
  5199. if (!vb->getVertexStrider(vertex_strider) ||
  5200. !vb->getIndexStrider(index_strider))
  5201. {
  5202. llwarns << "Could not get vertex and index striders."
  5203. << llendl;
  5204. return;
  5205. }
  5206. if (skinned && !vb->getWeight4Strider(weights_strider))
  5207. {
  5208. llwarns << "Could not get weight strider." << llendl;
  5209. return;
  5210. }
  5211. LLVector4a::memcpyNonAliased16((F32*)vertex_strider.get(),
  5212. (F32*)vf.mPositions,
  5213. num_vertices * 4 * sizeof(F32));
  5214. if (skinned)
  5215. {
  5216. LLMatrix4a bind_shape_matrix;
  5217. bind_shape_matrix.loadu(mdl->mSkinInfo.mBindShapeMatrix);
  5218. for (U32 k = 0; k < num_vertices; ++k)
  5219. {
  5220. LLVector4a* v = vertex_strider.get();
  5221. bind_shape_matrix.affineTransform(*v, *v);
  5222. vertex_strider++;
  5223. }
  5224. }
  5225. if (vf.mTexCoords)
  5226. {
  5227. if (!vb->getTexCoord0Strider(tc_strider))
  5228. {
  5229. llwarns << "Could not get coord strider." << llendl;
  5230. return;
  5231. }
  5232. S32 tex_size = (num_vertices * 2 * sizeof(F32) + 0xF) & ~0xF;
  5233. LLVector4a::memcpyNonAliased16((F32*)tc_strider.get(),
  5234. (F32*)vf.mTexCoords, tex_size);
  5235. }
  5236. if (vf.mNormals)
  5237. {
  5238. if (!vb->getNormalStrider(normal_strider))
  5239. {
  5240. llwarns << "Could not get normal strider." << llendl;
  5241. return;
  5242. }
  5243. if (skinned)
  5244. {
  5245. LLVector4a* src = vf.mNormals;
  5246. LLVector4a* end = src + num_vertices;
  5247. while (src < end)
  5248. {
  5249. LLVector4a* n = normal_strider.get();
  5250. mat_normal.rotate(*src++, *n);
  5251. n->normalize3fast();
  5252. normal_strider++;
  5253. }
  5254. }
  5255. else
  5256. {
  5257. LLVector4a::memcpyNonAliased16((F32*)normal_strider.get(),
  5258. (F32*)vf.mNormals,
  5259. num_vertices * 4 * sizeof(F32));
  5260. }
  5261. }
  5262. if (skinned)
  5263. {
  5264. bool fp_prec_error = false;
  5265. for (U32 i = 0; i < num_vertices; ++i)
  5266. {
  5267. // Find closest weight to vf.mVertices[i].mPosition
  5268. LLVector3 pos(vf.mPositions[i].getF32ptr());
  5269. const LLModel::weight_list& weight_list =
  5270. mdl->getJointInfluences(pos);
  5271. // LLModel::loadModel() should guarantee this:
  5272. if (weight_list.size() <= 0 || weight_list.size() > 4)
  5273. {
  5274. return;
  5275. }
  5276. LLVector4 w(0.f, 0.f, 0.f, 0.f);
  5277. for (U32 i = 0, count2 = weight_list.size();
  5278. i < count2; ++i)
  5279. {
  5280. F32 wght = llclamp(weight_list[i].mWeight,
  5281. .001f, 0.999f);
  5282. F32 joint = (F32)weight_list[i].mJointIdx;
  5283. w.mV[i] = joint + wght;
  5284. if (w.mV[i] - (S32)w.mV[i] <= 0.f)
  5285. {
  5286. // Because weights are non-zero, and range of
  5287. // weight values should not cause floating point
  5288. // precision issues.
  5289. fp_prec_error = true;
  5290. }
  5291. }
  5292. (*weights_strider++).loadua(w.mV);
  5293. }
  5294. if (fp_prec_error)
  5295. {
  5296. llwarns << "Floating point precision error detected."
  5297. << llendl;
  5298. }
  5299. }
  5300. // Build indices
  5301. for (U32 i = 0; i < num_indices; ++i)
  5302. {
  5303. *index_strider++ = vf.mIndices[i];
  5304. }
  5305. mVertexBuffer[lod][mdl].emplace_back(vb);
  5306. vb->unmapBuffer(); // Requiered to get all the changes saved ! HB
  5307. }
  5308. }
  5309. // A redraw will be needed. HB
  5310. mNeedsUpdate = true;
  5311. }
  5312. void LLModelPreview::update()
  5313. {
  5314. if (mGenLOD)
  5315. {
  5316. bool subscribe_for_generation = mLodsQuery.empty();
  5317. mGenLOD = false;
  5318. mDirty = true;
  5319. mLodsQuery.clear();
  5320. for (S32 lod = LLModel::LOD_HIGH; lod >= 0; --lod)
  5321. {
  5322. // Adding all lods into query for generation
  5323. mLodsQuery.push_back(lod);
  5324. }
  5325. if (subscribe_for_generation)
  5326. {
  5327. doOnIdleRepeating(lodQueryCallback);
  5328. }
  5329. }
  5330. if (mDirty && mLodsQuery.empty())
  5331. {
  5332. mDirty = false;
  5333. updateDimentionsAndOffsets();
  5334. updateStatusMessages();
  5335. refresh();
  5336. }
  5337. }
  5338. void LLModelPreview::createPreviewAvatar()
  5339. {
  5340. mPreviewAvatar =
  5341. (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR,
  5342. gAgent.getRegion(),
  5343. LLViewerObject::CO_FLAG_UI_AVATAR);
  5344. if (mPreviewAvatar)
  5345. {
  5346. mPreviewAvatar->createDrawable();
  5347. mPreviewAvatar->mSpecialRenderMode = 1;
  5348. mPreviewAvatar->startMotion(ANIM_AGENT_STAND);
  5349. mPreviewAvatar->hideSkirt();
  5350. }
  5351. else
  5352. {
  5353. llwarns << "Failed to create preview avatar for upload model window"
  5354. << llendl;
  5355. }
  5356. }
  5357. //static
  5358. U32 LLModelPreview::countRootModels(LLModelLoader::model_list models)
  5359. {
  5360. U32 root_models = 0;
  5361. model_list::iterator model_iter = models.begin();
  5362. while (model_iter != models.end())
  5363. {
  5364. LLModel* mdl = *model_iter;
  5365. if (mdl && mdl->mSubmodelID == 0)
  5366. {
  5367. ++root_models;
  5368. }
  5369. ++model_iter;
  5370. }
  5371. return root_models;
  5372. }
  5373. //static
  5374. void LLModelPreview::loadedCallback(LLModelLoader::scene& scene,
  5375. LLModelLoader::model_list& model_list,
  5376. S32 lod, void* userdata)
  5377. {
  5378. LLModelPreview* preview = (LLModelPreview*)userdata;
  5379. if (preview && preview == LLFloaterModelPreview::getModelPreview())
  5380. {
  5381. preview->loadModelCallback(lod);
  5382. const LLVOAvatar* avatarp = preview->mPreviewAvatar;
  5383. if (avatarp && avatarp->mDrawable)
  5384. {
  5385. // Set up ground plane for possible rendering
  5386. const LLVector3 root_pos = avatarp->mRoot->getPosition();
  5387. const LLVector4a* ext = avatarp->mDrawable->getSpatialExtents();
  5388. const LLVector4a min = ext[0], max = ext[1];
  5389. const F32 center = (max[2] - min[2]) * 0.5f;
  5390. const F32 ground = root_pos[2] - center;
  5391. preview->mGroundPlane[0].set(min[0], min[1], ground);
  5392. preview->mGroundPlane[1].set(max[0], min[1], ground);
  5393. preview->mGroundPlane[2].set(max[0], max[1], ground);
  5394. preview->mGroundPlane[3].set(min[0], max[1], ground);
  5395. }
  5396. }
  5397. }
  5398. //static
  5399. void LLModelPreview::stateChangedCallback(U32 state, void* userdata)
  5400. {
  5401. LLModelPreview* preview = (LLModelPreview*)userdata;
  5402. if (preview && preview == LLFloaterModelPreview::getModelPreview())
  5403. {
  5404. preview->setLoadState(state);
  5405. }
  5406. }
  5407. //static
  5408. LLJoint* LLModelPreview::lookupJointByName(const std::string& str,
  5409. void* userdata)
  5410. {
  5411. LLModelPreview* preview = (LLModelPreview*)userdata;
  5412. if (preview && preview == LLFloaterModelPreview::getModelPreview() &&
  5413. preview->mPreviewAvatar)
  5414. {
  5415. U32 joint_key = LLJoint::getKey(str, false);
  5416. return preview->mPreviewAvatar->getJoint(joint_key);
  5417. }
  5418. return NULL;
  5419. }
  5420. //static
  5421. U32 LLModelPreview::loadTextures(LLImportMaterial& material, void* userdata)
  5422. {
  5423. LLModelPreview* preview = (LLModelPreview*)userdata;
  5424. if (preview && preview == LLFloaterModelPreview::getModelPreview() &&
  5425. !material.mDiffuseMapFilename.empty())
  5426. {
  5427. material.mUserData = new LLPointer<LLViewerFetchedTexture>;
  5428. LLPointer<LLViewerFetchedTexture>& tex =
  5429. (*reinterpret_cast<LLPointer<LLViewerFetchedTexture>*>(material.mUserData));
  5430. tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" +
  5431. material.mDiffuseMapFilename,
  5432. FTT_LOCAL_FILE,
  5433. true,
  5434. LLGLTexture::BOOST_PREVIEW);
  5435. if (tex->getDiscardLevel() < tex->getMaxDiscardLevel())
  5436. {
  5437. // File was loaded previously, reload image to get potential
  5438. // changes.
  5439. tex->clearFetchedResults();
  5440. }
  5441. tex->setLoadedCallback(LLModelPreview::textureLoadedCallback,
  5442. 0, true, false, userdata, NULL, false);
  5443. tex->forceToSaveRawImage(0, F32_MAX);
  5444. material.setDiffuseMap(tex->getID()); // Record tex ID
  5445. return 1;
  5446. }
  5447. material.mUserData = NULL;
  5448. return 0;
  5449. }
  5450. void LLModelPreview::addEmptyFace(LLModel* modelp)
  5451. {
  5452. if (!modelp)
  5453. {
  5454. llwarns << "NULL model pointer passed !" << llendl;
  5455. return;
  5456. }
  5457. U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL |
  5458. LLVertexBuffer::MAP_TEXCOORD0;
  5459. LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask);
  5460. buff->allocateBuffer(1, 3);
  5461. buff->resetVertexData();
  5462. LLStrider<U16> index_strider;
  5463. if (!buff->getIndexStrider(index_strider))
  5464. {
  5465. llwarns << "Failed to get index strider range, aborted !" << llendl;
  5466. return;
  5467. }
  5468. buff->resetIndexData();
  5469. if (!buff->validateRange(0, buff->getNumVerts() - 1,
  5470. buff->getNumIndices(), 0))
  5471. {
  5472. llwarns << "Invalid range, aborted !" << llendl;
  5473. return;
  5474. }
  5475. LLStrider<LLVector3> pos;
  5476. LLStrider<LLVector3> norm;
  5477. LLStrider<LLVector2> tc;
  5478. LLStrider<U16> index;
  5479. if (!buff->getVertexStrider(pos))
  5480. {
  5481. llwarns << "Could not allocate vertex strider, aborting !" << llendl;
  5482. return;
  5483. }
  5484. if (type_mask & LLVertexBuffer::MAP_NORMAL)
  5485. {
  5486. if (!buff->getNormalStrider(norm))
  5487. {
  5488. llwarns << "Could not allocate normal strider, aborting !"
  5489. << llendl;
  5490. return;
  5491. }
  5492. }
  5493. if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
  5494. {
  5495. if (!buff->getTexCoord0Strider(tc))
  5496. {
  5497. llwarns << "Could not allocate texcoord strider, aborting !"
  5498. << llendl;
  5499. return;
  5500. }
  5501. }
  5502. if (!buff->getIndexStrider(index))
  5503. {
  5504. llwarns << "Could not allocate index strider, aborting !" << llendl;
  5505. return;
  5506. }
  5507. // Resize face array
  5508. S32 face_cnt = modelp->getNumVolumeFaces();
  5509. modelp->setNumVolumeFaces(face_cnt + 1);
  5510. modelp->setVolumeFaceData(face_cnt + 1, pos, norm, tc, index,
  5511. buff->getNumVerts(), buff->getNumIndices());
  5512. }
  5513. // For PBR rendering only.
  5514. static void upload_matrix_palette(LLVOAvatar* avp, LLMeshSkinInfo* skinp)
  5515. {
  5516. static LLMatrix4a mat4a[LL_MAX_JOINTS_PER_MESH_OBJECT];
  5517. static F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT * 12];
  5518. skinp->updateHash(true); // true = force
  5519. // Only upload the matrix palette if not yet previously done. HB
  5520. static LLVOAvatar* last_avp = NULL;
  5521. static U64 last_hash = 0;
  5522. static LLGLSLShader* last_shaderp = NULL;
  5523. if (last_avp == avp && last_hash == skinp->mHash &&
  5524. last_shaderp == LLGLSLShader::sCurBoundShaderPtr)
  5525. {
  5526. return;
  5527. }
  5528. last_avp = avp;
  5529. last_hash = skinp->mHash;
  5530. last_shaderp = LLGLSLShader::sCurBoundShaderPtr;
  5531. U32 count = LLSkinningUtil::initSkinningMatrixPalette(mat4a, skinp, avp);
  5532. U32 idx = 0;
  5533. for (U32 i = 0; i < count; ++i)
  5534. {
  5535. const F32* m = mat4a[i].mMatrix[0].getF32ptr();
  5536. mp[idx++] = m[0];
  5537. mp[idx++] = m[1];
  5538. mp[idx++] = m[2];
  5539. mp[idx++] = m[12];
  5540. mp[idx++] = m[4];
  5541. mp[idx++] = m[5];
  5542. mp[idx++] = m[6];
  5543. mp[idx++] = m[13];
  5544. mp[idx++] = m[8];
  5545. mp[idx++] = m[9];
  5546. mp[idx++] = m[10];
  5547. mp[idx++] = m[14];
  5548. }
  5549. LLGLSLShader* shaderp = LLGLSLShader::sCurBoundShaderPtr;
  5550. shaderp->uniformMatrix3x4fv(LLShaderMgr::AVATAR_MATRIX, count, false, mp);
  5551. }
  5552. bool LLModelPreview::render()
  5553. {
  5554. assert_main_thread();
  5555. if (!mFMP)
  5556. {
  5557. llwarns << "Model Preview floater is gone ! Aborted." << llendl;
  5558. return false;
  5559. }
  5560. LLMutexLock lock(this);
  5561. mNeedsUpdate = false;
  5562. bool edges = mViewOption["show_edges"];
  5563. bool joint_overrides = mViewOption["show_joint_overrides"];
  5564. bool joint_positions = mViewOption["show_joint_positions"];
  5565. bool collision_volumes = mViewOption["show_collision_volumes"];
  5566. bool skin_weight = mViewOption["show_skin_weight"];
  5567. bool textures = mViewOption["show_textures"];
  5568. bool physics = mViewOption["show_physics"];
  5569. S32 width = getWidth();
  5570. S32 height = getHeight();
  5571. LLGLSUIDefault def;
  5572. LLGLDisable no_blend(GL_BLEND);
  5573. LLGLEnable cull(GL_CULL_FACE);
  5574. // SL-12781 disable Z-buffer to render background color
  5575. LLGLDepthTest depth(GL_FALSE);
  5576. {
  5577. gUIProgram.bind();
  5578. // Clear background to grey
  5579. gGL.matrixMode(LLRender::MM_PROJECTION);
  5580. gGL.pushMatrix();
  5581. gGL.loadIdentity();
  5582. gGL.ortho(0.f, width, 0.f, height, -1.f, 1.f);
  5583. gGL.matrixMode(LLRender::MM_MODELVIEW);
  5584. gGL.pushMatrix();
  5585. gGL.loadIdentity();
  5586. gGL.color4fv(PREVIEW_CANVAS_COL.mV);
  5587. gl_rect_2d_simple(width, height);
  5588. gGL.matrixMode(LLRender::MM_PROJECTION);
  5589. gGL.popMatrix();
  5590. gGL.matrixMode(LLRender::MM_MODELVIEW);
  5591. gGL.popMatrix();
  5592. gUIProgram.unbind();
  5593. }
  5594. stop_glerror();
  5595. bool has_skin_weights = false;
  5596. bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
  5597. bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean();
  5598. if (upload_joints != mLastJointUpdate)
  5599. {
  5600. mLastJointUpdate = upload_joints;
  5601. mFMP->clearSkinningInfo();
  5602. }
  5603. for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(),
  5604. end = mScene[mPreviewLOD].end();
  5605. iter != end; ++iter)
  5606. {
  5607. for (LLModelLoader::model_instance_list_t::iterator
  5608. model_iter = iter->second.begin(),
  5609. model_end = iter->second.end();
  5610. model_iter != model_end; ++model_iter)
  5611. {
  5612. LLModelInstance& instance = *model_iter;
  5613. LLModel* model = instance.mModel;
  5614. model->mPelvisOffset = mPelvisZOffset;
  5615. if (!model->mSkinWeights.empty())
  5616. {
  5617. has_skin_weights = true;
  5618. }
  5619. }
  5620. }
  5621. if (has_skin_weights && lodsReady())
  5622. {
  5623. // Model has skin weights: enable view options for skin weights and
  5624. // joint positions
  5625. if (!mLegacyRigFlags)
  5626. {
  5627. #if 1
  5628. if (mFirstSkinUpdate)
  5629. {
  5630. mFirstSkinUpdate = false;
  5631. // Auto-enable weight upload if weights are present
  5632. skin_weight = mViewOption["show_skin_weight"] = true;
  5633. mFMP->childSetValue("upload_skin", true);
  5634. }
  5635. #endif
  5636. mFMP->enableViewOption("show_skin_weight");
  5637. mFMP->setViewOptionEnabled("show_joint_overrides", skin_weight);
  5638. mFMP->setViewOptionEnabled("show_joint_positions", skin_weight);
  5639. mFMP->setViewOptionEnabled("show_collision_volumes", skin_weight);
  5640. mFMP->childSetValue("show_skin_weight", skin_weight);
  5641. if (skin_weight)
  5642. {
  5643. // Cannot display both physics and skin weights... HB
  5644. mFMP->childSetValue("show_physics", false);
  5645. mViewOption["show_physics"] = false;
  5646. }
  5647. mFMP->childEnable("upload_skin");
  5648. }
  5649. else if (mLegacyRigFlags & LEGACY_RIG_FLAG_NO_JOINT)
  5650. {
  5651. mFMP->childSetVisible("skin_no_joint", true);
  5652. }
  5653. else if (mLegacyRigFlags & LEGACY_RIG_FLAG_TOO_MANY_JOINTS)
  5654. {
  5655. mFMP->childSetVisible("skin_too_many_joints", true);
  5656. }
  5657. else if (mLegacyRigFlags & LEGACY_RIG_FLAG_UNKNOWN_JOINT)
  5658. {
  5659. mFMP->childSetVisible("skin_unknown_joint", true);
  5660. }
  5661. }
  5662. else
  5663. {
  5664. mFMP->childDisable("upload_skin");
  5665. mViewOption["show_skin_weight"] = false;
  5666. mFMP->setViewOptionEnabled("show_skin_weight", false);
  5667. mFMP->disableViewOption("show_skin_weight");
  5668. mFMP->childSetValue("show_skin_weight", false);
  5669. mFMP->disableViewOption("show_joint_overrides");
  5670. mFMP->disableViewOption("show_joint_positions");
  5671. mFMP->disableViewOption("show_collision_volumes");
  5672. skin_weight = false;
  5673. }
  5674. if (upload_skin && !has_skin_weights)
  5675. {
  5676. // Cannot upload skin weights if model has no skin weights
  5677. mFMP->childSetValue("upload_skin", false);
  5678. upload_skin = false;
  5679. }
  5680. if (!upload_skin && upload_joints)
  5681. {
  5682. // Cannot upload joints if not uploading skin weights
  5683. mFMP->childSetValue("upload_joints", false);
  5684. upload_joints = false;
  5685. }
  5686. if (upload_skin && upload_joints)
  5687. {
  5688. mFMP->childEnable("lock_scale_if_joint_position");
  5689. }
  5690. else
  5691. {
  5692. mFMP->childDisable("lock_scale_if_joint_position");
  5693. mFMP->childSetValue("lock_scale_if_joint_position", false);
  5694. }
  5695. // Only enable joint offsets if it passed the earlier critiquing
  5696. if (mRigValidJointUpload)
  5697. {
  5698. mFMP->childSetEnabled("upload_joints", upload_skin);
  5699. }
  5700. if (upload_skin)
  5701. {
  5702. mFMP->updateSkinningInfo(upload_joints);
  5703. }
  5704. else
  5705. {
  5706. mFMP->clearSkinningInfo();
  5707. }
  5708. F32 explode = mFMP->childGetValue("physics_explode").asReal();
  5709. // SL-12781 re-enable Z-buffer for 3D model preview
  5710. LLGLDepthTest gls_depth(GL_TRUE);
  5711. LLRect preview_rect = mFMP->getChildView("preview_panel")->getRect();
  5712. F32 aspect = (F32)preview_rect.getWidth() / preview_rect.getHeight();
  5713. gViewerCamera.setAspect(aspect);
  5714. gViewerCamera.setViewNoBroadcast(gViewerCamera.getDefaultFOV() /
  5715. mCameraZoom);
  5716. LLVector3 offset = mCameraOffset;
  5717. LLVector3 target_pos = mPreviewTarget + offset;
  5718. F32 z_near = 0.001f;
  5719. F32 z_far = mCameraDistance * 10.0f + mPreviewScale.length() +
  5720. mCameraOffset.length();
  5721. if (skin_weight && mPreviewAvatar)
  5722. {
  5723. target_pos = mPreviewAvatar->getPositionAgent();
  5724. z_near = 0.01f;
  5725. z_far = 1024.f;
  5726. // Render avatar previews every frame
  5727. mNeedsUpdate = true;
  5728. }
  5729. if (gUsePBRShaders)
  5730. {
  5731. gObjectPreviewProgram.bind(skin_weight);
  5732. }
  5733. else
  5734. {
  5735. gObjectPreviewProgram.bind();
  5736. }
  5737. // Do not let environment settings influence our scene lighting.
  5738. HBPreviewLighting preview_light;
  5739. gGL.loadIdentity();
  5740. LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
  5741. LLQuaternion(mCameraYaw, LLVector3::z_axis);
  5742. LLQuaternion av_rot = camera_rot;
  5743. F32 cam_dist = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
  5744. gViewerCamera.setOriginAndLookAt(target_pos +
  5745. // Camera position
  5746. (LLVector3(cam_dist, 0.f, 0.f) + offset) *
  5747. av_rot,
  5748. // Up axis
  5749. LLVector3::z_axis,
  5750. // Point of interest
  5751. target_pos);
  5752. z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f);
  5753. gViewerCamera.setPerspective(false, mOrigin.mX, mOrigin.mY, width, height,
  5754. false, z_near, z_far);
  5755. gGL.pushMatrix();
  5756. gGL.color4fv(PREVIEW_EDGE_COL.mV);
  5757. constexpr U32 type_mask = LLVertexBuffer::MAP_VERTEX |
  5758. LLVertexBuffer::MAP_NORMAL |
  5759. LLVertexBuffer::MAP_TEXCOORD0;
  5760. if (!mBaseModel.empty() && mVertexBuffer[5].empty())
  5761. {
  5762. genBuffers(-1, skin_weight);
  5763. }
  5764. if (!mModel[mPreviewLOD].empty())
  5765. {
  5766. LLTexUnit* unit0 = gGL.getTexUnit(0);
  5767. mFMP->childEnable("reset_btn");
  5768. bool regen = mVertexBuffer[mPreviewLOD].empty();
  5769. if (!regen)
  5770. {
  5771. const std::vector<LLPointer<LLVertexBuffer> >& vb_vec =
  5772. mVertexBuffer[mPreviewLOD].begin()->second;
  5773. if (!vb_vec.empty())
  5774. {
  5775. const LLVertexBuffer* buff = vb_vec[0];
  5776. regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) !=
  5777. skin_weight;
  5778. }
  5779. }
  5780. else
  5781. {
  5782. llinfos << "Vertex Buffer[" << mPreviewLOD << "]"
  5783. << " is empty; regenerating it..." << llendl;
  5784. regen = true;
  5785. }
  5786. if (regen)
  5787. {
  5788. genBuffers(mPreviewLOD, skin_weight);
  5789. }
  5790. if (!skin_weight)
  5791. {
  5792. for (LLMeshUploadThread::instance_list_t::iterator
  5793. iter = mUploadData.begin(), end = mUploadData.end();
  5794. iter != end; ++iter)
  5795. {
  5796. LLModelInstance& instance = *iter;
  5797. LLModel* model = instance.mLOD[mPreviewLOD];
  5798. if (!model)
  5799. {
  5800. continue;
  5801. }
  5802. gGL.pushMatrix();
  5803. LLMatrix4 mat = instance.mTransform;
  5804. gGL.multMatrix(mat.getF32ptr());
  5805. for (U32 i = 0,
  5806. count = mVertexBuffer[mPreviewLOD][model].size();
  5807. i < count; ++i)
  5808. {
  5809. LLVertexBuffer* buffer =
  5810. mVertexBuffer[mPreviewLOD][model][i];
  5811. // Note: mask ignored in PBR rendering mode
  5812. buffer->setBuffer(type_mask & buffer->getTypeMask());
  5813. if (textures)
  5814. {
  5815. U32 mat_count = instance.mModel->mMaterialList.size();
  5816. if (i < mat_count)
  5817. {
  5818. const std::string& binding =
  5819. instance.mModel->mMaterialList[i];
  5820. const LLImportMaterial& material =
  5821. instance.mMaterial[binding];
  5822. gGL.diffuseColor4fv(material.mDiffuseColor.mV);
  5823. // Find the tex for this material, bind it, and add
  5824. // it to our set
  5825. LLViewerFetchedTexture* tex =
  5826. bind_mat_diffuse_tex(material);
  5827. if (tex)
  5828. {
  5829. mTextureSet.insert(tex);
  5830. }
  5831. }
  5832. }
  5833. else
  5834. {
  5835. gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
  5836. }
  5837. buffer->drawRange(LLRender::TRIANGLES, 0,
  5838. buffer->getNumVerts() - 1,
  5839. buffer->getNumIndices(), 0);
  5840. unit0->unbind(LLTexUnit::TT_TEXTURE);
  5841. gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
  5842. if (edges)
  5843. {
  5844. gGL.lineWidth(1.f);
  5845. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  5846. buffer->drawRange(LLRender::TRIANGLES, 0,
  5847. buffer->getNumVerts() - 1,
  5848. buffer->getNumIndices(), 0);
  5849. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  5850. }
  5851. buffer->unmapBuffer();
  5852. }
  5853. gGL.popMatrix();
  5854. }
  5855. stop_glerror();
  5856. if (physics)
  5857. {
  5858. glClear(GL_DEPTH_BUFFER_BIT);
  5859. for (U32 pass = 0; pass < 2; ++pass)
  5860. {
  5861. if (pass == 0)
  5862. {
  5863. // Depth only pass
  5864. gGL.setColorMask(false, false);
  5865. }
  5866. else
  5867. {
  5868. gGL.setColorMask(true, true);
  5869. }
  5870. // Enable alpha blending on second pass but not first pass
  5871. LLGLState blend(GL_BLEND, pass);
  5872. gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
  5873. LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
  5874. for (LLMeshUploadThread::instance_list_t::iterator
  5875. iter = mUploadData.begin(),
  5876. end = mUploadData.end();
  5877. iter != end; ++iter)
  5878. {
  5879. LLModelInstance& instance = *iter;
  5880. LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
  5881. if (!model)
  5882. {
  5883. continue;
  5884. }
  5885. gGL.pushMatrix();
  5886. LLMatrix4 mat = instance.mTransform;
  5887. gGL.multMatrix(mat.getF32ptr());
  5888. bool render_mesh = true;
  5889. LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
  5890. if (decomp)
  5891. {
  5892. decomp->mMutex.lock();
  5893. LLModel::Decomposition& physics = model->mPhysics;
  5894. if (!physics.mHull.empty())
  5895. {
  5896. render_mesh = false;
  5897. if (physics.mMesh.empty())
  5898. {
  5899. // Build vertex buffer for physics mesh
  5900. gMeshRepo.buildPhysicsMesh(physics);
  5901. }
  5902. if (!physics.mMesh.empty())
  5903. {
  5904. LLGLSLShader* shaderp = NULL;
  5905. if (gUsePBRShaders)
  5906. {
  5907. // Note: this could be either of
  5908. // gObjectPreviewProgram or
  5909. // gSkinnedObjectPreviewProgram. HB
  5910. shaderp =
  5911. LLGLSLShader::sCurBoundShaderPtr;
  5912. if (shaderp) // Paranoia
  5913. {
  5914. shaderp->unbind();
  5915. }
  5916. gPhysicsPreviewProgram.bind();
  5917. }
  5918. // Render hull instead of mesh
  5919. for (U32 i = 0, count = physics.mMesh.size();
  5920. i < count; ++i)
  5921. {
  5922. if (explode > 0.f)
  5923. {
  5924. gGL.pushMatrix();
  5925. LLVector3 offset =
  5926. model->mHullCenter[i]-model->mCenterOfHullCenters;
  5927. offset *= explode;
  5928. gGL.translatef(offset.mV[0],
  5929. offset.mV[1],
  5930. offset.mV[2]);
  5931. }
  5932. static std::vector<LLColor4U> hull_colors;
  5933. if (i + 1 >= hull_colors.size())
  5934. {
  5935. hull_colors.emplace_back(rand() % 128 + 127,
  5936. rand() % 128 + 127,
  5937. rand() % 128 + 127,
  5938. 128);
  5939. }
  5940. gGL.diffuseColor4ubv(hull_colors[i].mV);
  5941. LLVertexBuffer::drawArrays(LLRender::TRIANGLES,
  5942. physics.mMesh[i].mPositions,
  5943. physics.mMesh[i].mNormals);
  5944. if (explode > 0.f)
  5945. {
  5946. gGL.popMatrix();
  5947. }
  5948. }
  5949. if (gUsePBRShaders)
  5950. {
  5951. gPhysicsPreviewProgram.unbind();
  5952. if (shaderp) // Paranoia
  5953. {
  5954. shaderp->bind();
  5955. }
  5956. }
  5957. }
  5958. }
  5959. decomp->mMutex.unlock();
  5960. }
  5961. if (render_mesh)
  5962. {
  5963. if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
  5964. {
  5965. genBuffers(LLModel::LOD_PHYSICS, false);
  5966. }
  5967. if (pass > 0)
  5968. {
  5969. for (U32 i = 0,
  5970. count = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
  5971. i < count; ++i)
  5972. {
  5973. LLVertexBuffer* buffer =
  5974. mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
  5975. unit0->unbind(LLTexUnit::TT_TEXTURE);
  5976. gGL.diffuseColor4fv(PREVIEW_PHYS_FILL_COL.mV);
  5977. // Note: mask ignored in PBR rendering mode
  5978. buffer->setBuffer(type_mask &
  5979. buffer->getTypeMask());
  5980. buffer->drawRange(LLRender::TRIANGLES, 0,
  5981. buffer->getNumVerts() - 1,
  5982. buffer->getNumIndices(), 0);
  5983. gGL.diffuseColor4fv(PREVIEW_PHYS_EDGE_COL.mV);
  5984. gGL.lineWidth(1.f);
  5985. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  5986. buffer->drawRange(LLRender::TRIANGLES, 0,
  5987. buffer->getNumVerts() - 1,
  5988. buffer->getNumIndices(), 0);
  5989. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  5990. buffer->unmapBuffer();
  5991. }
  5992. }
  5993. }
  5994. gGL.popMatrix();
  5995. }
  5996. // Show degenerate triangles, if any
  5997. if (mHasDegenerate)
  5998. {
  5999. gGL.lineWidth(PREVIEW_DEG_EDGE_WIDTH);
  6000. glPointSize(PREVIEW_DEG_POINT_SIZE);
  6001. LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
  6002. LLGLDisable cull(GL_CULL_FACE);
  6003. gGL.diffuseColor4f(1.f, 0.f, 0.f, 1.f);
  6004. const LLVector4a scale(0.5f);
  6005. for (LLMeshUploadThread::instance_list_t::iterator
  6006. iter = mUploadData.begin(),
  6007. end = mUploadData.end();
  6008. iter != end; ++iter)
  6009. {
  6010. LLModelInstance& instance = *iter;
  6011. LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
  6012. if (!model) continue;
  6013. LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
  6014. if (!decomp) continue;
  6015. gGL.pushMatrix();
  6016. LLMatrix4 mat = instance.mTransform;
  6017. gGL.multMatrix(mat.getF32ptr());
  6018. decomp->mMutex.lock();
  6019. LLModel::Decomposition& physics = model->mPhysics;
  6020. if (physics.mHull.empty())
  6021. {
  6022. if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
  6023. {
  6024. genBuffers(LLModel::LOD_PHYSICS, false);
  6025. }
  6026. for (U32 i = 0,
  6027. count = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
  6028. i < count; ++i)
  6029. {
  6030. LLVertexBuffer* buffer =
  6031. mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
  6032. // Note: mask ignored in PBR rendering mode
  6033. buffer->setBuffer(type_mask &
  6034. buffer->getTypeMask());
  6035. LLStrider<LLVector3> pos_strider;
  6036. LLStrider<U16> idx;
  6037. if (!buffer->getVertexStrider(pos_strider, 0) ||
  6038. !buffer->getIndexStrider(idx, 0))
  6039. {
  6040. decomp->mMutex.unlock();
  6041. gObjectPreviewProgram.bind();
  6042. gGL.popMatrix();
  6043. return false;
  6044. }
  6045. LLVector4a* pos = (LLVector4a*)pos_strider.get();
  6046. for (S32 i = 0, count = buffer->getNumIndices();
  6047. i < count; i += 3)
  6048. {
  6049. LLVector4a v1; v1.setMul(pos[*idx++], scale);
  6050. LLVector4a v2; v2.setMul(pos[*idx++], scale);
  6051. LLVector4a v3; v3.setMul(pos[*idx++], scale);
  6052. if (LLVolumeFace::isDegenerate(v1, v2, v3))
  6053. {
  6054. buffer->draw(LLRender::LINE_LOOP, 3, i);
  6055. buffer->draw(LLRender::POINTS, 3, i);
  6056. }
  6057. }
  6058. buffer->unmapBuffer();
  6059. }
  6060. }
  6061. decomp->mMutex.unlock();
  6062. gGL.popMatrix();
  6063. }
  6064. gGL.lineWidth(1.f);
  6065. glPointSize(1.f);
  6066. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  6067. }
  6068. stop_glerror();
  6069. }
  6070. }
  6071. }
  6072. else if (mPreviewAvatar)
  6073. {
  6074. target_pos = mPreviewAvatar->getPositionAgent();
  6075. mPreviewAvatar->clearAttachmentOverrides(); // Removes pelvis fixup
  6076. LLUUID fake_mesh_id;
  6077. fake_mesh_id.generate();
  6078. mPreviewAvatar->addPelvisFixup(mPelvisZOffset, fake_mesh_id);
  6079. bool pelvis_recalc = false;
  6080. gViewerCamera.setOriginAndLookAt(target_pos +
  6081. (LLVector3(cam_dist, 0.f, 0.f) + offset) *
  6082. av_rot,
  6083. LLVector3::z_axis, target_pos);
  6084. for (LLModelLoader::scene::iterator
  6085. iter = mScene[mPreviewLOD].begin(),
  6086. end = mScene[mPreviewLOD].end();
  6087. iter != end; ++iter)
  6088. {
  6089. for (LLModelLoader::model_instance_list_t::iterator
  6090. model_iter = iter->second.begin(),
  6091. model_end = iter->second.end();
  6092. model_iter != model_end; ++model_iter)
  6093. {
  6094. LLModelInstance& instance = *model_iter;
  6095. LLModel* model = instance.mModel;
  6096. if (!model || model->mSkinWeights.empty())
  6097. {
  6098. continue;
  6099. }
  6100. const LLMeshSkinInfo* skin = &model->mSkinInfo;
  6101. U32 joint_count = llmin(LL_MAX_JOINTS_PER_MESH_OBJECT,
  6102. (U32)skin->mJointKeys.size());
  6103. U32 bind_count = skin->mAlternateBindMatrix.size();
  6104. if (joint_overrides && bind_count &&
  6105. joint_count == bind_count)
  6106. {
  6107. // Mesh Id is used to determine which mesh gets to set
  6108. // the joint offset in the event of a conflict. Since
  6109. // we do not know the mesh id yet, we cannot guarantee
  6110. // that joint offsets will be applied with the same
  6111. // priority as in the uploaded model. If the file
  6112. // contains multiple meshes with conflicting joint
  6113. // offsets, preview may be incorrect.
  6114. LLUUID fake_mesh_id;
  6115. fake_mesh_id.generate();
  6116. for (U32 j = 0; j < joint_count; ++j)
  6117. {
  6118. LLJoint* joint =
  6119. mPreviewAvatar->getJoint(skin->mJointKeys[j]);
  6120. if (!joint) continue;
  6121. const LLVector3& jpos =
  6122. skin->mAlternateBindMatrix[j].getTranslation();
  6123. if (!joint->aboveJointPosThreshold(jpos))
  6124. {
  6125. continue;
  6126. }
  6127. bool changed;
  6128. joint->addAttachmentPosOverride(jpos, fake_mesh_id,
  6129. "model", &changed);
  6130. // If joint is a pelvis then handle old/new pelvis
  6131. // to foot values
  6132. if (changed &&
  6133. skin->mJointKeys[j] == LL_JOINT_KEY_PELVIS)
  6134. {
  6135. pelvis_recalc = true;
  6136. }
  6137. if (skin->mLockScaleIfJointPosition)
  6138. {
  6139. // Note that unlike positions, there is no
  6140. // threshold check here, just a lock at the
  6141. // default value.
  6142. joint->addAttachmentScaleOverride(joint->getDefaultScale(),
  6143. fake_mesh_id,
  6144. "model");
  6145. }
  6146. }
  6147. }
  6148. for (U32 i = 0,
  6149. count = mVertexBuffer[mPreviewLOD][model].size();
  6150. i < count; ++i)
  6151. {
  6152. LLVertexBuffer* buffer =
  6153. mVertexBuffer[mPreviewLOD][model][i];
  6154. if (gUsePBRShaders)
  6155. {
  6156. model->mSkinInfo.updateHash(true); // true = force
  6157. upload_matrix_palette(mPreviewAvatar,
  6158. &model->mSkinInfo);
  6159. unit0->unbind(LLTexUnit::TT_TEXTURE);
  6160. if (textures)
  6161. {
  6162. U32 mat_count =
  6163. instance.mModel->mMaterialList.size();
  6164. if (i < mat_count)
  6165. {
  6166. const std::string& binding =
  6167. instance.mModel->mMaterialList[i];
  6168. const LLImportMaterial& material =
  6169. instance.mMaterial[binding];
  6170. gGL.diffuseColor4fv(material.mDiffuseColor.mV);
  6171. // Find the tex for this material, bind it,
  6172. // and add it to our set
  6173. LLViewerFetchedTexture* tex =
  6174. bind_mat_diffuse_tex(material);
  6175. if (tex)
  6176. {
  6177. mTextureSet.insert(tex);
  6178. }
  6179. }
  6180. }
  6181. else
  6182. {
  6183. gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
  6184. }
  6185. buffer->setBuffer();
  6186. }
  6187. else
  6188. {
  6189. const LLVolumeFace& face = model->getVolumeFace(i);
  6190. LLStrider<LLVector3> position;
  6191. LLStrider<LLVector4a> weight;
  6192. if (!buffer->getVertexStrider(position) ||
  6193. !buffer->getWeight4Strider(weight))
  6194. {
  6195. gObjectPreviewProgram.bind();
  6196. gGL.popMatrix();
  6197. return false;
  6198. }
  6199. // Build matrix palette
  6200. LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
  6201. LLSkinningUtil::initSkinningMatrixPalette(mat, skin,
  6202. mPreviewAvatar);
  6203. LLMatrix4a bind_shape_matrix;
  6204. bind_shape_matrix.loadu(skin->mBindShapeMatrix);
  6205. for (U32 j = 0, count2 = buffer->getNumVerts();
  6206. j < count2; ++j)
  6207. {
  6208. LLMatrix4a final_mat;
  6209. LLSkinningUtil::getPerVertexSkinMatrix(weight[j],
  6210. mat,
  6211. final_mat,
  6212. true);
  6213. LLVector4a& v = face.mPositions[j];
  6214. LLVector4a t;
  6215. LLVector4a dst;
  6216. bind_shape_matrix.affineTransform(v, t);
  6217. final_mat.affineTransform(t, dst);
  6218. position[j][0] = dst[0];
  6219. position[j][1] = dst[1];
  6220. position[j][2] = dst[2];
  6221. }
  6222. // Make sure there is a material set before
  6223. // dereferencing it; if none, set the buffer type and
  6224. // unbind the texture.
  6225. if (instance.mModel->mMaterialList.size() > i &&
  6226. instance.mMaterial.find(instance.mModel->mMaterialList[i]) !=
  6227. instance.mMaterial.end())
  6228. {
  6229. const std::string& binding =
  6230. instance.mModel->mMaterialList[i];
  6231. const LLImportMaterial& material =
  6232. instance.mMaterial[binding];
  6233. // Note: mask ignored in PBR rendering mode
  6234. buffer->setBuffer(type_mask &
  6235. buffer->getTypeMask());
  6236. gGL.diffuseColor4fv(material.mDiffuseColor.mV);
  6237. unit0->unbind(LLTexUnit::TT_TEXTURE);
  6238. // Find the tex for this material, bind it and add
  6239. // it to our set
  6240. LLViewerFetchedTexture* tex =
  6241. bind_mat_diffuse_tex(material);
  6242. if (tex)
  6243. {
  6244. mTextureSet.insert(tex);
  6245. }
  6246. }
  6247. else
  6248. {
  6249. buffer->setBuffer(type_mask &
  6250. buffer->getTypeMask());
  6251. unit0->unbind(LLTexUnit::TT_TEXTURE);
  6252. }
  6253. }
  6254. buffer->draw(LLRender::TRIANGLES,
  6255. buffer->getNumIndices(), 0);
  6256. if (edges)
  6257. {
  6258. if (gUsePBRShaders)
  6259. {
  6260. unit0->unbind(LLTexUnit::TT_TEXTURE);
  6261. }
  6262. gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
  6263. gGL.lineWidth(1.f);
  6264. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  6265. buffer->draw(LLRender::TRIANGLES,
  6266. buffer->getNumIndices(), 0);
  6267. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  6268. }
  6269. buffer->unmapBuffer();
  6270. }
  6271. }
  6272. }
  6273. stop_glerror();
  6274. if (joint_positions || collision_volumes)
  6275. {
  6276. LLGLSLShader* shaderp = LLGLSLShader::sCurBoundShaderPtr;
  6277. if (shaderp)
  6278. {
  6279. gDebugProgram.bind();
  6280. }
  6281. if (collision_volumes)
  6282. {
  6283. mPreviewAvatar->renderCollisionVolumes();
  6284. }
  6285. if (joint_positions)
  6286. {
  6287. if (mFMP->mTabContainer->getCurrentPanel() ==
  6288. mFMP->mModifiersPanel)
  6289. {
  6290. mPreviewAvatar->renderBones(mFMP->mSelectedJointName);
  6291. }
  6292. else
  6293. {
  6294. mPreviewAvatar->renderBones();
  6295. }
  6296. renderGroundPlane(mPelvisZOffset);
  6297. }
  6298. if (shaderp)
  6299. {
  6300. shaderp->bind();
  6301. }
  6302. }
  6303. if (pelvis_recalc)
  6304. {
  6305. // Size/scale re-calculation
  6306. mPreviewAvatar->postPelvisSetRecalc();
  6307. }
  6308. }
  6309. }
  6310. // Note: this could be either of gObjectPreviewProgram or its rigged
  6311. // variant (gSkinnedObjectPreviewProgram). HB
  6312. if (LLGLSLShader::sCurBoundShaderPtr) // Paranoia
  6313. {
  6314. LLGLSLShader::sCurBoundShaderPtr->unbind();
  6315. }
  6316. gGL.popMatrix();
  6317. return true;
  6318. }
  6319. void LLModelPreview::renderGroundPlane(F32 z_offset)
  6320. {
  6321. gGL.diffuseColor3f(1.f, 0.f, 1.f);
  6322. gGL.begin(LLRender::LINES);
  6323. gGL.vertex3fv(mGroundPlane[0].mV);
  6324. gGL.vertex3fv(mGroundPlane[1].mV);
  6325. gGL.vertex3fv(mGroundPlane[1].mV);
  6326. gGL.vertex3fv(mGroundPlane[2].mV);
  6327. gGL.vertex3fv(mGroundPlane[2].mV);
  6328. gGL.vertex3fv(mGroundPlane[3].mV);
  6329. gGL.vertex3fv(mGroundPlane[3].mV);
  6330. gGL.vertex3fv(mGroundPlane[0].mV);
  6331. gGL.end();
  6332. }
  6333. void LLModelPreview::rotate(F32 yaw_radians, F32 pitch_radians)
  6334. {
  6335. mCameraYaw = mCameraYaw + yaw_radians;
  6336. constexpr F32 limit = 0.8f * F_PI_BY_TWO;
  6337. mCameraPitch = llclamp(mCameraPitch + pitch_radians, -limit, limit);
  6338. }
  6339. void LLModelPreview::zoom(F32 zoom_amt)
  6340. {
  6341. F32 new_zoom = mCameraZoom + zoom_amt;
  6342. mCameraZoom = llclamp(new_zoom, 1.f, PREVIEW_ZOOM_LIMIT);
  6343. }
  6344. void LLModelPreview::pan(F32 right, F32 up)
  6345. {
  6346. bool skin_weight = mViewOption["show_skin_weight"];
  6347. F32 cam_dist = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
  6348. mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] +
  6349. right * cam_dist / mCameraZoom,
  6350. -1.f, 1.f);
  6351. mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] +
  6352. up * cam_dist / mCameraZoom,
  6353. -1.f, 1.f);
  6354. }
  6355. void LLModelPreview::setPreviewLOD(S32 lod)
  6356. {
  6357. lod = llclamp(lod, 0, (S32)LLModel::LOD_HIGH);
  6358. if (lod != mPreviewLOD && mFMP)
  6359. {
  6360. mPreviewLOD = lod;
  6361. LLComboBox* combo_box =
  6362. mFMP->getChild<LLComboBox>("preview_lod_combo");
  6363. // Combo box list of lods is in reverse order
  6364. combo_box->setCurrentByIndex(NUM_LOD - 1 - mPreviewLOD);
  6365. std::string cname = "lod_file_" + lod_name[mPreviewLOD];
  6366. mFMP->childSetText(cname.c_str(), mLODFile[mPreviewLOD]);
  6367. LLColor4 highlight_color =
  6368. gColors.getColor("MeshImportTableHighlightColor");
  6369. LLColor4 normal_color = gColors.getColor("MeshImportTableNormalColor");
  6370. for (S32 i = 0; i <= LLModel::LOD_HIGH; ++i)
  6371. {
  6372. const LLColor4& color = i == lod ? highlight_color : normal_color;
  6373. mFMP->childSetColor(lod_status_name[i], color);
  6374. mFMP->childSetColor(lod_label_name[i], color);
  6375. mFMP->childSetColor(lod_triangles_name[i], color);
  6376. mFMP->childSetColor(lod_vertices_name[i], color);
  6377. }
  6378. // Make preview repopulate info
  6379. mFMP->clearSkinningInfo();
  6380. }
  6381. refresh();
  6382. }
  6383. //static
  6384. void LLModelPreview::textureLoadedCallback(bool success,
  6385. LLViewerFetchedTexture* src_vi,
  6386. LLImageRaw* src,
  6387. LLImageRaw* src_aux,
  6388. S32 discard_level, bool is_final,
  6389. void* userdata)
  6390. {
  6391. // Not the best solution, but the model preview belongs to the floater, so
  6392. // it is an easy way to check that the preview still exists.
  6393. LLFloaterModelPreview* fmp = LLFloaterModelPreview::findInstance();
  6394. if (!fmp) return; // Floater gone !
  6395. LLModelPreview* self = (LLModelPreview*)userdata;
  6396. if (!self || self != fmp->mModelPreview) return; // Preview changed
  6397. self->refresh();
  6398. if (is_final && self->mModelLoader)
  6399. {
  6400. if (self->mModelLoader->mNumOfFetchingTextures > 0)
  6401. {
  6402. --self->mModelLoader->mNumOfFetchingTextures;
  6403. }
  6404. }
  6405. }
  6406. //static
  6407. bool LLModelPreview::lodQueryCallback()
  6408. {
  6409. // Not the best solution, but the model preview belongs to the floater, so
  6410. // it is an easy way to check that the preview still exists.
  6411. LLFloaterModelPreview* fmp = LLFloaterModelPreview::findInstance();
  6412. if (!fmp) return true; // Floater gone !
  6413. LLModelPreview* self = fmp->mModelPreview;
  6414. if (self)
  6415. {
  6416. if (!self->mLodsQuery.empty())
  6417. {
  6418. S32 lod = self->mLodsQuery.back();
  6419. // *HACK: when GLOD fails, try genMeshOptimizerLODs()... HB
  6420. if (!self->genGlodLODs(lod))
  6421. {
  6422. llwarns << "GLOD failed, trying with meshoptimizer." << llendl;
  6423. self->genMeshOptimizerLODs(lod, MESH_OPTIMIZER_AUTO);
  6424. }
  6425. self->mLodsQuery.pop_back();
  6426. // Return false to continue the LOD generation cycle when
  6427. // mLodsQuery is not empty
  6428. return self->mLodsQuery.empty();
  6429. }
  6430. }
  6431. // Nothing left to process
  6432. return true;
  6433. }
  6434. void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
  6435. {
  6436. if (!mFMP || mLODFrozen)
  6437. {
  6438. return;
  6439. }
  6440. std::string cname = "lod_source_" + lod_name[lod];
  6441. S32 lod_mode =
  6442. mFMP->getChild<LLComboBox>(cname.c_str())->getCurrentIndex();
  6443. if (lod_mode == GENERATE)
  6444. {
  6445. // *HACK: when GLOD fails, try genMeshOptimizerLODs()... HB
  6446. if (!genGlodLODs(lod, 3, enforce_tri_limit))
  6447. {
  6448. llwarns << "GLOD failed, trying with meshoptimizer." << llendl;
  6449. genMeshOptimizerLODs(lod, MESH_OPTIMIZER_AUTO, 3,
  6450. enforce_tri_limit);
  6451. }
  6452. refresh();
  6453. }
  6454. else if (lod_mode > GENERATE && lod_mode < USE_LOD_ABOVE)
  6455. {
  6456. genMeshOptimizerLODs(lod, lod_mode, 3, enforce_tri_limit);
  6457. refresh();
  6458. }
  6459. }