rmodels.c 313 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003
  1. /**********************************************************************************************
  2. *
  3. * rmodels - Basic functions to draw 3d shapes and load and draw 3d models
  4. *
  5. * CONFIGURATION:
  6. * #define SUPPORT_MODULE_RMODELS
  7. * rmodels module is included in the build
  8. *
  9. * #define SUPPORT_FILEFORMAT_OBJ
  10. * #define SUPPORT_FILEFORMAT_MTL
  11. * #define SUPPORT_FILEFORMAT_IQM
  12. * #define SUPPORT_FILEFORMAT_GLTF
  13. * #define SUPPORT_FILEFORMAT_VOX
  14. * #define SUPPORT_FILEFORMAT_M3D
  15. * Selected desired fileformats to be supported for model data loading
  16. *
  17. * #define SUPPORT_MESH_GENERATION
  18. * Support procedural mesh generation functions, uses external par_shapes.h library
  19. * NOTE: Some generated meshes DO NOT include generated texture coordinates
  20. *
  21. *
  22. * LICENSE: zlib/libpng
  23. *
  24. * Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
  25. *
  26. * This software is provided "as-is", without any express or implied warranty. In no event
  27. * will the authors be held liable for any damages arising from the use of this software.
  28. *
  29. * Permission is granted to anyone to use this software for any purpose, including commercial
  30. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  31. *
  32. * 1. The origin of this software must not be misrepresented; you must not claim that you
  33. * wrote the original software. If you use this software in a product, an acknowledgment
  34. * in the product documentation would be appreciated but is not required.
  35. *
  36. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  37. * as being the original software.
  38. *
  39. * 3. This notice may not be removed or altered from any source distribution.
  40. *
  41. **********************************************************************************************/
  42. #include "raylib.h" // Declares module functions
  43. // Check if config flags have been externally provided on compilation line
  44. #if !defined(EXTERNAL_CONFIG_FLAGS)
  45. #include "config.h" // Defines module configuration flags
  46. #endif
  47. #if defined(SUPPORT_MODULE_RMODELS)
  48. #include "utils.h" // Required for: TRACELOG(), LoadFileData(), LoadFileText(), SaveFileText()
  49. #include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
  50. #include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality
  51. #include <stdio.h> // Required for: sprintf()
  52. #include <stdlib.h> // Required for: malloc(), calloc(), free()
  53. #include <string.h> // Required for: memcmp(), strlen(), strncpy()
  54. #include <math.h> // Required for: sinf(), cosf(), sqrtf(), fabsf()
  55. #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
  56. #define TINYOBJ_MALLOC RL_MALLOC
  57. #define TINYOBJ_CALLOC RL_CALLOC
  58. #define TINYOBJ_REALLOC RL_REALLOC
  59. #define TINYOBJ_FREE RL_FREE
  60. #define TINYOBJ_LOADER_C_IMPLEMENTATION
  61. #include "external/tinyobj_loader_c.h" // OBJ/MTL file formats loading
  62. #endif
  63. #if defined(SUPPORT_FILEFORMAT_GLTF)
  64. #define CGLTF_MALLOC RL_MALLOC
  65. #define CGLTF_FREE RL_FREE
  66. #define CGLTF_IMPLEMENTATION
  67. #include "external/cgltf.h" // glTF file format loading
  68. #endif
  69. #if defined(SUPPORT_FILEFORMAT_VOX)
  70. #define VOX_MALLOC RL_MALLOC
  71. #define VOX_CALLOC RL_CALLOC
  72. #define VOX_REALLOC RL_REALLOC
  73. #define VOX_FREE RL_FREE
  74. #define VOX_LOADER_IMPLEMENTATION
  75. #include "external/vox_loader.h" // VOX file format loading (MagikaVoxel)
  76. #endif
  77. #if defined(SUPPORT_FILEFORMAT_M3D)
  78. #define M3D_MALLOC RL_MALLOC
  79. #define M3D_REALLOC RL_REALLOC
  80. #define M3D_FREE RL_FREE
  81. #define M3D_IMPLEMENTATION
  82. #include "external/m3d.h" // Model3D file format loading
  83. #endif
  84. #if defined(SUPPORT_MESH_GENERATION)
  85. #define PAR_MALLOC(T, N) ((T *)RL_MALLOC(N*sizeof(T)))
  86. #define PAR_CALLOC(T, N) ((T *)RL_CALLOC(N*sizeof(T), 1))
  87. #define PAR_REALLOC(T, BUF, N) ((T *)RL_REALLOC(BUF, sizeof(T)*(N)))
  88. #define PAR_FREE RL_FREE
  89. #if defined(_MSC_VER) // Disable some MSVC warning
  90. #pragma warning(push)
  91. #pragma warning(disable : 4244)
  92. #pragma warning(disable : 4305)
  93. #endif
  94. #define PAR_SHAPES_IMPLEMENTATION
  95. #include "external/par_shapes.h" // Shapes 3d parametric generation
  96. #if defined(_MSC_VER)
  97. #pragma warning(pop) // Disable MSVC warning suppression
  98. #endif
  99. #endif
  100. #if defined(_WIN32)
  101. #include <direct.h> // Required for: _chdir() [Used in LoadOBJ()]
  102. #define CHDIR _chdir
  103. #else
  104. #include <unistd.h> // Required for: chdir() (POSIX) [Used in LoadOBJ()]
  105. #define CHDIR chdir
  106. #endif
  107. //----------------------------------------------------------------------------------
  108. // Defines and Macros
  109. //----------------------------------------------------------------------------------
  110. #ifndef MAX_MATERIAL_MAPS
  111. #define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported
  112. #endif
  113. #ifndef MAX_MESH_VERTEX_BUFFERS
  114. #define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
  115. #endif
  116. //----------------------------------------------------------------------------------
  117. // Types and Structures Definition
  118. //----------------------------------------------------------------------------------
  119. // ...
  120. //----------------------------------------------------------------------------------
  121. // Global Variables Definition
  122. //----------------------------------------------------------------------------------
  123. // ...
  124. //----------------------------------------------------------------------------------
  125. // Module Internal Functions Declaration
  126. //----------------------------------------------------------------------------------
  127. #if defined(SUPPORT_FILEFORMAT_OBJ)
  128. static Model LoadOBJ(const char *fileName); // Load OBJ mesh data
  129. #endif
  130. #if defined(SUPPORT_FILEFORMAT_IQM)
  131. static Model LoadIQM(const char *fileName); // Load IQM mesh data
  132. static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount); // Load IQM animation data
  133. #endif
  134. #if defined(SUPPORT_FILEFORMAT_GLTF)
  135. static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
  136. static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount); // Load GLTF animation data
  137. #endif
  138. #if defined(SUPPORT_FILEFORMAT_VOX)
  139. static Model LoadVOX(const char *filename); // Load VOX mesh data
  140. #endif
  141. #if defined(SUPPORT_FILEFORMAT_M3D)
  142. static Model LoadM3D(const char *filename); // Load M3D mesh data
  143. static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount); // Load M3D animation data
  144. #endif
  145. #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
  146. static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
  147. #endif
  148. //----------------------------------------------------------------------------------
  149. // Module Functions Definition
  150. //----------------------------------------------------------------------------------
  151. // Draw a line in 3D world space
  152. void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color)
  153. {
  154. rlBegin(RL_LINES);
  155. rlColor4ub(color.r, color.g, color.b, color.a);
  156. rlVertex3f(startPos.x, startPos.y, startPos.z);
  157. rlVertex3f(endPos.x, endPos.y, endPos.z);
  158. rlEnd();
  159. }
  160. // Draw a point in 3D space, actually a small line
  161. // WARNING: OpenGL ES 2.0 does not support point mode drawing
  162. void DrawPoint3D(Vector3 position, Color color)
  163. {
  164. rlPushMatrix();
  165. rlTranslatef(position.x, position.y, position.z);
  166. rlBegin(RL_LINES);
  167. rlColor4ub(color.r, color.g, color.b, color.a);
  168. rlVertex3f(0.0f, 0.0f, 0.0f);
  169. rlVertex3f(0.0f, 0.0f, 0.1f);
  170. rlEnd();
  171. rlPopMatrix();
  172. }
  173. // Draw a circle in 3D world space
  174. void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color)
  175. {
  176. rlPushMatrix();
  177. rlTranslatef(center.x, center.y, center.z);
  178. rlRotatef(rotationAngle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
  179. rlBegin(RL_LINES);
  180. for (int i = 0; i < 360; i += 10)
  181. {
  182. rlColor4ub(color.r, color.g, color.b, color.a);
  183. rlVertex3f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius, 0.0f);
  184. rlVertex3f(sinf(DEG2RAD*(i + 10))*radius, cosf(DEG2RAD*(i + 10))*radius, 0.0f);
  185. }
  186. rlEnd();
  187. rlPopMatrix();
  188. }
  189. // Draw a color-filled triangle (vertex in counter-clockwise order!)
  190. void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)
  191. {
  192. rlBegin(RL_TRIANGLES);
  193. rlColor4ub(color.r, color.g, color.b, color.a);
  194. rlVertex3f(v1.x, v1.y, v1.z);
  195. rlVertex3f(v2.x, v2.y, v2.z);
  196. rlVertex3f(v3.x, v3.y, v3.z);
  197. rlEnd();
  198. }
  199. // Draw a triangle strip defined by points
  200. void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color)
  201. {
  202. if (pointCount < 3) return; // Security check
  203. rlBegin(RL_TRIANGLES);
  204. rlColor4ub(color.r, color.g, color.b, color.a);
  205. for (int i = 2; i < pointCount; i++)
  206. {
  207. if ((i%2) == 0)
  208. {
  209. rlVertex3f(points[i].x, points[i].y, points[i].z);
  210. rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);
  211. rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);
  212. }
  213. else
  214. {
  215. rlVertex3f(points[i].x, points[i].y, points[i].z);
  216. rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);
  217. rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);
  218. }
  219. }
  220. rlEnd();
  221. }
  222. // Draw cube
  223. // NOTE: Cube position is the center position
  224. void DrawCube(Vector3 position, float width, float height, float length, Color color)
  225. {
  226. float x = 0.0f;
  227. float y = 0.0f;
  228. float z = 0.0f;
  229. rlPushMatrix();
  230. // NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)
  231. rlTranslatef(position.x, position.y, position.z);
  232. //rlRotatef(45, 0, 1, 0);
  233. //rlScalef(1.0f, 1.0f, 1.0f); // NOTE: Vertices are directly scaled on definition
  234. rlBegin(RL_TRIANGLES);
  235. rlColor4ub(color.r, color.g, color.b, color.a);
  236. // Front face
  237. rlNormal3f(0.0f, 0.0f, 1.0f);
  238. rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left
  239. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right
  240. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left
  241. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right
  242. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left
  243. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right
  244. // Back face
  245. rlNormal3f(0.0f, 0.0f, -1.0f);
  246. rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left
  247. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left
  248. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right
  249. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right
  250. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right
  251. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left
  252. // Top face
  253. rlNormal3f(0.0f, 1.0f, 0.0f);
  254. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left
  255. rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left
  256. rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right
  257. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right
  258. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left
  259. rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right
  260. // Bottom face
  261. rlNormal3f(0.0f, -1.0f, 0.0f);
  262. rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left
  263. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right
  264. rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left
  265. rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Right
  266. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right
  267. rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left
  268. // Right face
  269. rlNormal3f(1.0f, 0.0f, 0.0f);
  270. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right
  271. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right
  272. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left
  273. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left
  274. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right
  275. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left
  276. // Left face
  277. rlNormal3f(-1.0f, 0.0f, 0.0f);
  278. rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right
  279. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left
  280. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right
  281. rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left
  282. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left
  283. rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right
  284. rlEnd();
  285. rlPopMatrix();
  286. }
  287. // Draw cube (Vector version)
  288. void DrawCubeV(Vector3 position, Vector3 size, Color color)
  289. {
  290. DrawCube(position, size.x, size.y, size.z, color);
  291. }
  292. // Draw cube wires
  293. void DrawCubeWires(Vector3 position, float width, float height, float length, Color color)
  294. {
  295. float x = 0.0f;
  296. float y = 0.0f;
  297. float z = 0.0f;
  298. rlPushMatrix();
  299. rlTranslatef(position.x, position.y, position.z);
  300. rlBegin(RL_LINES);
  301. rlColor4ub(color.r, color.g, color.b, color.a);
  302. // Front face
  303. //------------------------------------------------------------------
  304. // Bottom line
  305. rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left
  306. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right
  307. // Left line
  308. rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right
  309. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right
  310. // Top line
  311. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right
  312. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left
  313. // Right line
  314. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left
  315. rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left
  316. // Back face
  317. //------------------------------------------------------------------
  318. // Bottom line
  319. rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left
  320. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right
  321. // Left line
  322. rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right
  323. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right
  324. // Top line
  325. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right
  326. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left
  327. // Right line
  328. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left
  329. rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left
  330. // Top face
  331. //------------------------------------------------------------------
  332. // Left line
  333. rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left front
  334. rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left back
  335. // Right line
  336. rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right front
  337. rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right back
  338. // Bottom face
  339. //------------------------------------------------------------------
  340. // Left line
  341. rlVertex3f(x - width/2, y - height/2, z + length/2); // Top left front
  342. rlVertex3f(x - width/2, y - height/2, z - length/2); // Top left back
  343. // Right line
  344. rlVertex3f(x + width/2, y - height/2, z + length/2); // Top right front
  345. rlVertex3f(x + width/2, y - height/2, z - length/2); // Top right back
  346. rlEnd();
  347. rlPopMatrix();
  348. }
  349. // Draw cube wires (vector version)
  350. void DrawCubeWiresV(Vector3 position, Vector3 size, Color color)
  351. {
  352. DrawCubeWires(position, size.x, size.y, size.z, color);
  353. }
  354. // Draw sphere
  355. void DrawSphere(Vector3 centerPos, float radius, Color color)
  356. {
  357. DrawSphereEx(centerPos, radius, 16, 16, color);
  358. }
  359. // Draw sphere with extended parameters
  360. void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)
  361. {
  362. #if 0
  363. // Basic implementation, do not use it!
  364. // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls!
  365. // New optimized version below only requires 4 cos()/sin() calls
  366. rlPushMatrix();
  367. // NOTE: Transformation is applied in inverse order (scale -> translate)
  368. rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
  369. rlScalef(radius, radius, radius);
  370. rlBegin(RL_TRIANGLES);
  371. rlColor4ub(color.r, color.g, color.b, color.a);
  372. for (int i = 0; i < (rings + 2); i++)
  373. {
  374. for (int j = 0; j < slices; j++)
  375. {
  376. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
  377. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
  378. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
  379. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
  380. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  381. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
  382. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),
  383. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  384. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));
  385. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
  386. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
  387. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
  388. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
  389. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i))),
  390. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
  391. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
  392. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  393. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
  394. }
  395. }
  396. rlEnd();
  397. rlPopMatrix();
  398. #endif
  399. rlPushMatrix();
  400. // NOTE: Transformation is applied in inverse order (scale -> translate)
  401. rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
  402. rlScalef(radius, radius, radius);
  403. rlBegin(RL_TRIANGLES);
  404. rlColor4ub(color.r, color.g, color.b, color.a);
  405. float ringangle = DEG2RAD*(180.0f/(rings + 1)); // Angle between latitudinal parallels
  406. float sliceangle = DEG2RAD*(360.0f/slices); // Angle between longitudinal meridians
  407. float cosring = cosf(ringangle);
  408. float sinring = sinf(ringangle);
  409. float cosslice = cosf(sliceangle);
  410. float sinslice = sinf(sliceangle);
  411. Vector3 vertices[4] = { 0 }; // Required to store face vertices
  412. vertices[2] = (Vector3){ 0, 1, 0 };
  413. vertices[3] = (Vector3){ sinring, cosring, 0 };
  414. for (int i = 0; i < rings + 1; i++)
  415. {
  416. for (int j = 0; j < slices; j++)
  417. {
  418. vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face
  419. vertices[1] = vertices[3];
  420. vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis
  421. vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z };
  422. rlNormal3f(vertices[0].x, vertices[0].y, vertices[0].z);
  423. rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
  424. rlNormal3f(vertices[3].x, vertices[3].y, vertices[3].z);
  425. rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
  426. rlNormal3f(vertices[1].x, vertices[1].y, vertices[1].z);
  427. rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z);
  428. rlNormal3f(vertices[0].x, vertices[0].y, vertices[0].z);
  429. rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
  430. rlNormal3f(vertices[2].x, vertices[2].y, vertices[2].z);
  431. rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z);
  432. rlNormal3f(vertices[3].x, vertices[3].y, vertices[3].z);
  433. rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
  434. }
  435. vertices[2] = vertices[3]; // Rotate around z axis to set up starting vertices for next ring
  436. vertices[3] = (Vector3){ cosring*vertices[3].x + sinring*vertices[3].y, -sinring*vertices[3].x + cosring*vertices[3].y, vertices[3].z }; // Rotation matrix around z axis
  437. }
  438. rlEnd();
  439. rlPopMatrix();
  440. }
  441. // Draw sphere wires
  442. void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color)
  443. {
  444. rlPushMatrix();
  445. // NOTE: Transformation is applied in inverse order (scale -> translate)
  446. rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
  447. rlScalef(radius, radius, radius);
  448. rlBegin(RL_LINES);
  449. rlColor4ub(color.r, color.g, color.b, color.a);
  450. for (int i = 0; i < (rings + 2); i++)
  451. {
  452. for (int j = 0; j < slices; j++)
  453. {
  454. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
  455. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
  456. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
  457. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
  458. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  459. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
  460. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
  461. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  462. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
  463. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),
  464. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  465. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));
  466. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),
  467. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
  468. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));
  469. rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
  470. sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
  471. cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
  472. }
  473. }
  474. rlEnd();
  475. rlPopMatrix();
  476. }
  477. // Draw a cylinder
  478. // NOTE: It could be also used for pyramid and cone
  479. void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)
  480. {
  481. if (sides < 3) sides = 3;
  482. const float angleStep = 360.0f/sides;
  483. rlPushMatrix();
  484. rlTranslatef(position.x, position.y, position.z);
  485. rlBegin(RL_TRIANGLES);
  486. rlColor4ub(color.r, color.g, color.b, color.a);
  487. if (radiusTop > 0)
  488. {
  489. // Draw Body -------------------------------------------------------------------------------------
  490. for (int i = 0; i < sides; i++)
  491. {
  492. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom); //Bottom Left
  493. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom); //Bottom Right
  494. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop); //Top Right
  495. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop); //Top Left
  496. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom); //Bottom Left
  497. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop); //Top Right
  498. }
  499. // Draw Cap --------------------------------------------------------------------------------------
  500. for (int i = 0; i < sides; i++)
  501. {
  502. rlVertex3f(0, height, 0);
  503. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);
  504. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);
  505. }
  506. }
  507. else
  508. {
  509. // Draw Cone -------------------------------------------------------------------------------------
  510. for (int i = 0; i < sides; i++)
  511. {
  512. rlVertex3f(0, height, 0);
  513. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);
  514. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);
  515. }
  516. }
  517. // Draw Base -----------------------------------------------------------------------------------------
  518. for (int i = 0; i < sides; i++)
  519. {
  520. rlVertex3f(0, 0, 0);
  521. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);
  522. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);
  523. }
  524. rlEnd();
  525. rlPopMatrix();
  526. }
  527. // Draw a cylinder with base at startPos and top at endPos
  528. // NOTE: It could be also used for pyramid and cone
  529. void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
  530. {
  531. if (sides < 3) sides = 3;
  532. Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
  533. if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check
  534. // Construct a basis of the base and the top face:
  535. Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
  536. Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
  537. float baseAngle = (2.0f*PI)/sides;
  538. rlBegin(RL_TRIANGLES);
  539. rlColor4ub(color.r, color.g, color.b, color.a);
  540. for (int i = 0; i < sides; i++)
  541. {
  542. // Compute the four vertices
  543. float s1 = sinf(baseAngle*(i + 0))*startRadius;
  544. float c1 = cosf(baseAngle*(i + 0))*startRadius;
  545. Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };
  546. float s2 = sinf(baseAngle*(i + 1))*startRadius;
  547. float c2 = cosf(baseAngle*(i + 1))*startRadius;
  548. Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };
  549. float s3 = sinf(baseAngle*(i + 0))*endRadius;
  550. float c3 = cosf(baseAngle*(i + 0))*endRadius;
  551. Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };
  552. float s4 = sinf(baseAngle*(i + 1))*endRadius;
  553. float c4 = cosf(baseAngle*(i + 1))*endRadius;
  554. Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };
  555. if (startRadius > 0)
  556. {
  557. rlVertex3f(startPos.x, startPos.y, startPos.z); // |
  558. rlVertex3f(w2.x, w2.y, w2.z); // T0
  559. rlVertex3f(w1.x, w1.y, w1.z); // |
  560. }
  561. // w2 x.-----------x startPos
  562. rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /
  563. rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /
  564. rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /
  565. // | 2 \ T 'x w1
  566. rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos
  567. rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/
  568. rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /
  569. // '.\|/
  570. if (endRadius > 0) // 'x w3
  571. {
  572. rlVertex3f(endPos.x, endPos.y, endPos.z); // |
  573. rlVertex3f(w3.x, w3.y, w3.z); // T3
  574. rlVertex3f(w4.x, w4.y, w4.z); // |
  575. } //
  576. }
  577. rlEnd();
  578. }
  579. // Draw a wired cylinder
  580. // NOTE: It could be also used for pyramid and cone
  581. void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)
  582. {
  583. if (sides < 3) sides = 3;
  584. const float angleStep = 360.0f/sides;
  585. rlPushMatrix();
  586. rlTranslatef(position.x, position.y, position.z);
  587. rlBegin(RL_LINES);
  588. rlColor4ub(color.r, color.g, color.b, color.a);
  589. for (int i = 0; i < sides; i++)
  590. {
  591. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);
  592. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);
  593. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);
  594. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);
  595. rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);
  596. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);
  597. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);
  598. rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);
  599. }
  600. rlEnd();
  601. rlPopMatrix();
  602. }
  603. // Draw a wired cylinder with base at startPos and top at endPos
  604. // NOTE: It could be also used for pyramid and cone
  605. void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
  606. {
  607. if (sides < 3) sides = 3;
  608. Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
  609. if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check
  610. // Construct a basis of the base and the top face:
  611. Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
  612. Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
  613. float baseAngle = (2.0f*PI)/sides;
  614. rlBegin(RL_LINES);
  615. rlColor4ub(color.r, color.g, color.b, color.a);
  616. for (int i = 0; i < sides; i++)
  617. {
  618. // Compute the four vertices
  619. float s1 = sinf(baseAngle*(i + 0))*startRadius;
  620. float c1 = cosf(baseAngle*(i + 0))*startRadius;
  621. Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };
  622. float s2 = sinf(baseAngle*(i + 1))*startRadius;
  623. float c2 = cosf(baseAngle*(i + 1))*startRadius;
  624. Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };
  625. float s3 = sinf(baseAngle*(i + 0))*endRadius;
  626. float c3 = cosf(baseAngle*(i + 0))*endRadius;
  627. Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };
  628. float s4 = sinf(baseAngle*(i + 1))*endRadius;
  629. float c4 = cosf(baseAngle*(i + 1))*endRadius;
  630. Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };
  631. rlVertex3f(w1.x, w1.y, w1.z);
  632. rlVertex3f(w2.x, w2.y, w2.z);
  633. rlVertex3f(w1.x, w1.y, w1.z);
  634. rlVertex3f(w3.x, w3.y, w3.z);
  635. rlVertex3f(w3.x, w3.y, w3.z);
  636. rlVertex3f(w4.x, w4.y, w4.z);
  637. }
  638. rlEnd();
  639. }
  640. // Draw a capsule with the center of its sphere caps at startPos and endPos
  641. void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
  642. {
  643. if (slices < 3) slices = 3;
  644. Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
  645. // draw a sphere if start and end points are the same
  646. bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);
  647. if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};
  648. // Construct a basis of the base and the caps:
  649. Vector3 b0 = Vector3Normalize(direction);
  650. Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
  651. Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
  652. Vector3 capCenter = endPos;
  653. float baseSliceAngle = (2.0f*PI)/slices;
  654. float baseRingAngle = PI*0.5f/rings;
  655. rlBegin(RL_TRIANGLES);
  656. rlColor4ub(color.r, color.g, color.b, color.a);
  657. // render both caps
  658. for (int c = 0; c < 2; c++)
  659. {
  660. for (int i = 0; i < rings; i++)
  661. {
  662. for (int j = 0; j < slices; j++)
  663. {
  664. // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
  665. // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
  666. // as we iterate through the rings they must get smaller by the cos(angle(i))
  667. // compute the four vertices
  668. float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
  669. float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
  670. Vector3 w1 = (Vector3){
  671. capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x)*radius,
  672. capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y)*radius,
  673. capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z)*radius
  674. };
  675. float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));
  676. float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));
  677. Vector3 w2 = (Vector3){
  678. capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x)*radius,
  679. capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y)*radius,
  680. capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z)*radius
  681. };
  682. float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));
  683. float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));
  684. Vector3 w3 = (Vector3){
  685. capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x)*radius,
  686. capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y)*radius,
  687. capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z)*radius
  688. };
  689. float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));
  690. float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));
  691. Vector3 w4 = (Vector3){
  692. capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x)*radius,
  693. capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y)*radius,
  694. capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z)*radius
  695. };
  696. // Make sure cap triangle normals are facing outwards
  697. if (c == 0)
  698. {
  699. rlVertex3f(w1.x, w1.y, w1.z);
  700. rlVertex3f(w2.x, w2.y, w2.z);
  701. rlVertex3f(w3.x, w3.y, w3.z);
  702. rlVertex3f(w2.x, w2.y, w2.z);
  703. rlVertex3f(w4.x, w4.y, w4.z);
  704. rlVertex3f(w3.x, w3.y, w3.z);
  705. }
  706. else
  707. {
  708. rlVertex3f(w1.x, w1.y, w1.z);
  709. rlVertex3f(w3.x, w3.y, w3.z);
  710. rlVertex3f(w2.x, w2.y, w2.z);
  711. rlVertex3f(w2.x, w2.y, w2.z);
  712. rlVertex3f(w3.x, w3.y, w3.z);
  713. rlVertex3f(w4.x, w4.y, w4.z);
  714. }
  715. }
  716. }
  717. capCenter = startPos;
  718. b0 = Vector3Scale(b0, -1.0f);
  719. }
  720. // render middle
  721. if (!sphereCase)
  722. {
  723. for (int j = 0; j < slices; j++)
  724. {
  725. // compute the four vertices
  726. float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
  727. float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
  728. Vector3 w1 = {
  729. startPos.x + ringSin1*b1.x + ringCos1*b2.x,
  730. startPos.y + ringSin1*b1.y + ringCos1*b2.y,
  731. startPos.z + ringSin1*b1.z + ringCos1*b2.z
  732. };
  733. float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
  734. float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
  735. Vector3 w2 = {
  736. startPos.x + ringSin2*b1.x + ringCos2*b2.x,
  737. startPos.y + ringSin2*b1.y + ringCos2*b2.y,
  738. startPos.z + ringSin2*b1.z + ringCos2*b2.z
  739. };
  740. float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
  741. float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
  742. Vector3 w3 = {
  743. endPos.x + ringSin3*b1.x + ringCos3*b2.x,
  744. endPos.y + ringSin3*b1.y + ringCos3*b2.y,
  745. endPos.z + ringSin3*b1.z + ringCos3*b2.z
  746. };
  747. float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
  748. float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
  749. Vector3 w4 = {
  750. endPos.x + ringSin4*b1.x + ringCos4*b2.x,
  751. endPos.y + ringSin4*b1.y + ringCos4*b2.y,
  752. endPos.z + ringSin4*b1.z + ringCos4*b2.z
  753. };
  754. // w2 x.-----------x startPos
  755. rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /
  756. rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /
  757. rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /
  758. // | 2 \ T 'x w1
  759. rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos
  760. rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/
  761. rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /
  762. // '.\|/
  763. // 'x w3
  764. }
  765. }
  766. rlEnd();
  767. }
  768. // Draw capsule wires with the center of its sphere caps at startPos and endPos
  769. void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
  770. {
  771. if (slices < 3) slices = 3;
  772. Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
  773. // draw a sphere if start and end points are the same
  774. bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);
  775. if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};
  776. // Construct a basis of the base and the caps:
  777. Vector3 b0 = Vector3Normalize(direction);
  778. Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
  779. Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
  780. Vector3 capCenter = endPos;
  781. float baseSliceAngle = (2.0f*PI)/slices;
  782. float baseRingAngle = PI*0.5f/rings;
  783. rlBegin(RL_LINES);
  784. rlColor4ub(color.r, color.g, color.b, color.a);
  785. // render both caps
  786. for (int c = 0; c < 2; c++)
  787. {
  788. for (int i = 0; i < rings; i++)
  789. {
  790. for (int j = 0; j < slices; j++)
  791. {
  792. // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
  793. // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
  794. // as we iterate through the rings they must get smaller by the cos(angle(i))
  795. // compute the four vertices
  796. float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
  797. float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
  798. Vector3 w1 = (Vector3){
  799. capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x)*radius,
  800. capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y)*radius,
  801. capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z)*radius
  802. };
  803. float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));
  804. float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));
  805. Vector3 w2 = (Vector3){
  806. capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x)*radius,
  807. capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y)*radius,
  808. capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z)*radius
  809. };
  810. float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));
  811. float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));
  812. Vector3 w3 = (Vector3){
  813. capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x)*radius,
  814. capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y)*radius,
  815. capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z)*radius
  816. };
  817. float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));
  818. float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));
  819. Vector3 w4 = (Vector3){
  820. capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x)*radius,
  821. capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y)*radius,
  822. capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z)*radius
  823. };
  824. rlVertex3f(w1.x, w1.y, w1.z);
  825. rlVertex3f(w2.x, w2.y, w2.z);
  826. rlVertex3f(w2.x, w2.y, w2.z);
  827. rlVertex3f(w3.x, w3.y, w3.z);
  828. rlVertex3f(w1.x, w1.y, w1.z);
  829. rlVertex3f(w3.x, w3.y, w3.z);
  830. rlVertex3f(w2.x, w2.y, w2.z);
  831. rlVertex3f(w4.x, w4.y, w4.z);
  832. rlVertex3f(w3.x, w3.y, w3.z);
  833. rlVertex3f(w4.x, w4.y, w4.z);
  834. }
  835. }
  836. capCenter = startPos;
  837. b0 = Vector3Scale(b0, -1.0f);
  838. }
  839. // render middle
  840. if (!sphereCase)
  841. {
  842. for (int j = 0; j < slices; j++)
  843. {
  844. // compute the four vertices
  845. float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
  846. float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
  847. Vector3 w1 = {
  848. startPos.x + ringSin1*b1.x + ringCos1*b2.x,
  849. startPos.y + ringSin1*b1.y + ringCos1*b2.y,
  850. startPos.z + ringSin1*b1.z + ringCos1*b2.z
  851. };
  852. float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
  853. float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
  854. Vector3 w2 = {
  855. startPos.x + ringSin2*b1.x + ringCos2*b2.x,
  856. startPos.y + ringSin2*b1.y + ringCos2*b2.y,
  857. startPos.z + ringSin2*b1.z + ringCos2*b2.z
  858. };
  859. float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
  860. float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
  861. Vector3 w3 = {
  862. endPos.x + ringSin3*b1.x + ringCos3*b2.x,
  863. endPos.y + ringSin3*b1.y + ringCos3*b2.y,
  864. endPos.z + ringSin3*b1.z + ringCos3*b2.z
  865. };
  866. float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
  867. float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
  868. Vector3 w4 = {
  869. endPos.x + ringSin4*b1.x + ringCos4*b2.x,
  870. endPos.y + ringSin4*b1.y + ringCos4*b2.y,
  871. endPos.z + ringSin4*b1.z + ringCos4*b2.z
  872. };
  873. rlVertex3f(w1.x, w1.y, w1.z);
  874. rlVertex3f(w3.x, w3.y, w3.z);
  875. rlVertex3f(w2.x, w2.y, w2.z);
  876. rlVertex3f(w4.x, w4.y, w4.z);
  877. rlVertex3f(w2.x, w2.y, w2.z);
  878. rlVertex3f(w3.x, w3.y, w3.z);
  879. }
  880. }
  881. rlEnd();
  882. }
  883. // Draw a plane
  884. void DrawPlane(Vector3 centerPos, Vector2 size, Color color)
  885. {
  886. // NOTE: Plane is always created on XZ ground
  887. rlPushMatrix();
  888. rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
  889. rlScalef(size.x, 1.0f, size.y);
  890. rlBegin(RL_QUADS);
  891. rlColor4ub(color.r, color.g, color.b, color.a);
  892. rlNormal3f(0.0f, 1.0f, 0.0f);
  893. rlVertex3f(-0.5f, 0.0f, -0.5f);
  894. rlVertex3f(-0.5f, 0.0f, 0.5f);
  895. rlVertex3f(0.5f, 0.0f, 0.5f);
  896. rlVertex3f(0.5f, 0.0f, -0.5f);
  897. rlEnd();
  898. rlPopMatrix();
  899. }
  900. // Draw a ray line
  901. void DrawRay(Ray ray, Color color)
  902. {
  903. float scale = 10000;
  904. rlBegin(RL_LINES);
  905. rlColor4ub(color.r, color.g, color.b, color.a);
  906. rlColor4ub(color.r, color.g, color.b, color.a);
  907. rlVertex3f(ray.position.x, ray.position.y, ray.position.z);
  908. rlVertex3f(ray.position.x + ray.direction.x*scale, ray.position.y + ray.direction.y*scale, ray.position.z + ray.direction.z*scale);
  909. rlEnd();
  910. }
  911. // Draw a grid centered at (0, 0, 0)
  912. void DrawGrid(int slices, float spacing)
  913. {
  914. int halfSlices = slices/2;
  915. rlBegin(RL_LINES);
  916. for (int i = -halfSlices; i <= halfSlices; i++)
  917. {
  918. if (i == 0)
  919. {
  920. rlColor3f(0.5f, 0.5f, 0.5f);
  921. }
  922. else
  923. {
  924. rlColor3f(0.75f, 0.75f, 0.75f);
  925. }
  926. rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);
  927. rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);
  928. rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);
  929. rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);
  930. }
  931. rlEnd();
  932. }
  933. // Load model from files (mesh and material)
  934. Model LoadModel(const char *fileName)
  935. {
  936. Model model = { 0 };
  937. #if defined(SUPPORT_FILEFORMAT_OBJ)
  938. if (IsFileExtension(fileName, ".obj")) model = LoadOBJ(fileName);
  939. #endif
  940. #if defined(SUPPORT_FILEFORMAT_IQM)
  941. if (IsFileExtension(fileName, ".iqm")) model = LoadIQM(fileName);
  942. #endif
  943. #if defined(SUPPORT_FILEFORMAT_GLTF)
  944. if (IsFileExtension(fileName, ".gltf") || IsFileExtension(fileName, ".glb")) model = LoadGLTF(fileName);
  945. #endif
  946. #if defined(SUPPORT_FILEFORMAT_VOX)
  947. if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName);
  948. #endif
  949. #if defined(SUPPORT_FILEFORMAT_M3D)
  950. if (IsFileExtension(fileName, ".m3d")) model = LoadM3D(fileName);
  951. #endif
  952. // Make sure model transform is set to identity matrix!
  953. model.transform = MatrixIdentity();
  954. if ((model.meshCount != 0) && (model.meshes != NULL))
  955. {
  956. // Upload vertex data to GPU (static meshes)
  957. for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false);
  958. }
  959. else TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load model mesh(es) data", fileName);
  960. if (model.materialCount == 0)
  961. {
  962. TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to load model material data, default to white material", fileName);
  963. model.materialCount = 1;
  964. model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
  965. model.materials[0] = LoadMaterialDefault();
  966. if (model.meshMaterial == NULL) model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  967. }
  968. return model;
  969. }
  970. // Load model from generated mesh
  971. // WARNING: A shallow copy of mesh is generated, passed by value,
  972. // as long as struct contains pointers to data and some values, we get a copy
  973. // of mesh pointing to same data as original version... be careful!
  974. Model LoadModelFromMesh(Mesh mesh)
  975. {
  976. Model model = { 0 };
  977. model.transform = MatrixIdentity();
  978. model.meshCount = 1;
  979. model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  980. model.meshes[0] = mesh;
  981. model.materialCount = 1;
  982. model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
  983. model.materials[0] = LoadMaterialDefault();
  984. model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  985. model.meshMaterial[0] = 0; // First material index
  986. return model;
  987. }
  988. // Check if a model is valid (loaded in GPU, VAO/VBOs)
  989. bool IsModelValid(Model model)
  990. {
  991. bool result = false;
  992. if ((model.meshes != NULL) && // Validate model contains some mesh
  993. (model.materials != NULL) && // Validate model contains some material (at least default one)
  994. (model.meshMaterial != NULL) && // Validate mesh-material linkage
  995. (model.meshCount > 0) && // Validate mesh count
  996. (model.materialCount > 0)) result = true; // Validate material count
  997. // NOTE: Many elements could be validated from a model, including every model mesh VAO/VBOs
  998. // but some VBOs could not be used, it depends on Mesh vertex data
  999. for (int i = 0; i < model.meshCount; i++)
  1000. {
  1001. if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU
  1002. if ((model.meshes[i].texcoords != NULL) && (model.meshes[i].vboId[1] == 0)) { result = false; break; } // Vertex textcoords buffer not uploaded to GPU
  1003. if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU
  1004. if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU
  1005. if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU
  1006. if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU
  1007. if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU
  1008. if ((model.meshes[i].boneIds != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIds buffer not uploaded to GPU
  1009. if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
  1010. // NOTE: Some OpenGL versions do not support VAO, so we don't check it
  1011. //if (model.meshes[i].vaoId == 0) { result = false; break }
  1012. }
  1013. return result;
  1014. }
  1015. // Unload model (meshes/materials) from memory (RAM and/or VRAM)
  1016. // NOTE: This function takes care of all model elements, for a detailed control
  1017. // over them, use UnloadMesh() and UnloadMaterial()
  1018. void UnloadModel(Model model)
  1019. {
  1020. // Unload meshes
  1021. for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]);
  1022. // Unload materials maps
  1023. // NOTE: As the user could be sharing shaders and textures between models,
  1024. // we don't unload the material but just free its maps,
  1025. // the user is responsible for freeing models shaders and textures
  1026. for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
  1027. // Unload arrays
  1028. RL_FREE(model.meshes);
  1029. RL_FREE(model.materials);
  1030. RL_FREE(model.meshMaterial);
  1031. // Unload animation data
  1032. RL_FREE(model.bones);
  1033. RL_FREE(model.bindPose);
  1034. TRACELOG(LOG_INFO, "MODEL: Unloaded model (and meshes) from RAM and VRAM");
  1035. }
  1036. // Compute model bounding box limits (considers all meshes)
  1037. BoundingBox GetModelBoundingBox(Model model)
  1038. {
  1039. BoundingBox bounds = { 0 };
  1040. if (model.meshCount > 0)
  1041. {
  1042. Vector3 temp = { 0 };
  1043. bounds = GetMeshBoundingBox(model.meshes[0]);
  1044. for (int i = 1; i < model.meshCount; i++)
  1045. {
  1046. BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]);
  1047. temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x;
  1048. temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y;
  1049. temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z;
  1050. bounds.min = temp;
  1051. temp.x = (bounds.max.x > tempBounds.max.x)? bounds.max.x : tempBounds.max.x;
  1052. temp.y = (bounds.max.y > tempBounds.max.y)? bounds.max.y : tempBounds.max.y;
  1053. temp.z = (bounds.max.z > tempBounds.max.z)? bounds.max.z : tempBounds.max.z;
  1054. bounds.max = temp;
  1055. }
  1056. }
  1057. // Apply model.transform to bounding box
  1058. // WARNING: Current BoundingBox structure design does not support rotation transformations,
  1059. // in those cases is up to the user to calculate the proper box bounds (8 vertices transformed)
  1060. bounds.min = Vector3Transform(bounds.min, model.transform);
  1061. bounds.max = Vector3Transform(bounds.max, model.transform);
  1062. return bounds;
  1063. }
  1064. // Upload vertex data into a VAO (if supported) and VBO
  1065. void UploadMesh(Mesh *mesh, bool dynamic)
  1066. {
  1067. if (mesh->vaoId > 0)
  1068. {
  1069. // Check if mesh has already been loaded in GPU
  1070. TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId);
  1071. return;
  1072. }
  1073. mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
  1074. mesh->vaoId = 0; // Vertex Array Object
  1075. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0; // Vertex buffer: positions
  1076. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0; // Vertex buffer: texcoords
  1077. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0; // Vertex buffer: normals
  1078. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors
  1079. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents
  1080. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2
  1081. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices
  1082. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1083. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds
  1084. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights
  1085. #endif
  1086. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1087. mesh->vaoId = rlLoadVertexArray();
  1088. rlEnableVertexArray(mesh->vaoId);
  1089. // NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data
  1090. // Enable vertex attributes: position (shader-location = 0)
  1091. void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;
  1092. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);
  1093. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0);
  1094. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
  1095. // Enable vertex attributes: texcoords (shader-location = 1)
  1096. if (mesh->texcoords != NULL)
  1097. {
  1098. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);
  1099. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);
  1100. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
  1101. }
  1102. else
  1103. {
  1104. float value[2] = { 0.0f, 0.0f };
  1105. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, value, SHADER_ATTRIB_VEC2, 2);
  1106. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
  1107. }
  1108. // WARNING: When setting default vertex attribute values, the values for each generic vertex attribute
  1109. // is part of current state, and it is maintained even if a different program object is used
  1110. if (mesh->normals != NULL)
  1111. {
  1112. // Enable vertex attributes: normals (shader-location = 2)
  1113. void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;
  1114. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);
  1115. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0);
  1116. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
  1117. }
  1118. else
  1119. {
  1120. // Default vertex attribute: normal
  1121. // WARNING: Default value provided to shader if location available
  1122. float value[3] = { 0.0f, 0.0f, 1.0f };
  1123. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, value, SHADER_ATTRIB_VEC3, 3);
  1124. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
  1125. }
  1126. if (mesh->colors != NULL)
  1127. {
  1128. // Enable vertex attribute: color (shader-location = 3)
  1129. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
  1130. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0);
  1131. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);
  1132. }
  1133. else
  1134. {
  1135. // Default vertex attribute: color
  1136. // WARNING: Default value provided to shader if location available
  1137. float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // WHITE
  1138. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, value, SHADER_ATTRIB_VEC4, 4);
  1139. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);
  1140. }
  1141. if (mesh->tangents != NULL)
  1142. {
  1143. // Enable vertex attribute: tangent (shader-location = 4)
  1144. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);
  1145. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);
  1146. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);
  1147. }
  1148. else
  1149. {
  1150. // Default vertex attribute: tangent
  1151. // WARNING: Default value provided to shader if location available
  1152. float value[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
  1153. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, value, SHADER_ATTRIB_VEC4, 4);
  1154. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);
  1155. }
  1156. if (mesh->texcoords2 != NULL)
  1157. {
  1158. // Enable vertex attribute: texcoord2 (shader-location = 5)
  1159. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);
  1160. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0);
  1161. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);
  1162. }
  1163. else
  1164. {
  1165. // Default vertex attribute: texcoord2
  1166. // WARNING: Default value provided to shader if location available
  1167. float value[2] = { 0.0f, 0.0f };
  1168. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, value, SHADER_ATTRIB_VEC2, 2);
  1169. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);
  1170. }
  1171. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1172. if (mesh->boneIds != NULL)
  1173. {
  1174. // Enable vertex attribute: boneIds (shader-location = 7)
  1175. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
  1176. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0);
  1177. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
  1178. }
  1179. else
  1180. {
  1181. // Default vertex attribute: boneIds
  1182. // WARNING: Default value provided to shader if location available
  1183. float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1184. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4);
  1185. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
  1186. }
  1187. if (mesh->boneWeights != NULL)
  1188. {
  1189. // Enable vertex attribute: boneWeights (shader-location = 8)
  1190. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic);
  1191. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0);
  1192. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
  1193. }
  1194. else
  1195. {
  1196. // Default vertex attribute: boneWeights
  1197. // WARNING: Default value provided to shader if location available
  1198. float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1199. rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, value, SHADER_ATTRIB_VEC4, 2);
  1200. rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
  1201. }
  1202. #endif
  1203. if (mesh->indices != NULL)
  1204. {
  1205. mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);
  1206. }
  1207. if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);
  1208. else TRACELOG(LOG_INFO, "VBO: Mesh uploaded successfully to VRAM (GPU)");
  1209. rlDisableVertexArray();
  1210. #endif
  1211. }
  1212. // Update mesh vertex data in GPU for a specific buffer index
  1213. void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset)
  1214. {
  1215. rlUpdateVertexBuffer(mesh.vboId[index], data, dataSize, offset);
  1216. }
  1217. // Draw a 3d mesh with material and transform
  1218. void DrawMesh(Mesh mesh, Material material, Matrix transform)
  1219. {
  1220. #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
  1221. #define GL_VERTEX_ARRAY 0x8074
  1222. #define GL_NORMAL_ARRAY 0x8075
  1223. #define GL_COLOR_ARRAY 0x8076
  1224. #define GL_TEXTURE_COORD_ARRAY 0x8078
  1225. rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);
  1226. if (mesh.animVertices) rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.animVertices);
  1227. else rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);
  1228. if (mesh.texcoords) rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
  1229. if (mesh.animNormals) rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.animNormals);
  1230. else if (mesh.normals) rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
  1231. if (mesh.colors) rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
  1232. rlPushMatrix();
  1233. rlMultMatrixf(MatrixToFloat(transform));
  1234. rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r,
  1235. material.maps[MATERIAL_MAP_DIFFUSE].color.g,
  1236. material.maps[MATERIAL_MAP_DIFFUSE].color.b,
  1237. material.maps[MATERIAL_MAP_DIFFUSE].color.a);
  1238. if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices);
  1239. else rlDrawVertexArray(0, mesh.vertexCount);
  1240. rlPopMatrix();
  1241. rlDisableStatePointer(GL_VERTEX_ARRAY);
  1242. rlDisableStatePointer(GL_TEXTURE_COORD_ARRAY);
  1243. rlDisableStatePointer(GL_NORMAL_ARRAY);
  1244. rlDisableStatePointer(GL_COLOR_ARRAY);
  1245. rlDisableTexture();
  1246. #endif
  1247. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1248. // Bind shader program
  1249. rlEnableShader(material.shader.id);
  1250. // Send required data to shader (matrices, values)
  1251. //-----------------------------------------------------
  1252. // Upload to shader material.colDiffuse
  1253. if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)
  1254. {
  1255. float values[4] = {
  1256. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,
  1257. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,
  1258. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,
  1259. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f
  1260. };
  1261. rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);
  1262. }
  1263. // Upload to shader material.colSpecular (if location available)
  1264. if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)
  1265. {
  1266. float values[4] = {
  1267. (float)material.maps[MATERIAL_MAP_SPECULAR].color.r/255.0f,
  1268. (float)material.maps[MATERIAL_MAP_SPECULAR].color.g/255.0f,
  1269. (float)material.maps[MATERIAL_MAP_SPECULAR].color.b/255.0f,
  1270. (float)material.maps[MATERIAL_MAP_SPECULAR].color.a/255.0f
  1271. };
  1272. rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);
  1273. }
  1274. // Get a copy of current matrices to work with,
  1275. // just in case stereo render is required, and we need to modify them
  1276. // NOTE: At this point the modelview matrix just contains the view matrix (camera)
  1277. // That's because BeginMode3D() sets it and there is no model-drawing function
  1278. // that modifies it, all use rlPushMatrix() and rlPopMatrix()
  1279. Matrix matModel = MatrixIdentity();
  1280. Matrix matView = rlGetMatrixModelview();
  1281. Matrix matModelView = MatrixIdentity();
  1282. Matrix matProjection = rlGetMatrixProjection();
  1283. // Upload view and projection matrices (if locations available)
  1284. if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
  1285. if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
  1286. // Accumulate several model transformations:
  1287. // transform: model transformation provided (includes DrawModel() params combined with model.transform)
  1288. // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
  1289. matModel = MatrixMultiply(transform, rlGetMatrixTransform());
  1290. // Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL
  1291. if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], matModel);
  1292. // Get model-view matrix
  1293. matModelView = MatrixMultiply(matModel, matView);
  1294. // Upload model normal matrix (if locations available)
  1295. if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
  1296. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1297. // Upload Bone Transforms
  1298. if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices)
  1299. {
  1300. rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
  1301. }
  1302. #endif
  1303. //-----------------------------------------------------
  1304. // Bind active texture maps (if available)
  1305. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  1306. {
  1307. if (material.maps[i].texture.id > 0)
  1308. {
  1309. // Select current shader texture slot
  1310. rlActiveTextureSlot(i);
  1311. // Enable texture for active slot
  1312. if ((i == MATERIAL_MAP_IRRADIANCE) ||
  1313. (i == MATERIAL_MAP_PREFILTER) ||
  1314. (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);
  1315. else rlEnableTexture(material.maps[i].texture.id);
  1316. rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);
  1317. }
  1318. }
  1319. // Try binding vertex array objects (VAO) or use VBOs if not possible
  1320. // WARNING: UploadMesh() enables all vertex attributes available in mesh and sets default attribute values
  1321. // for shader expected vertex attributes that are not provided by the mesh (i.e. colors)
  1322. // This could be a dangerous approach because different meshes with different shaders can enable/disable some attributes
  1323. if (!rlEnableVertexArray(mesh.vaoId))
  1324. {
  1325. // Bind mesh VBO data: vertex position (shader-location = 0)
  1326. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);
  1327. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
  1328. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
  1329. // Bind mesh VBO data: vertex texcoords (shader-location = 1)
  1330. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);
  1331. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
  1332. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
  1333. if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
  1334. {
  1335. // Bind mesh VBO data: vertex normals (shader-location = 2)
  1336. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);
  1337. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
  1338. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);
  1339. }
  1340. // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
  1341. if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)
  1342. {
  1343. if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)
  1344. {
  1345. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);
  1346. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
  1347. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
  1348. }
  1349. else
  1350. {
  1351. // Set default value for defined vertex attribute in shader but not provided by mesh
  1352. // WARNING: It could result in GPU undefined behaviour
  1353. float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  1354. rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);
  1355. rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
  1356. }
  1357. }
  1358. // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
  1359. if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
  1360. {
  1361. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);
  1362. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
  1363. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);
  1364. }
  1365. // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
  1366. if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
  1367. {
  1368. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);
  1369. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
  1370. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
  1371. }
  1372. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1373. // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)
  1374. if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)
  1375. {
  1376. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);
  1377. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
  1378. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
  1379. }
  1380. // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
  1381. if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
  1382. {
  1383. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);
  1384. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);
  1385. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);
  1386. }
  1387. #endif
  1388. if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);
  1389. }
  1390. int eyeCount = 1;
  1391. if (rlIsStereoRenderEnabled()) eyeCount = 2;
  1392. for (int eye = 0; eye < eyeCount; eye++)
  1393. {
  1394. // Calculate model-view-projection matrix (MVP)
  1395. Matrix matModelViewProjection = MatrixIdentity();
  1396. if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
  1397. else
  1398. {
  1399. // Setup current eye viewport (half screen width)
  1400. rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());
  1401. matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));
  1402. }
  1403. // Send combined model-view-projection matrix to shader
  1404. rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);
  1405. // Draw mesh
  1406. if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0);
  1407. else rlDrawVertexArray(0, mesh.vertexCount);
  1408. }
  1409. // Unbind all bound texture maps
  1410. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  1411. {
  1412. if (material.maps[i].texture.id > 0)
  1413. {
  1414. // Select current shader texture slot
  1415. rlActiveTextureSlot(i);
  1416. // Disable texture for active slot
  1417. if ((i == MATERIAL_MAP_IRRADIANCE) ||
  1418. (i == MATERIAL_MAP_PREFILTER) ||
  1419. (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();
  1420. else rlDisableTexture();
  1421. }
  1422. }
  1423. // Disable all possible vertex array objects (or VBOs)
  1424. rlDisableVertexArray();
  1425. rlDisableVertexBuffer();
  1426. rlDisableVertexBufferElement();
  1427. // Disable shader program
  1428. rlDisableShader();
  1429. // Restore rlgl internal modelview and projection matrices
  1430. rlSetMatrixModelview(matView);
  1431. rlSetMatrixProjection(matProjection);
  1432. #endif
  1433. }
  1434. // Draw multiple mesh instances with material and different transforms
  1435. void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances)
  1436. {
  1437. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1438. // Instancing required variables
  1439. float16 *instanceTransforms = NULL;
  1440. unsigned int instancesVboId = 0;
  1441. // Bind shader program
  1442. rlEnableShader(material.shader.id);
  1443. // Send required data to shader (matrices, values)
  1444. //-----------------------------------------------------
  1445. // Upload to shader material.colDiffuse
  1446. if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)
  1447. {
  1448. float values[4] = {
  1449. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,
  1450. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,
  1451. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,
  1452. (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f
  1453. };
  1454. rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);
  1455. }
  1456. // Upload to shader material.colSpecular (if location available)
  1457. if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)
  1458. {
  1459. float values[4] = {
  1460. (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f,
  1461. (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.g/255.0f,
  1462. (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.b/255.0f,
  1463. (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f
  1464. };
  1465. rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);
  1466. }
  1467. // Get a copy of current matrices to work with,
  1468. // just in case stereo render is required, and we need to modify them
  1469. // NOTE: At this point the modelview matrix just contains the view matrix (camera)
  1470. // That's because BeginMode3D() sets it and there is no model-drawing function
  1471. // that modifies it, all use rlPushMatrix() and rlPopMatrix()
  1472. Matrix matModel = MatrixIdentity();
  1473. Matrix matView = rlGetMatrixModelview();
  1474. Matrix matModelView = MatrixIdentity();
  1475. Matrix matProjection = rlGetMatrixProjection();
  1476. // Upload view and projection matrices (if locations available)
  1477. if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
  1478. if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
  1479. // Create instances buffer
  1480. instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));
  1481. // Fill buffer with instances transformations as float16 arrays
  1482. for (int i = 0; i < instances; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);
  1483. // Enable mesh VAO to attach new buffer
  1484. rlEnableVertexArray(mesh.vaoId);
  1485. // This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()
  1486. // It isn't clear which would be reliably faster in all cases and on all platforms,
  1487. // anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
  1488. // no faster, since we're transferring all the transform matrices anyway
  1489. instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
  1490. // Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
  1491. for (unsigned int i = 0; i < 4; i++)
  1492. {
  1493. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i);
  1494. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4));
  1495. rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 1);
  1496. }
  1497. rlDisableVertexBuffer();
  1498. rlDisableVertexArray();
  1499. // Accumulate internal matrix transform (push/pop) and view matrix
  1500. // NOTE: In this case, model instance transformation must be computed in the shader
  1501. matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);
  1502. // Upload model normal matrix (if locations available)
  1503. if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
  1504. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1505. // Upload Bone Transforms
  1506. if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices)
  1507. {
  1508. rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
  1509. }
  1510. #endif
  1511. //-----------------------------------------------------
  1512. // Bind active texture maps (if available)
  1513. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  1514. {
  1515. if (material.maps[i].texture.id > 0)
  1516. {
  1517. // Select current shader texture slot
  1518. rlActiveTextureSlot(i);
  1519. // Enable texture for active slot
  1520. if ((i == MATERIAL_MAP_IRRADIANCE) ||
  1521. (i == MATERIAL_MAP_PREFILTER) ||
  1522. (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);
  1523. else rlEnableTexture(material.maps[i].texture.id);
  1524. rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);
  1525. }
  1526. }
  1527. // Try binding vertex array objects (VAO)
  1528. // or use VBOs if not possible
  1529. if (!rlEnableVertexArray(mesh.vaoId))
  1530. {
  1531. // Bind mesh VBO data: vertex position (shader-location = 0)
  1532. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);
  1533. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
  1534. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
  1535. // Bind mesh VBO data: vertex texcoords (shader-location = 1)
  1536. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);
  1537. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
  1538. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
  1539. if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
  1540. {
  1541. // Bind mesh VBO data: vertex normals (shader-location = 2)
  1542. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);
  1543. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
  1544. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);
  1545. }
  1546. // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
  1547. if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)
  1548. {
  1549. if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)
  1550. {
  1551. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);
  1552. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
  1553. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
  1554. }
  1555. else
  1556. {
  1557. // Set default value for unused attribute
  1558. // NOTE: Required when using default shader and no VAO support
  1559. float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  1560. rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);
  1561. rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
  1562. }
  1563. }
  1564. // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
  1565. if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
  1566. {
  1567. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);
  1568. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
  1569. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);
  1570. }
  1571. // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
  1572. if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
  1573. {
  1574. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);
  1575. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
  1576. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
  1577. }
  1578. #ifdef RL_SUPPORT_MESH_GPU_SKINNING
  1579. // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)
  1580. if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)
  1581. {
  1582. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);
  1583. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
  1584. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
  1585. }
  1586. // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
  1587. if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
  1588. {
  1589. rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);
  1590. rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);
  1591. rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);
  1592. }
  1593. #endif
  1594. if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);
  1595. }
  1596. int eyeCount = 1;
  1597. if (rlIsStereoRenderEnabled()) eyeCount = 2;
  1598. for (int eye = 0; eye < eyeCount; eye++)
  1599. {
  1600. // Calculate model-view-projection matrix (MVP)
  1601. Matrix matModelViewProjection = MatrixIdentity();
  1602. if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
  1603. else
  1604. {
  1605. // Setup current eye viewport (half screen width)
  1606. rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());
  1607. matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));
  1608. }
  1609. // Send combined model-view-projection matrix to shader
  1610. rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);
  1611. // Draw mesh instanced
  1612. if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);
  1613. else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);
  1614. }
  1615. // Unbind all bound texture maps
  1616. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  1617. {
  1618. if (material.maps[i].texture.id > 0)
  1619. {
  1620. // Select current shader texture slot
  1621. rlActiveTextureSlot(i);
  1622. // Disable texture for active slot
  1623. if ((i == MATERIAL_MAP_IRRADIANCE) ||
  1624. (i == MATERIAL_MAP_PREFILTER) ||
  1625. (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();
  1626. else rlDisableTexture();
  1627. }
  1628. }
  1629. // Disable all possible vertex array objects (or VBOs)
  1630. rlDisableVertexArray();
  1631. rlDisableVertexBuffer();
  1632. rlDisableVertexBufferElement();
  1633. // Disable shader program
  1634. rlDisableShader();
  1635. // Remove instance transforms buffer
  1636. rlUnloadVertexBuffer(instancesVboId);
  1637. RL_FREE(instanceTransforms);
  1638. #endif
  1639. }
  1640. // Unload mesh from memory (RAM and VRAM)
  1641. void UnloadMesh(Mesh mesh)
  1642. {
  1643. // Unload rlgl mesh vboId data
  1644. rlUnloadVertexArray(mesh.vaoId);
  1645. if (mesh.vboId != NULL) for (int i = 0; i < MAX_MESH_VERTEX_BUFFERS; i++) rlUnloadVertexBuffer(mesh.vboId[i]);
  1646. RL_FREE(mesh.vboId);
  1647. RL_FREE(mesh.vertices);
  1648. RL_FREE(mesh.texcoords);
  1649. RL_FREE(mesh.normals);
  1650. RL_FREE(mesh.colors);
  1651. RL_FREE(mesh.tangents);
  1652. RL_FREE(mesh.texcoords2);
  1653. RL_FREE(mesh.indices);
  1654. RL_FREE(mesh.animVertices);
  1655. RL_FREE(mesh.animNormals);
  1656. RL_FREE(mesh.boneWeights);
  1657. RL_FREE(mesh.boneIds);
  1658. RL_FREE(mesh.boneMatrices);
  1659. }
  1660. // Export mesh data to file
  1661. bool ExportMesh(Mesh mesh, const char *fileName)
  1662. {
  1663. bool success = false;
  1664. if (IsFileExtension(fileName, ".obj"))
  1665. {
  1666. // Estimated data size, it should be enough...
  1667. int vc = mesh.vertexCount;
  1668. int dataSize = vc*(int)strlen("v -0000.000000f -0000.000000f -0000.000000f\n") +
  1669. vc*(int)strlen("vt -0.000000f -0.000000f\n") +
  1670. vc*(int)strlen("vn -0.0000f -0.0000f -0.0000f\n") +
  1671. mesh.triangleCount*snprintf(NULL, 0, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", vc, vc, vc, vc, vc, vc, vc, vc, vc);
  1672. // NOTE: Text data buffer size is estimated considering mesh data size
  1673. char *txtData = (char *)RL_CALLOC(dataSize + 1000, sizeof(char));
  1674. int byteCount = 0;
  1675. byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n");
  1676. byteCount += sprintf(txtData + byteCount, "# // //\n");
  1677. byteCount += sprintf(txtData + byteCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");
  1678. byteCount += sprintf(txtData + byteCount, "# // //\n");
  1679. byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");
  1680. byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n");
  1681. byteCount += sprintf(txtData + byteCount, "# // //\n");
  1682. byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) //\n");
  1683. byteCount += sprintf(txtData + byteCount, "# // //\n");
  1684. byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");
  1685. byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount);
  1686. byteCount += sprintf(txtData + byteCount, "# Triangle Count: %i\n\n", mesh.triangleCount);
  1687. byteCount += sprintf(txtData + byteCount, "g mesh\n");
  1688. for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
  1689. {
  1690. byteCount += sprintf(txtData + byteCount, "v %.6f %.6f %.6f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
  1691. }
  1692. for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
  1693. {
  1694. byteCount += sprintf(txtData + byteCount, "vt %.6f %.6f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
  1695. }
  1696. for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
  1697. {
  1698. byteCount += sprintf(txtData + byteCount, "vn %.4f %.4f %.4f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
  1699. }
  1700. if (mesh.indices != NULL)
  1701. {
  1702. for (int i = 0, v = 0; i < mesh.triangleCount; i++, v += 3)
  1703. {
  1704. byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n",
  1705. mesh.indices[v] + 1, mesh.indices[v] + 1, mesh.indices[v] + 1,
  1706. mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1,
  1707. mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1);
  1708. }
  1709. }
  1710. else
  1711. {
  1712. for (int i = 0, v = 1; i < mesh.triangleCount; i++, v += 3)
  1713. {
  1714. byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", v, v, v, v + 1, v + 1, v + 1, v + 2, v + 2, v + 2);
  1715. }
  1716. }
  1717. // NOTE: Text data length exported is determined by '\0' (NULL) character
  1718. success = SaveFileText(fileName, txtData);
  1719. RL_FREE(txtData);
  1720. }
  1721. else if (IsFileExtension(fileName, ".raw"))
  1722. {
  1723. // TODO: Support additional file formats to export mesh vertex data
  1724. }
  1725. return success;
  1726. }
  1727. // Export mesh as code file (.h) defining multiple arrays of vertex attributes
  1728. bool ExportMeshAsCode(Mesh mesh, const char *fileName)
  1729. {
  1730. bool success = false;
  1731. #ifndef TEXT_BYTES_PER_LINE
  1732. #define TEXT_BYTES_PER_LINE 20
  1733. #endif
  1734. // NOTE: Text data buffer size is fixed to 64MB
  1735. char *txtData = (char *)RL_CALLOC(64*1024*1024, sizeof(char)); // 64 MB
  1736. int byteCount = 0;
  1737. byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
  1738. byteCount += sprintf(txtData + byteCount, "// //\n");
  1739. byteCount += sprintf(txtData + byteCount, "// MeshAsCode exporter v1.0 - Mesh vertex data exported as arrays //\n");
  1740. byteCount += sprintf(txtData + byteCount, "// //\n");
  1741. byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
  1742. byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
  1743. byteCount += sprintf(txtData + byteCount, "// //\n");
  1744. byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2023 Ramon Santamaria (@raysan5) //\n");
  1745. byteCount += sprintf(txtData + byteCount, "// //\n");
  1746. byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
  1747. // Get file name from path and convert variable name to uppercase
  1748. char varFileName[256] = { 0 };
  1749. strcpy(varFileName, GetFileNameWithoutExt(fileName));
  1750. for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
  1751. // Add image information
  1752. byteCount += sprintf(txtData + byteCount, "// Mesh basic information\n");
  1753. byteCount += sprintf(txtData + byteCount, "#define %s_VERTEX_COUNT %i\n", varFileName, mesh.vertexCount);
  1754. byteCount += sprintf(txtData + byteCount, "#define %s_TRIANGLE_COUNT %i\n\n", varFileName, mesh.triangleCount);
  1755. // Define vertex attributes data as separate arrays
  1756. //-----------------------------------------------------------------------------------------
  1757. if (mesh.vertices != NULL) // Vertex position (XYZ - 3 components per vertex - float)
  1758. {
  1759. byteCount += sprintf(txtData + byteCount, "static float %s_VERTEX_DATA[%i] = { ", varFileName, mesh.vertexCount*3);
  1760. for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.vertices[i]);
  1761. byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.vertices[mesh.vertexCount*3 - 1]);
  1762. }
  1763. if (mesh.texcoords != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)
  1764. {
  1765. byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD_DATA[%i] = { ", varFileName, mesh.vertexCount*2);
  1766. for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords[i]);
  1767. byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords[mesh.vertexCount*2 - 1]);
  1768. }
  1769. if (mesh.texcoords2 != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)
  1770. {
  1771. byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD2_DATA[%i] = { ", varFileName, mesh.vertexCount*2);
  1772. for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords2[i]);
  1773. byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords2[mesh.vertexCount*2 - 1]);
  1774. }
  1775. if (mesh.normals != NULL) // Vertex normals (XYZ - 3 components per vertex - float)
  1776. {
  1777. byteCount += sprintf(txtData + byteCount, "static float %s_NORMAL_DATA[%i] = { ", varFileName, mesh.vertexCount*3);
  1778. for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.normals[i]);
  1779. byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.normals[mesh.vertexCount*3 - 1]);
  1780. }
  1781. if (mesh.tangents != NULL) // Vertex tangents (XYZW - 4 components per vertex - float)
  1782. {
  1783. byteCount += sprintf(txtData + byteCount, "static float %s_TANGENT_DATA[%i] = { ", varFileName, mesh.vertexCount*4);
  1784. for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.tangents[i]);
  1785. byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.tangents[mesh.vertexCount*4 - 1]);
  1786. }
  1787. if (mesh.colors != NULL) // Vertex colors (RGBA - 4 components per vertex - unsigned char)
  1788. {
  1789. byteCount += sprintf(txtData + byteCount, "static unsigned char %s_COLOR_DATA[%i] = { ", varFileName, mesh.vertexCount*4);
  1790. for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), mesh.colors[i]);
  1791. byteCount += sprintf(txtData + byteCount, "0x%x };\n\n", mesh.colors[mesh.vertexCount*4 - 1]);
  1792. }
  1793. if (mesh.indices != NULL) // Vertex indices (3 index per triangle - unsigned short)
  1794. {
  1795. byteCount += sprintf(txtData + byteCount, "static unsigned short %s_INDEX_DATA[%i] = { ", varFileName, mesh.triangleCount*3);
  1796. for (int i = 0; i < mesh.triangleCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%i,\n" : "%i, "), mesh.indices[i]);
  1797. byteCount += sprintf(txtData + byteCount, "%i };\n", mesh.indices[mesh.triangleCount*3 - 1]);
  1798. }
  1799. //-----------------------------------------------------------------------------------------
  1800. // NOTE: Text data size exported is determined by '\0' (NULL) character
  1801. success = SaveFileText(fileName, txtData);
  1802. RL_FREE(txtData);
  1803. //if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
  1804. //else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
  1805. return success;
  1806. }
  1807. #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
  1808. // Process obj materials
  1809. static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
  1810. {
  1811. // Init model mats
  1812. for (int m = 0; m < materialCount; m++)
  1813. {
  1814. // Init material to default
  1815. // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
  1816. materials[m] = LoadMaterialDefault();
  1817. if (mats == NULL) continue;
  1818. // Get default texture, in case no texture is defined
  1819. // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
  1820. materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
  1821. if (mats[m].diffuse_texname != NULL) materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(mats[m].diffuse_texname); //char *diffuse_texname; // map_Kd
  1822. else materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(mats[m].diffuse[0]*255.0f), (unsigned char)(mats[m].diffuse[1]*255.0f), (unsigned char)(mats[m].diffuse[2]*255.0f), 255 }; //float diffuse[3];
  1823. materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
  1824. if (mats[m].specular_texname != NULL) materials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(mats[m].specular_texname); //char *specular_texname; // map_Ks
  1825. materials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(mats[m].specular[0]*255.0f), (unsigned char)(mats[m].specular[1]*255.0f), (unsigned char)(mats[m].specular[2]*255.0f), 255 }; //float specular[3];
  1826. materials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;
  1827. if (mats[m].bump_texname != NULL) materials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(mats[m].bump_texname); //char *bump_texname; // map_bump, bump
  1828. materials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;
  1829. materials[m].maps[MATERIAL_MAP_NORMAL].value = mats[m].shininess;
  1830. materials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(mats[m].emission[0]*255.0f), (unsigned char)(mats[m].emission[1]*255.0f), (unsigned char)(mats[m].emission[2]*255.0f), 255 }; //float emission[3];
  1831. if (mats[m].displacement_texname != NULL) materials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(mats[m].displacement_texname); //char *displacement_texname; // disp
  1832. }
  1833. }
  1834. #endif
  1835. // Load materials from model file
  1836. Material *LoadMaterials(const char *fileName, int *materialCount)
  1837. {
  1838. Material *materials = NULL;
  1839. unsigned int count = 0;
  1840. // TODO: Support IQM and GLTF for materials parsing
  1841. #if defined(SUPPORT_FILEFORMAT_MTL)
  1842. if (IsFileExtension(fileName, ".mtl"))
  1843. {
  1844. tinyobj_material_t *mats = NULL;
  1845. int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
  1846. if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
  1847. materials = (Material *)RL_MALLOC(count*sizeof(Material));
  1848. ProcessMaterialsOBJ(materials, mats, count);
  1849. tinyobj_materials_free(mats, count);
  1850. }
  1851. #else
  1852. TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to load material file", fileName);
  1853. #endif
  1854. *materialCount = count;
  1855. return materials;
  1856. }
  1857. // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
  1858. Material LoadMaterialDefault(void)
  1859. {
  1860. Material material = { 0 };
  1861. material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS, sizeof(MaterialMap));
  1862. // Using rlgl default shader
  1863. material.shader.id = rlGetShaderIdDefault();
  1864. material.shader.locs = rlGetShaderLocsDefault();
  1865. // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)
  1866. material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
  1867. //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set
  1868. //material.maps[MATERIAL_MAP_SPECULAR].texture; // NOTE: By default, not set
  1869. material.maps[MATERIAL_MAP_DIFFUSE].color = WHITE; // Diffuse color
  1870. material.maps[MATERIAL_MAP_SPECULAR].color = WHITE; // Specular color
  1871. return material;
  1872. }
  1873. // Check if a material is valid (map textures loaded in GPU)
  1874. bool IsMaterialValid(Material material)
  1875. {
  1876. bool result = false;
  1877. if ((material.maps != NULL) && // Validate material contain some map
  1878. (material.shader.id > 0)) result = true; // Validate material shader is valid
  1879. // TODO: Check if available maps contain loaded textures
  1880. return result;
  1881. }
  1882. // Unload material from memory
  1883. void UnloadMaterial(Material material)
  1884. {
  1885. // Unload material shader (avoid unloading default shader, managed by raylib)
  1886. if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);
  1887. // Unload loaded texture maps (avoid unloading default texture, managed by raylib)
  1888. if (material.maps != NULL)
  1889. {
  1890. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  1891. {
  1892. if (material.maps[i].texture.id != rlGetTextureIdDefault()) rlUnloadTexture(material.maps[i].texture.id);
  1893. }
  1894. }
  1895. RL_FREE(material.maps);
  1896. }
  1897. // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
  1898. // NOTE: Previous texture should be manually unloaded
  1899. void SetMaterialTexture(Material *material, int mapType, Texture2D texture)
  1900. {
  1901. material->maps[mapType].texture = texture;
  1902. }
  1903. // Set the material for a mesh
  1904. void SetModelMeshMaterial(Model *model, int meshId, int materialId)
  1905. {
  1906. if (meshId >= model->meshCount) TRACELOG(LOG_WARNING, "MESH: Id greater than mesh count");
  1907. else if (materialId >= model->materialCount) TRACELOG(LOG_WARNING, "MATERIAL: Id greater than material count");
  1908. else model->meshMaterial[meshId] = materialId;
  1909. }
  1910. // Load model animations from file
  1911. ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
  1912. {
  1913. ModelAnimation *animations = NULL;
  1914. #if defined(SUPPORT_FILEFORMAT_IQM)
  1915. if (IsFileExtension(fileName, ".iqm")) animations = LoadModelAnimationsIQM(fileName, animCount);
  1916. #endif
  1917. #if defined(SUPPORT_FILEFORMAT_M3D)
  1918. if (IsFileExtension(fileName, ".m3d")) animations = LoadModelAnimationsM3D(fileName, animCount);
  1919. #endif
  1920. #if defined(SUPPORT_FILEFORMAT_GLTF)
  1921. if (IsFileExtension(fileName, ".gltf;.glb")) animations = LoadModelAnimationsGLTF(fileName, animCount);
  1922. #endif
  1923. return animations;
  1924. }
  1925. // Update model animated bones transform matrices for a given frame
  1926. // NOTE: Updated data is not uploaded to GPU but kept at model.meshes[i].boneMatrices[boneId],
  1927. // to be uploaded to shader at drawing, in case GPU skinning is enabled
  1928. void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
  1929. {
  1930. if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
  1931. {
  1932. if (frame >= anim.frameCount) frame = frame%anim.frameCount;
  1933. // Get first mesh which have bones
  1934. int firstMeshWithBones = -1;
  1935. for (int i = 0; i < model.meshCount; i++)
  1936. {
  1937. if (model.meshes[i].boneMatrices)
  1938. {
  1939. if (firstMeshWithBones == -1)
  1940. {
  1941. firstMeshWithBones = i;
  1942. break;
  1943. }
  1944. }
  1945. }
  1946. if (firstMeshWithBones != -1)
  1947. {
  1948. // Update all bones and boneMatrices of first mesh with bones
  1949. for (int boneId = 0; boneId < anim.boneCount; boneId++)
  1950. {
  1951. Transform *bindTransform = &model.bindPose[boneId];
  1952. Matrix bindMatrix = MatrixMultiply(MatrixMultiply(
  1953. MatrixScale(bindTransform->scale.x, bindTransform->scale.y, bindTransform->scale.z),
  1954. QuaternionToMatrix(bindTransform->rotation)),
  1955. MatrixTranslate(bindTransform->translation.x, bindTransform->translation.y, bindTransform->translation.z));
  1956. Transform *targetTransform = &anim.framePoses[frame][boneId];
  1957. Matrix targetMatrix = MatrixMultiply(MatrixMultiply(
  1958. MatrixScale(targetTransform->scale.x, targetTransform->scale.y, targetTransform->scale.z),
  1959. QuaternionToMatrix(targetTransform->rotation)),
  1960. MatrixTranslate(targetTransform->translation.x, targetTransform->translation.y, targetTransform->translation.z));
  1961. model.meshes[firstMeshWithBones].boneMatrices[boneId] = MatrixMultiply(MatrixInvert(bindMatrix), targetMatrix);
  1962. }
  1963. // Update remaining meshes with bones
  1964. // NOTE: Using deep copy because shallow copy results in double free with 'UnloadModel()'
  1965. for (int i = firstMeshWithBones + 1; i < model.meshCount; i++)
  1966. {
  1967. if (model.meshes[i].boneMatrices)
  1968. {
  1969. memcpy(model.meshes[i].boneMatrices,
  1970. model.meshes[firstMeshWithBones].boneMatrices,
  1971. model.meshes[i].boneCount*sizeof(model.meshes[i].boneMatrices[0]));
  1972. }
  1973. }
  1974. }
  1975. }
  1976. }
  1977. // at least 2x speed up vs the old method
  1978. // Update model animated vertex data (positions and normals) for a given frame
  1979. // NOTE: Updated data is uploaded to GPU
  1980. void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
  1981. {
  1982. UpdateModelAnimationBones(model,anim,frame);
  1983. for (int m = 0; m < model.meshCount; m++)
  1984. {
  1985. Mesh mesh = model.meshes[m];
  1986. Vector3 animVertex = { 0 };
  1987. Vector3 animNormal = { 0 };
  1988. int boneId = 0;
  1989. int boneCounter = 0;
  1990. float boneWeight = 0.0;
  1991. bool updated = false; // Flag to check when anim vertex information is updated
  1992. const int vValues = mesh.vertexCount*3;
  1993. // Skip if missing bone data, causes segfault without on some models
  1994. if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue;
  1995. for (int vCounter = 0; vCounter < vValues; vCounter += 3)
  1996. {
  1997. mesh.animVertices[vCounter] = 0;
  1998. mesh.animVertices[vCounter + 1] = 0;
  1999. mesh.animVertices[vCounter + 2] = 0;
  2000. if (mesh.animNormals != NULL)
  2001. {
  2002. mesh.animNormals[vCounter] = 0;
  2003. mesh.animNormals[vCounter + 1] = 0;
  2004. mesh.animNormals[vCounter + 2] = 0;
  2005. }
  2006. // Iterates over 4 bones per vertex
  2007. for (int j = 0; j < 4; j++, boneCounter++)
  2008. {
  2009. boneWeight = mesh.boneWeights[boneCounter];
  2010. boneId = mesh.boneIds[boneCounter];
  2011. // Early stop when no transformation will be applied
  2012. if (boneWeight == 0.0f) continue;
  2013. animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
  2014. animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]);
  2015. mesh.animVertices[vCounter] += animVertex.x*boneWeight;
  2016. mesh.animVertices[vCounter+1] += animVertex.y*boneWeight;
  2017. mesh.animVertices[vCounter+2] += animVertex.z*boneWeight;
  2018. updated = true;
  2019. // Normals processing
  2020. // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
  2021. if ((mesh.normals != NULL) && (mesh.animNormals != NULL ))
  2022. {
  2023. animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
  2024. animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model.meshes[m].boneMatrices[boneId])));
  2025. mesh.animNormals[vCounter] += animNormal.x*boneWeight;
  2026. mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
  2027. mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
  2028. }
  2029. }
  2030. }
  2031. if (updated)
  2032. {
  2033. rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position
  2034. if (mesh.normals != NULL) rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
  2035. }
  2036. }
  2037. }
  2038. // Unload animation array data
  2039. void UnloadModelAnimations(ModelAnimation *animations, int animCount)
  2040. {
  2041. for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);
  2042. RL_FREE(animations);
  2043. }
  2044. // Unload animation data
  2045. void UnloadModelAnimation(ModelAnimation anim)
  2046. {
  2047. for (int i = 0; i < anim.frameCount; i++) RL_FREE(anim.framePoses[i]);
  2048. RL_FREE(anim.bones);
  2049. RL_FREE(anim.framePoses);
  2050. }
  2051. // Check model animation skeleton match
  2052. // NOTE: Only number of bones and parent connections are checked
  2053. bool IsModelAnimationValid(Model model, ModelAnimation anim)
  2054. {
  2055. int result = true;
  2056. if (model.boneCount != anim.boneCount) result = false;
  2057. else
  2058. {
  2059. for (int i = 0; i < model.boneCount; i++)
  2060. {
  2061. if (model.bones[i].parent != anim.bones[i].parent) { result = false; break; }
  2062. }
  2063. }
  2064. return result;
  2065. }
  2066. #if defined(SUPPORT_MESH_GENERATION)
  2067. // Generate polygonal mesh
  2068. Mesh GenMeshPoly(int sides, float radius)
  2069. {
  2070. Mesh mesh = { 0 };
  2071. if (sides < 3) return mesh; // Security check
  2072. int vertexCount = sides*3;
  2073. // Vertices definition
  2074. Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
  2075. float d = 0.0f, dStep = 360.0f/sides;
  2076. for (int v = 0; v < vertexCount - 2; v += 3)
  2077. {
  2078. vertices[v] = (Vector3){ 0.0f, 0.0f, 0.0f };
  2079. vertices[v + 1] = (Vector3){ sinf(DEG2RAD*d)*radius, 0.0f, cosf(DEG2RAD*d)*radius };
  2080. vertices[v + 2] = (Vector3){ sinf(DEG2RAD*(d+dStep))*radius, 0.0f, cosf(DEG2RAD*(d+dStep))*radius };
  2081. d += dStep;
  2082. }
  2083. // Normals definition
  2084. Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
  2085. for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;
  2086. // TexCoords definition
  2087. Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));
  2088. for (int n = 0; n < vertexCount; n++) texcoords[n] = (Vector2){ 0.0f, 0.0f };
  2089. mesh.vertexCount = vertexCount;
  2090. mesh.triangleCount = sides;
  2091. mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2092. mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
  2093. mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2094. // Mesh vertices position array
  2095. for (int i = 0; i < mesh.vertexCount; i++)
  2096. {
  2097. mesh.vertices[3*i] = vertices[i].x;
  2098. mesh.vertices[3*i + 1] = vertices[i].y;
  2099. mesh.vertices[3*i + 2] = vertices[i].z;
  2100. }
  2101. // Mesh texcoords array
  2102. for (int i = 0; i < mesh.vertexCount; i++)
  2103. {
  2104. mesh.texcoords[2*i] = texcoords[i].x;
  2105. mesh.texcoords[2*i + 1] = texcoords[i].y;
  2106. }
  2107. // Mesh normals array
  2108. for (int i = 0; i < mesh.vertexCount; i++)
  2109. {
  2110. mesh.normals[3*i] = normals[i].x;
  2111. mesh.normals[3*i + 1] = normals[i].y;
  2112. mesh.normals[3*i + 2] = normals[i].z;
  2113. }
  2114. RL_FREE(vertices);
  2115. RL_FREE(normals);
  2116. RL_FREE(texcoords);
  2117. // Upload vertex data to GPU (static mesh)
  2118. // NOTE: mesh.vboId array is allocated inside UploadMesh()
  2119. UploadMesh(&mesh, false);
  2120. return mesh;
  2121. }
  2122. // Generate plane mesh (with subdivisions)
  2123. Mesh GenMeshPlane(float width, float length, int resX, int resZ)
  2124. {
  2125. Mesh mesh = { 0 };
  2126. #define CUSTOM_MESH_GEN_PLANE
  2127. #if defined(CUSTOM_MESH_GEN_PLANE)
  2128. resX++;
  2129. resZ++;
  2130. // Vertices definition
  2131. int vertexCount = resX*resZ; // vertices get reused for the faces
  2132. Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
  2133. for (int z = 0; z < resZ; z++)
  2134. {
  2135. // [-length/2, length/2]
  2136. float zPos = ((float)z/(resZ - 1) - 0.5f)*length;
  2137. for (int x = 0; x < resX; x++)
  2138. {
  2139. // [-width/2, width/2]
  2140. float xPos = ((float)x/(resX - 1) - 0.5f)*width;
  2141. vertices[x + z*resX] = (Vector3){ xPos, 0.0f, zPos };
  2142. }
  2143. }
  2144. // Normals definition
  2145. Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
  2146. for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;
  2147. // TexCoords definition
  2148. Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));
  2149. for (int v = 0; v < resZ; v++)
  2150. {
  2151. for (int u = 0; u < resX; u++)
  2152. {
  2153. texcoords[u + v*resX] = (Vector2){ (float)u/(resX - 1), (float)v/(resZ - 1) };
  2154. }
  2155. }
  2156. // Triangles definition (indices)
  2157. int numFaces = (resX - 1)*(resZ - 1);
  2158. int *triangles = (int *)RL_MALLOC(numFaces*6*sizeof(int));
  2159. int t = 0;
  2160. for (int face = 0; face < numFaces; face++)
  2161. {
  2162. // Retrieve lower left corner from face ind
  2163. int i = face + face/(resX - 1);
  2164. triangles[t++] = i + resX;
  2165. triangles[t++] = i + 1;
  2166. triangles[t++] = i;
  2167. triangles[t++] = i + resX;
  2168. triangles[t++] = i + resX + 1;
  2169. triangles[t++] = i + 1;
  2170. }
  2171. mesh.vertexCount = vertexCount;
  2172. mesh.triangleCount = numFaces*2;
  2173. mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2174. mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
  2175. mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2176. mesh.indices = (unsigned short *)RL_MALLOC(mesh.triangleCount*3*sizeof(unsigned short));
  2177. // Mesh vertices position array
  2178. for (int i = 0; i < mesh.vertexCount; i++)
  2179. {
  2180. mesh.vertices[3*i] = vertices[i].x;
  2181. mesh.vertices[3*i + 1] = vertices[i].y;
  2182. mesh.vertices[3*i + 2] = vertices[i].z;
  2183. }
  2184. // Mesh texcoords array
  2185. for (int i = 0; i < mesh.vertexCount; i++)
  2186. {
  2187. mesh.texcoords[2*i] = texcoords[i].x;
  2188. mesh.texcoords[2*i + 1] = texcoords[i].y;
  2189. }
  2190. // Mesh normals array
  2191. for (int i = 0; i < mesh.vertexCount; i++)
  2192. {
  2193. mesh.normals[3*i] = normals[i].x;
  2194. mesh.normals[3*i + 1] = normals[i].y;
  2195. mesh.normals[3*i + 2] = normals[i].z;
  2196. }
  2197. // Mesh indices array initialization
  2198. for (int i = 0; i < mesh.triangleCount*3; i++) mesh.indices[i] = triangles[i];
  2199. RL_FREE(vertices);
  2200. RL_FREE(normals);
  2201. RL_FREE(texcoords);
  2202. RL_FREE(triangles);
  2203. #else // Use par_shapes library to generate plane mesh
  2204. par_shapes_mesh *plane = par_shapes_create_plane(resX, resZ); // No normals/texcoords generated!!!
  2205. par_shapes_scale(plane, width, length, 1.0f);
  2206. par_shapes_rotate(plane, -PI/2.0f, (float[]){ 1, 0, 0 });
  2207. par_shapes_translate(plane, -width/2, 0.0f, length/2);
  2208. mesh.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));
  2209. mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*sizeof(float));
  2210. mesh.normals = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));
  2211. mesh.vertexCount = plane->ntriangles*3;
  2212. mesh.triangleCount = plane->ntriangles;
  2213. for (int k = 0; k < mesh.vertexCount; k++)
  2214. {
  2215. mesh.vertices[k*3] = plane->points[plane->triangles[k]*3];
  2216. mesh.vertices[k*3 + 1] = plane->points[plane->triangles[k]*3 + 1];
  2217. mesh.vertices[k*3 + 2] = plane->points[plane->triangles[k]*3 + 2];
  2218. mesh.normals[k*3] = plane->normals[plane->triangles[k]*3];
  2219. mesh.normals[k*3 + 1] = plane->normals[plane->triangles[k]*3 + 1];
  2220. mesh.normals[k*3 + 2] = plane->normals[plane->triangles[k]*3 + 2];
  2221. mesh.texcoords[k*2] = plane->tcoords[plane->triangles[k]*2];
  2222. mesh.texcoords[k*2 + 1] = plane->tcoords[plane->triangles[k]*2 + 1];
  2223. }
  2224. par_shapes_free_mesh(plane);
  2225. #endif
  2226. // Upload vertex data to GPU (static mesh)
  2227. UploadMesh(&mesh, false);
  2228. return mesh;
  2229. }
  2230. // Generated cuboid mesh
  2231. Mesh GenMeshCube(float width, float height, float length)
  2232. {
  2233. Mesh mesh = { 0 };
  2234. #define CUSTOM_MESH_GEN_CUBE
  2235. #if defined(CUSTOM_MESH_GEN_CUBE)
  2236. float vertices[] = {
  2237. -width/2, -height/2, length/2,
  2238. width/2, -height/2, length/2,
  2239. width/2, height/2, length/2,
  2240. -width/2, height/2, length/2,
  2241. -width/2, -height/2, -length/2,
  2242. -width/2, height/2, -length/2,
  2243. width/2, height/2, -length/2,
  2244. width/2, -height/2, -length/2,
  2245. -width/2, height/2, -length/2,
  2246. -width/2, height/2, length/2,
  2247. width/2, height/2, length/2,
  2248. width/2, height/2, -length/2,
  2249. -width/2, -height/2, -length/2,
  2250. width/2, -height/2, -length/2,
  2251. width/2, -height/2, length/2,
  2252. -width/2, -height/2, length/2,
  2253. width/2, -height/2, -length/2,
  2254. width/2, height/2, -length/2,
  2255. width/2, height/2, length/2,
  2256. width/2, -height/2, length/2,
  2257. -width/2, -height/2, -length/2,
  2258. -width/2, -height/2, length/2,
  2259. -width/2, height/2, length/2,
  2260. -width/2, height/2, -length/2
  2261. };
  2262. float texcoords[] = {
  2263. 0.0f, 0.0f,
  2264. 1.0f, 0.0f,
  2265. 1.0f, 1.0f,
  2266. 0.0f, 1.0f,
  2267. 1.0f, 0.0f,
  2268. 1.0f, 1.0f,
  2269. 0.0f, 1.0f,
  2270. 0.0f, 0.0f,
  2271. 0.0f, 1.0f,
  2272. 0.0f, 0.0f,
  2273. 1.0f, 0.0f,
  2274. 1.0f, 1.0f,
  2275. 1.0f, 1.0f,
  2276. 0.0f, 1.0f,
  2277. 0.0f, 0.0f,
  2278. 1.0f, 0.0f,
  2279. 1.0f, 0.0f,
  2280. 1.0f, 1.0f,
  2281. 0.0f, 1.0f,
  2282. 0.0f, 0.0f,
  2283. 0.0f, 0.0f,
  2284. 1.0f, 0.0f,
  2285. 1.0f, 1.0f,
  2286. 0.0f, 1.0f
  2287. };
  2288. float normals[] = {
  2289. 0.0f, 0.0f, 1.0f,
  2290. 0.0f, 0.0f, 1.0f,
  2291. 0.0f, 0.0f, 1.0f,
  2292. 0.0f, 0.0f, 1.0f,
  2293. 0.0f, 0.0f,-1.0f,
  2294. 0.0f, 0.0f,-1.0f,
  2295. 0.0f, 0.0f,-1.0f,
  2296. 0.0f, 0.0f,-1.0f,
  2297. 0.0f, 1.0f, 0.0f,
  2298. 0.0f, 1.0f, 0.0f,
  2299. 0.0f, 1.0f, 0.0f,
  2300. 0.0f, 1.0f, 0.0f,
  2301. 0.0f,-1.0f, 0.0f,
  2302. 0.0f,-1.0f, 0.0f,
  2303. 0.0f,-1.0f, 0.0f,
  2304. 0.0f,-1.0f, 0.0f,
  2305. 1.0f, 0.0f, 0.0f,
  2306. 1.0f, 0.0f, 0.0f,
  2307. 1.0f, 0.0f, 0.0f,
  2308. 1.0f, 0.0f, 0.0f,
  2309. -1.0f, 0.0f, 0.0f,
  2310. -1.0f, 0.0f, 0.0f,
  2311. -1.0f, 0.0f, 0.0f,
  2312. -1.0f, 0.0f, 0.0f
  2313. };
  2314. mesh.vertices = (float *)RL_MALLOC(24*3*sizeof(float));
  2315. memcpy(mesh.vertices, vertices, 24*3*sizeof(float));
  2316. mesh.texcoords = (float *)RL_MALLOC(24*2*sizeof(float));
  2317. memcpy(mesh.texcoords, texcoords, 24*2*sizeof(float));
  2318. mesh.normals = (float *)RL_MALLOC(24*3*sizeof(float));
  2319. memcpy(mesh.normals, normals, 24*3*sizeof(float));
  2320. mesh.indices = (unsigned short *)RL_MALLOC(36*sizeof(unsigned short));
  2321. int k = 0;
  2322. // Indices can be initialized right now
  2323. for (int i = 0; i < 36; i += 6)
  2324. {
  2325. mesh.indices[i] = 4*k;
  2326. mesh.indices[i + 1] = 4*k + 1;
  2327. mesh.indices[i + 2] = 4*k + 2;
  2328. mesh.indices[i + 3] = 4*k;
  2329. mesh.indices[i + 4] = 4*k + 2;
  2330. mesh.indices[i + 5] = 4*k + 3;
  2331. k++;
  2332. }
  2333. mesh.vertexCount = 24;
  2334. mesh.triangleCount = 12;
  2335. #else // Use par_shapes library to generate cube mesh
  2336. /*
  2337. // Platonic solids:
  2338. par_shapes_mesh *par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
  2339. par_shapes_mesh *par_shapes_create_cube(); // 6 sides polyhedron (cube)
  2340. par_shapes_mesh *par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
  2341. par_shapes_mesh *par_shapes_create_dodecahedron(); // 12 sides polyhedron
  2342. par_shapes_mesh *par_shapes_create_icosahedron(); // 20 sides polyhedron
  2343. */
  2344. // Platonic solid generation: cube (6 sides)
  2345. // NOTE: No normals/texcoords generated by default
  2346. par_shapes_mesh *cube = par_shapes_create_cube();
  2347. cube->tcoords = PAR_MALLOC(float, 2*cube->npoints);
  2348. for (int i = 0; i < 2*cube->npoints; i++) cube->tcoords[i] = 0.0f;
  2349. par_shapes_scale(cube, width, height, length);
  2350. par_shapes_translate(cube, -width/2, 0.0f, -length/2);
  2351. par_shapes_compute_normals(cube);
  2352. mesh.vertices = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));
  2353. mesh.texcoords = (float *)RL_MALLOC(cube->ntriangles*3*2*sizeof(float));
  2354. mesh.normals = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));
  2355. mesh.vertexCount = cube->ntriangles*3;
  2356. mesh.triangleCount = cube->ntriangles;
  2357. for (int k = 0; k < mesh.vertexCount; k++)
  2358. {
  2359. mesh.vertices[k*3] = cube->points[cube->triangles[k]*3];
  2360. mesh.vertices[k*3 + 1] = cube->points[cube->triangles[k]*3 + 1];
  2361. mesh.vertices[k*3 + 2] = cube->points[cube->triangles[k]*3 + 2];
  2362. mesh.normals[k*3] = cube->normals[cube->triangles[k]*3];
  2363. mesh.normals[k*3 + 1] = cube->normals[cube->triangles[k]*3 + 1];
  2364. mesh.normals[k*3 + 2] = cube->normals[cube->triangles[k]*3 + 2];
  2365. mesh.texcoords[k*2] = cube->tcoords[cube->triangles[k]*2];
  2366. mesh.texcoords[k*2 + 1] = cube->tcoords[cube->triangles[k]*2 + 1];
  2367. }
  2368. par_shapes_free_mesh(cube);
  2369. #endif
  2370. // Upload vertex data to GPU (static mesh)
  2371. UploadMesh(&mesh, false);
  2372. return mesh;
  2373. }
  2374. // Generate sphere mesh (standard sphere)
  2375. Mesh GenMeshSphere(float radius, int rings, int slices)
  2376. {
  2377. Mesh mesh = { 0 };
  2378. if ((rings >= 3) && (slices >= 3))
  2379. {
  2380. par_shapes_set_epsilon_degenerate_sphere(0.0);
  2381. par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);
  2382. par_shapes_scale(sphere, radius, radius, radius);
  2383. // NOTE: Soft normals are computed internally
  2384. mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));
  2385. mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));
  2386. mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));
  2387. mesh.vertexCount = sphere->ntriangles*3;
  2388. mesh.triangleCount = sphere->ntriangles;
  2389. for (int k = 0; k < mesh.vertexCount; k++)
  2390. {
  2391. mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];
  2392. mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];
  2393. mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];
  2394. mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];
  2395. mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];
  2396. mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];
  2397. mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];
  2398. mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];
  2399. }
  2400. par_shapes_free_mesh(sphere);
  2401. // Upload vertex data to GPU (static mesh)
  2402. UploadMesh(&mesh, false);
  2403. }
  2404. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: sphere");
  2405. return mesh;
  2406. }
  2407. // Generate hemisphere mesh (half sphere, no bottom cap)
  2408. Mesh GenMeshHemiSphere(float radius, int rings, int slices)
  2409. {
  2410. Mesh mesh = { 0 };
  2411. if ((rings >= 3) && (slices >= 3))
  2412. {
  2413. if (radius < 0.0f) radius = 0.0f;
  2414. par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings);
  2415. par_shapes_scale(sphere, radius, radius, radius);
  2416. // NOTE: Soft normals are computed internally
  2417. mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));
  2418. mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));
  2419. mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));
  2420. mesh.vertexCount = sphere->ntriangles*3;
  2421. mesh.triangleCount = sphere->ntriangles;
  2422. for (int k = 0; k < mesh.vertexCount; k++)
  2423. {
  2424. mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];
  2425. mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];
  2426. mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];
  2427. mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];
  2428. mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];
  2429. mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];
  2430. mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];
  2431. mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];
  2432. }
  2433. par_shapes_free_mesh(sphere);
  2434. // Upload vertex data to GPU (static mesh)
  2435. UploadMesh(&mesh, false);
  2436. }
  2437. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: hemisphere");
  2438. return mesh;
  2439. }
  2440. // Generate cylinder mesh
  2441. Mesh GenMeshCylinder(float radius, float height, int slices)
  2442. {
  2443. Mesh mesh = { 0 };
  2444. if (slices >= 3)
  2445. {
  2446. // Instance a cylinder that sits on the Z=0 plane using the given tessellation
  2447. // levels across the UV domain. Think of "slices" like a number of pizza
  2448. // slices, and "stacks" like a number of stacked rings
  2449. // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale
  2450. par_shapes_mesh *cylinder = par_shapes_create_cylinder(slices, 8);
  2451. par_shapes_scale(cylinder, radius, radius, height);
  2452. par_shapes_rotate(cylinder, -PI/2.0f, (float[]){ 1, 0, 0 });
  2453. // Generate an orientable disk shape (top cap)
  2454. par_shapes_mesh *capTop = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, 1 });
  2455. capTop->tcoords = PAR_MALLOC(float, 2*capTop->npoints);
  2456. for (int i = 0; i < 2*capTop->npoints; i++) capTop->tcoords[i] = 0.0f;
  2457. par_shapes_rotate(capTop, -PI/2.0f, (float[]){ 1, 0, 0 });
  2458. par_shapes_rotate(capTop, 90*DEG2RAD, (float[]){ 0, 1, 0 });
  2459. par_shapes_translate(capTop, 0, height, 0);
  2460. // Generate an orientable disk shape (bottom cap)
  2461. par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });
  2462. capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);
  2463. for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;
  2464. par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });
  2465. par_shapes_rotate(capBottom, -90*DEG2RAD, (float[]){ 0, 1, 0 });
  2466. par_shapes_merge_and_free(cylinder, capTop);
  2467. par_shapes_merge_and_free(cylinder, capBottom);
  2468. mesh.vertices = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));
  2469. mesh.texcoords = (float *)RL_MALLOC(cylinder->ntriangles*3*2*sizeof(float));
  2470. mesh.normals = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));
  2471. mesh.vertexCount = cylinder->ntriangles*3;
  2472. mesh.triangleCount = cylinder->ntriangles;
  2473. for (int k = 0; k < mesh.vertexCount; k++)
  2474. {
  2475. mesh.vertices[k*3] = cylinder->points[cylinder->triangles[k]*3];
  2476. mesh.vertices[k*3 + 1] = cylinder->points[cylinder->triangles[k]*3 + 1];
  2477. mesh.vertices[k*3 + 2] = cylinder->points[cylinder->triangles[k]*3 + 2];
  2478. mesh.normals[k*3] = cylinder->normals[cylinder->triangles[k]*3];
  2479. mesh.normals[k*3 + 1] = cylinder->normals[cylinder->triangles[k]*3 + 1];
  2480. mesh.normals[k*3 + 2] = cylinder->normals[cylinder->triangles[k]*3 + 2];
  2481. mesh.texcoords[k*2] = cylinder->tcoords[cylinder->triangles[k]*2];
  2482. mesh.texcoords[k*2 + 1] = cylinder->tcoords[cylinder->triangles[k]*2 + 1];
  2483. }
  2484. par_shapes_free_mesh(cylinder);
  2485. // Upload vertex data to GPU (static mesh)
  2486. UploadMesh(&mesh, false);
  2487. }
  2488. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cylinder");
  2489. return mesh;
  2490. }
  2491. // Generate cone/pyramid mesh
  2492. Mesh GenMeshCone(float radius, float height, int slices)
  2493. {
  2494. Mesh mesh = { 0 };
  2495. if (slices >= 3)
  2496. {
  2497. // Instance a cone that sits on the Z=0 plane using the given tessellation
  2498. // levels across the UV domain. Think of "slices" like a number of pizza
  2499. // slices, and "stacks" like a number of stacked rings
  2500. // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale
  2501. par_shapes_mesh *cone = par_shapes_create_cone(slices, 8);
  2502. par_shapes_scale(cone, radius, radius, height);
  2503. par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 });
  2504. par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 });
  2505. // Generate an orientable disk shape (bottom cap)
  2506. par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });
  2507. capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);
  2508. for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;
  2509. par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });
  2510. par_shapes_merge_and_free(cone, capBottom);
  2511. mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));
  2512. mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float));
  2513. mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));
  2514. mesh.vertexCount = cone->ntriangles*3;
  2515. mesh.triangleCount = cone->ntriangles;
  2516. for (int k = 0; k < mesh.vertexCount; k++)
  2517. {
  2518. mesh.vertices[k*3] = cone->points[cone->triangles[k]*3];
  2519. mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1];
  2520. mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2];
  2521. mesh.normals[k*3] = cone->normals[cone->triangles[k]*3];
  2522. mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1];
  2523. mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2];
  2524. mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2];
  2525. mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1];
  2526. }
  2527. par_shapes_free_mesh(cone);
  2528. // Upload vertex data to GPU (static mesh)
  2529. UploadMesh(&mesh, false);
  2530. }
  2531. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone");
  2532. return mesh;
  2533. }
  2534. // Generate torus mesh
  2535. Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
  2536. {
  2537. Mesh mesh = { 0 };
  2538. if ((sides >= 3) && (radSeg >= 3))
  2539. {
  2540. if (radius > 1.0f) radius = 1.0f;
  2541. else if (radius < 0.1f) radius = 0.1f;
  2542. // Create a donut that sits on the Z=0 plane with the specified inner radius
  2543. // The outer radius can be controlled with par_shapes_scale
  2544. par_shapes_mesh *torus = par_shapes_create_torus(radSeg, sides, radius);
  2545. par_shapes_scale(torus, size/2, size/2, size/2);
  2546. mesh.vertices = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));
  2547. mesh.texcoords = (float *)RL_MALLOC(torus->ntriangles*3*2*sizeof(float));
  2548. mesh.normals = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));
  2549. mesh.vertexCount = torus->ntriangles*3;
  2550. mesh.triangleCount = torus->ntriangles;
  2551. for (int k = 0; k < mesh.vertexCount; k++)
  2552. {
  2553. mesh.vertices[k*3] = torus->points[torus->triangles[k]*3];
  2554. mesh.vertices[k*3 + 1] = torus->points[torus->triangles[k]*3 + 1];
  2555. mesh.vertices[k*3 + 2] = torus->points[torus->triangles[k]*3 + 2];
  2556. mesh.normals[k*3] = torus->normals[torus->triangles[k]*3];
  2557. mesh.normals[k*3 + 1] = torus->normals[torus->triangles[k]*3 + 1];
  2558. mesh.normals[k*3 + 2] = torus->normals[torus->triangles[k]*3 + 2];
  2559. mesh.texcoords[k*2] = torus->tcoords[torus->triangles[k]*2];
  2560. mesh.texcoords[k*2 + 1] = torus->tcoords[torus->triangles[k]*2 + 1];
  2561. }
  2562. par_shapes_free_mesh(torus);
  2563. // Upload vertex data to GPU (static mesh)
  2564. UploadMesh(&mesh, false);
  2565. }
  2566. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: torus");
  2567. return mesh;
  2568. }
  2569. // Generate trefoil knot mesh
  2570. Mesh GenMeshKnot(float radius, float size, int radSeg, int sides)
  2571. {
  2572. Mesh mesh = { 0 };
  2573. if ((sides >= 3) && (radSeg >= 3))
  2574. {
  2575. if (radius > 3.0f) radius = 3.0f;
  2576. else if (radius < 0.5f) radius = 0.5f;
  2577. par_shapes_mesh *knot = par_shapes_create_trefoil_knot(radSeg, sides, radius);
  2578. par_shapes_scale(knot, size, size, size);
  2579. mesh.vertices = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));
  2580. mesh.texcoords = (float *)RL_MALLOC(knot->ntriangles*3*2*sizeof(float));
  2581. mesh.normals = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));
  2582. mesh.vertexCount = knot->ntriangles*3;
  2583. mesh.triangleCount = knot->ntriangles;
  2584. for (int k = 0; k < mesh.vertexCount; k++)
  2585. {
  2586. mesh.vertices[k*3] = knot->points[knot->triangles[k]*3];
  2587. mesh.vertices[k*3 + 1] = knot->points[knot->triangles[k]*3 + 1];
  2588. mesh.vertices[k*3 + 2] = knot->points[knot->triangles[k]*3 + 2];
  2589. mesh.normals[k*3] = knot->normals[knot->triangles[k]*3];
  2590. mesh.normals[k*3 + 1] = knot->normals[knot->triangles[k]*3 + 1];
  2591. mesh.normals[k*3 + 2] = knot->normals[knot->triangles[k]*3 + 2];
  2592. mesh.texcoords[k*2] = knot->tcoords[knot->triangles[k]*2];
  2593. mesh.texcoords[k*2 + 1] = knot->tcoords[knot->triangles[k]*2 + 1];
  2594. }
  2595. par_shapes_free_mesh(knot);
  2596. // Upload vertex data to GPU (static mesh)
  2597. UploadMesh(&mesh, false);
  2598. }
  2599. else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: knot");
  2600. return mesh;
  2601. }
  2602. // Generate a mesh from heightmap
  2603. // NOTE: Vertex data is uploaded to GPU
  2604. Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
  2605. {
  2606. #define GRAY_VALUE(c) ((float)(c.r + c.g + c.b)/3.0f)
  2607. Mesh mesh = { 0 };
  2608. int mapX = heightmap.width;
  2609. int mapZ = heightmap.height;
  2610. Color *pixels = LoadImageColors(heightmap);
  2611. // NOTE: One vertex per pixel
  2612. mesh.triangleCount = (mapX - 1)*(mapZ - 1)*2; // One quad every four pixels
  2613. mesh.vertexCount = mesh.triangleCount*3;
  2614. mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2615. mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2616. mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
  2617. mesh.colors = NULL;
  2618. int vCounter = 0; // Used to count vertices float by float
  2619. int tcCounter = 0; // Used to count texcoords float by float
  2620. int nCounter = 0; // Used to count normals float by float
  2621. Vector3 scaleFactor = { size.x/(mapX - 1), size.y/255.0f, size.z/(mapZ - 1) };
  2622. Vector3 vA = { 0 };
  2623. Vector3 vB = { 0 };
  2624. Vector3 vC = { 0 };
  2625. Vector3 vN = { 0 };
  2626. for (int z = 0; z < mapZ-1; z++)
  2627. {
  2628. for (int x = 0; x < mapX-1; x++)
  2629. {
  2630. // Fill vertices array with data
  2631. //----------------------------------------------------------
  2632. // one triangle - 3 vertex
  2633. mesh.vertices[vCounter] = (float)x*scaleFactor.x;
  2634. mesh.vertices[vCounter + 1] = GRAY_VALUE(pixels[x + z*mapX])*scaleFactor.y;
  2635. mesh.vertices[vCounter + 2] = (float)z*scaleFactor.z;
  2636. mesh.vertices[vCounter + 3] = (float)x*scaleFactor.x;
  2637. mesh.vertices[vCounter + 4] = GRAY_VALUE(pixels[x + (z + 1)*mapX])*scaleFactor.y;
  2638. mesh.vertices[vCounter + 5] = (float)(z + 1)*scaleFactor.z;
  2639. mesh.vertices[vCounter + 6] = (float)(x + 1)*scaleFactor.x;
  2640. mesh.vertices[vCounter + 7] = GRAY_VALUE(pixels[(x + 1) + z*mapX])*scaleFactor.y;
  2641. mesh.vertices[vCounter + 8] = (float)z*scaleFactor.z;
  2642. // Another triangle - 3 vertex
  2643. mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6];
  2644. mesh.vertices[vCounter + 10] = mesh.vertices[vCounter + 7];
  2645. mesh.vertices[vCounter + 11] = mesh.vertices[vCounter + 8];
  2646. mesh.vertices[vCounter + 12] = mesh.vertices[vCounter + 3];
  2647. mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4];
  2648. mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5];
  2649. mesh.vertices[vCounter + 15] = (float)(x + 1)*scaleFactor.x;
  2650. mesh.vertices[vCounter + 16] = GRAY_VALUE(pixels[(x + 1) + (z + 1)*mapX])*scaleFactor.y;
  2651. mesh.vertices[vCounter + 17] = (float)(z + 1)*scaleFactor.z;
  2652. vCounter += 18; // 6 vertex, 18 floats
  2653. // Fill texcoords array with data
  2654. //--------------------------------------------------------------
  2655. mesh.texcoords[tcCounter] = (float)x/(mapX - 1);
  2656. mesh.texcoords[tcCounter + 1] = (float)z/(mapZ - 1);
  2657. mesh.texcoords[tcCounter + 2] = (float)x/(mapX - 1);
  2658. mesh.texcoords[tcCounter + 3] = (float)(z + 1)/(mapZ - 1);
  2659. mesh.texcoords[tcCounter + 4] = (float)(x + 1)/(mapX - 1);
  2660. mesh.texcoords[tcCounter + 5] = (float)z/(mapZ - 1);
  2661. mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4];
  2662. mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5];
  2663. mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2];
  2664. mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3];
  2665. mesh.texcoords[tcCounter + 10] = (float)(x + 1)/(mapX - 1);
  2666. mesh.texcoords[tcCounter + 11] = (float)(z + 1)/(mapZ - 1);
  2667. tcCounter += 12; // 6 texcoords, 12 floats
  2668. // Fill normals array with data
  2669. //--------------------------------------------------------------
  2670. for (int i = 0; i < 18; i += 9)
  2671. {
  2672. vA.x = mesh.vertices[nCounter + i];
  2673. vA.y = mesh.vertices[nCounter + i + 1];
  2674. vA.z = mesh.vertices[nCounter + i + 2];
  2675. vB.x = mesh.vertices[nCounter + i + 3];
  2676. vB.y = mesh.vertices[nCounter + i + 4];
  2677. vB.z = mesh.vertices[nCounter + i + 5];
  2678. vC.x = mesh.vertices[nCounter + i + 6];
  2679. vC.y = mesh.vertices[nCounter + i + 7];
  2680. vC.z = mesh.vertices[nCounter + i + 8];
  2681. vN = Vector3Normalize(Vector3CrossProduct(Vector3Subtract(vB, vA), Vector3Subtract(vC, vA)));
  2682. mesh.normals[nCounter + i] = vN.x;
  2683. mesh.normals[nCounter + i + 1] = vN.y;
  2684. mesh.normals[nCounter + i + 2] = vN.z;
  2685. mesh.normals[nCounter + i + 3] = vN.x;
  2686. mesh.normals[nCounter + i + 4] = vN.y;
  2687. mesh.normals[nCounter + i + 5] = vN.z;
  2688. mesh.normals[nCounter + i + 6] = vN.x;
  2689. mesh.normals[nCounter + i + 7] = vN.y;
  2690. mesh.normals[nCounter + i + 8] = vN.z;
  2691. }
  2692. nCounter += 18; // 6 vertex, 18 floats
  2693. }
  2694. }
  2695. UnloadImageColors(pixels); // Unload pixels color data
  2696. // Upload vertex data to GPU (static mesh)
  2697. UploadMesh(&mesh, false);
  2698. return mesh;
  2699. }
  2700. // Generate a cubes mesh from pixel data
  2701. // NOTE: Vertex data is uploaded to GPU
  2702. Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
  2703. {
  2704. #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
  2705. Mesh mesh = { 0 };
  2706. Color *pixels = LoadImageColors(cubicmap);
  2707. // NOTE: Max possible number of triangles numCubes*(12 triangles by cube)
  2708. int maxTriangles = cubicmap.width*cubicmap.height*12;
  2709. int vCounter = 0; // Used to count vertices
  2710. int tcCounter = 0; // Used to count texcoords
  2711. int nCounter = 0; // Used to count normals
  2712. float w = cubeSize.x;
  2713. float h = cubeSize.z;
  2714. float h2 = cubeSize.y;
  2715. Vector3 *mapVertices = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));
  2716. Vector2 *mapTexcoords = (Vector2 *)RL_MALLOC(maxTriangles*3*sizeof(Vector2));
  2717. Vector3 *mapNormals = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));
  2718. // Define the 6 normals of the cube, we will combine them accordingly later...
  2719. Vector3 n1 = { 1.0f, 0.0f, 0.0f };
  2720. Vector3 n2 = { -1.0f, 0.0f, 0.0f };
  2721. Vector3 n3 = { 0.0f, 1.0f, 0.0f };
  2722. Vector3 n4 = { 0.0f, -1.0f, 0.0f };
  2723. Vector3 n5 = { 0.0f, 0.0f, -1.0f };
  2724. Vector3 n6 = { 0.0f, 0.0f, 1.0f };
  2725. // NOTE: We use texture rectangles to define different textures for top-bottom-front-back-right-left (6)
  2726. typedef struct RectangleF {
  2727. float x;
  2728. float y;
  2729. float width;
  2730. float height;
  2731. } RectangleF;
  2732. RectangleF rightTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };
  2733. RectangleF leftTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };
  2734. RectangleF frontTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };
  2735. RectangleF backTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };
  2736. RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };
  2737. RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };
  2738. for (int z = 0; z < cubicmap.height; ++z)
  2739. {
  2740. for (int x = 0; x < cubicmap.width; ++x)
  2741. {
  2742. // Define the 8 vertex of the cube, we will combine them accordingly later...
  2743. Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };
  2744. Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) };
  2745. Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) };
  2746. Vector3 v4 = { w*(x + 0.5f), h2, h*(z - 0.5f) };
  2747. Vector3 v5 = { w*(x + 0.5f), 0, h*(z - 0.5f) };
  2748. Vector3 v6 = { w*(x - 0.5f), 0, h*(z - 0.5f) };
  2749. Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) };
  2750. Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) };
  2751. // We check pixel color to be WHITE -> draw full cube
  2752. if (COLOR_EQUAL(pixels[z*cubicmap.width + x], WHITE))
  2753. {
  2754. // Define triangles and checking collateral cubes
  2755. //------------------------------------------------
  2756. // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)
  2757. // WARNING: Not required for a WHITE cubes, created to allow seeing the map from outside
  2758. mapVertices[vCounter] = v1;
  2759. mapVertices[vCounter + 1] = v2;
  2760. mapVertices[vCounter + 2] = v3;
  2761. mapVertices[vCounter + 3] = v1;
  2762. mapVertices[vCounter + 4] = v3;
  2763. mapVertices[vCounter + 5] = v4;
  2764. vCounter += 6;
  2765. mapNormals[nCounter] = n3;
  2766. mapNormals[nCounter + 1] = n3;
  2767. mapNormals[nCounter + 2] = n3;
  2768. mapNormals[nCounter + 3] = n3;
  2769. mapNormals[nCounter + 4] = n3;
  2770. mapNormals[nCounter + 5] = n3;
  2771. nCounter += 6;
  2772. mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };
  2773. mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };
  2774. mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };
  2775. mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };
  2776. mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };
  2777. mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };
  2778. tcCounter += 6;
  2779. // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)
  2780. mapVertices[vCounter] = v6;
  2781. mapVertices[vCounter + 1] = v8;
  2782. mapVertices[vCounter + 2] = v7;
  2783. mapVertices[vCounter + 3] = v6;
  2784. mapVertices[vCounter + 4] = v5;
  2785. mapVertices[vCounter + 5] = v8;
  2786. vCounter += 6;
  2787. mapNormals[nCounter] = n4;
  2788. mapNormals[nCounter + 1] = n4;
  2789. mapNormals[nCounter + 2] = n4;
  2790. mapNormals[nCounter + 3] = n4;
  2791. mapNormals[nCounter + 4] = n4;
  2792. mapNormals[nCounter + 5] = n4;
  2793. nCounter += 6;
  2794. mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };
  2795. mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };
  2796. mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };
  2797. mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };
  2798. mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y };
  2799. mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };
  2800. tcCounter += 6;
  2801. // Checking cube on bottom of current cube
  2802. if (((z < cubicmap.height - 1) && COLOR_EQUAL(pixels[(z + 1)*cubicmap.width + x], BLACK)) || (z == cubicmap.height - 1))
  2803. {
  2804. // Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8
  2805. // NOTE: Collateral occluded faces are not generated
  2806. mapVertices[vCounter] = v2;
  2807. mapVertices[vCounter + 1] = v7;
  2808. mapVertices[vCounter + 2] = v3;
  2809. mapVertices[vCounter + 3] = v3;
  2810. mapVertices[vCounter + 4] = v7;
  2811. mapVertices[vCounter + 5] = v8;
  2812. vCounter += 6;
  2813. mapNormals[nCounter] = n6;
  2814. mapNormals[nCounter + 1] = n6;
  2815. mapNormals[nCounter + 2] = n6;
  2816. mapNormals[nCounter + 3] = n6;
  2817. mapNormals[nCounter + 4] = n6;
  2818. mapNormals[nCounter + 5] = n6;
  2819. nCounter += 6;
  2820. mapTexcoords[tcCounter] = (Vector2){ frontTexUV.x, frontTexUV.y };
  2821. mapTexcoords[tcCounter + 1] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };
  2822. mapTexcoords[tcCounter + 2] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };
  2823. mapTexcoords[tcCounter + 3] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };
  2824. mapTexcoords[tcCounter + 4] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };
  2825. mapTexcoords[tcCounter + 5] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y + frontTexUV.height };
  2826. tcCounter += 6;
  2827. }
  2828. // Checking cube on top of current cube
  2829. if (((z > 0) && COLOR_EQUAL(pixels[(z - 1)*cubicmap.width + x], BLACK)) || (z == 0))
  2830. {
  2831. // Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5
  2832. // NOTE: Collateral occluded faces are not generated
  2833. mapVertices[vCounter] = v1;
  2834. mapVertices[vCounter + 1] = v5;
  2835. mapVertices[vCounter + 2] = v6;
  2836. mapVertices[vCounter + 3] = v1;
  2837. mapVertices[vCounter + 4] = v4;
  2838. mapVertices[vCounter + 5] = v5;
  2839. vCounter += 6;
  2840. mapNormals[nCounter] = n5;
  2841. mapNormals[nCounter + 1] = n5;
  2842. mapNormals[nCounter + 2] = n5;
  2843. mapNormals[nCounter + 3] = n5;
  2844. mapNormals[nCounter + 4] = n5;
  2845. mapNormals[nCounter + 5] = n5;
  2846. nCounter += 6;
  2847. mapTexcoords[tcCounter] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };
  2848. mapTexcoords[tcCounter + 1] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };
  2849. mapTexcoords[tcCounter + 2] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y + backTexUV.height };
  2850. mapTexcoords[tcCounter + 3] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };
  2851. mapTexcoords[tcCounter + 4] = (Vector2){ backTexUV.x, backTexUV.y };
  2852. mapTexcoords[tcCounter + 5] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };
  2853. tcCounter += 6;
  2854. }
  2855. // Checking cube on right of current cube
  2856. if (((x < cubicmap.width - 1) && COLOR_EQUAL(pixels[z*cubicmap.width + (x + 1)], BLACK)) || (x == cubicmap.width - 1))
  2857. {
  2858. // Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5
  2859. // NOTE: Collateral occluded faces are not generated
  2860. mapVertices[vCounter] = v3;
  2861. mapVertices[vCounter + 1] = v8;
  2862. mapVertices[vCounter + 2] = v4;
  2863. mapVertices[vCounter + 3] = v4;
  2864. mapVertices[vCounter + 4] = v8;
  2865. mapVertices[vCounter + 5] = v5;
  2866. vCounter += 6;
  2867. mapNormals[nCounter] = n1;
  2868. mapNormals[nCounter + 1] = n1;
  2869. mapNormals[nCounter + 2] = n1;
  2870. mapNormals[nCounter + 3] = n1;
  2871. mapNormals[nCounter + 4] = n1;
  2872. mapNormals[nCounter + 5] = n1;
  2873. nCounter += 6;
  2874. mapTexcoords[tcCounter] = (Vector2){ rightTexUV.x, rightTexUV.y };
  2875. mapTexcoords[tcCounter + 1] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };
  2876. mapTexcoords[tcCounter + 2] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };
  2877. mapTexcoords[tcCounter + 3] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };
  2878. mapTexcoords[tcCounter + 4] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };
  2879. mapTexcoords[tcCounter + 5] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y + rightTexUV.height };
  2880. tcCounter += 6;
  2881. }
  2882. // Checking cube on left of current cube
  2883. if (((x > 0) && COLOR_EQUAL(pixels[z*cubicmap.width + (x - 1)], BLACK)) || (x == 0))
  2884. {
  2885. // Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7
  2886. // NOTE: Collateral occluded faces are not generated
  2887. mapVertices[vCounter] = v1;
  2888. mapVertices[vCounter + 1] = v7;
  2889. mapVertices[vCounter + 2] = v2;
  2890. mapVertices[vCounter + 3] = v1;
  2891. mapVertices[vCounter + 4] = v6;
  2892. mapVertices[vCounter + 5] = v7;
  2893. vCounter += 6;
  2894. mapNormals[nCounter] = n2;
  2895. mapNormals[nCounter + 1] = n2;
  2896. mapNormals[nCounter + 2] = n2;
  2897. mapNormals[nCounter + 3] = n2;
  2898. mapNormals[nCounter + 4] = n2;
  2899. mapNormals[nCounter + 5] = n2;
  2900. nCounter += 6;
  2901. mapTexcoords[tcCounter] = (Vector2){ leftTexUV.x, leftTexUV.y };
  2902. mapTexcoords[tcCounter + 1] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };
  2903. mapTexcoords[tcCounter + 2] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y };
  2904. mapTexcoords[tcCounter + 3] = (Vector2){ leftTexUV.x, leftTexUV.y };
  2905. mapTexcoords[tcCounter + 4] = (Vector2){ leftTexUV.x, leftTexUV.y + leftTexUV.height };
  2906. mapTexcoords[tcCounter + 5] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };
  2907. tcCounter += 6;
  2908. }
  2909. }
  2910. // We check pixel color to be BLACK, we will only draw floor and roof
  2911. else if (COLOR_EQUAL(pixels[z*cubicmap.width + x], BLACK))
  2912. {
  2913. // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)
  2914. mapVertices[vCounter] = v1;
  2915. mapVertices[vCounter + 1] = v3;
  2916. mapVertices[vCounter + 2] = v2;
  2917. mapVertices[vCounter + 3] = v1;
  2918. mapVertices[vCounter + 4] = v4;
  2919. mapVertices[vCounter + 5] = v3;
  2920. vCounter += 6;
  2921. mapNormals[nCounter] = n4;
  2922. mapNormals[nCounter + 1] = n4;
  2923. mapNormals[nCounter + 2] = n4;
  2924. mapNormals[nCounter + 3] = n4;
  2925. mapNormals[nCounter + 4] = n4;
  2926. mapNormals[nCounter + 5] = n4;
  2927. nCounter += 6;
  2928. mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };
  2929. mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };
  2930. mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };
  2931. mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };
  2932. mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };
  2933. mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };
  2934. tcCounter += 6;
  2935. // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)
  2936. mapVertices[vCounter] = v6;
  2937. mapVertices[vCounter + 1] = v7;
  2938. mapVertices[vCounter + 2] = v8;
  2939. mapVertices[vCounter + 3] = v6;
  2940. mapVertices[vCounter + 4] = v8;
  2941. mapVertices[vCounter + 5] = v5;
  2942. vCounter += 6;
  2943. mapNormals[nCounter] = n3;
  2944. mapNormals[nCounter + 1] = n3;
  2945. mapNormals[nCounter + 2] = n3;
  2946. mapNormals[nCounter + 3] = n3;
  2947. mapNormals[nCounter + 4] = n3;
  2948. mapNormals[nCounter + 5] = n3;
  2949. nCounter += 6;
  2950. mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };
  2951. mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };
  2952. mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };
  2953. mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };
  2954. mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };
  2955. mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y };
  2956. tcCounter += 6;
  2957. }
  2958. }
  2959. }
  2960. // Move data from mapVertices temp arrays to vertices float array
  2961. mesh.vertexCount = vCounter;
  2962. mesh.triangleCount = vCounter/3;
  2963. mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2964. mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
  2965. mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
  2966. mesh.colors = NULL;
  2967. int fCounter = 0;
  2968. // Move vertices data
  2969. for (int i = 0; i < vCounter; i++)
  2970. {
  2971. mesh.vertices[fCounter] = mapVertices[i].x;
  2972. mesh.vertices[fCounter + 1] = mapVertices[i].y;
  2973. mesh.vertices[fCounter + 2] = mapVertices[i].z;
  2974. fCounter += 3;
  2975. }
  2976. fCounter = 0;
  2977. // Move normals data
  2978. for (int i = 0; i < nCounter; i++)
  2979. {
  2980. mesh.normals[fCounter] = mapNormals[i].x;
  2981. mesh.normals[fCounter + 1] = mapNormals[i].y;
  2982. mesh.normals[fCounter + 2] = mapNormals[i].z;
  2983. fCounter += 3;
  2984. }
  2985. fCounter = 0;
  2986. // Move texcoords data
  2987. for (int i = 0; i < tcCounter; i++)
  2988. {
  2989. mesh.texcoords[fCounter] = mapTexcoords[i].x;
  2990. mesh.texcoords[fCounter + 1] = mapTexcoords[i].y;
  2991. fCounter += 2;
  2992. }
  2993. RL_FREE(mapVertices);
  2994. RL_FREE(mapNormals);
  2995. RL_FREE(mapTexcoords);
  2996. UnloadImageColors(pixels); // Unload pixels color data
  2997. // Upload vertex data to GPU (static mesh)
  2998. UploadMesh(&mesh, false);
  2999. return mesh;
  3000. }
  3001. #endif // SUPPORT_MESH_GENERATION
  3002. // Compute mesh bounding box limits
  3003. // NOTE: minVertex and maxVertex should be transformed by model transform matrix
  3004. BoundingBox GetMeshBoundingBox(Mesh mesh)
  3005. {
  3006. // Get min and max vertex to construct bounds (AABB)
  3007. Vector3 minVertex = { 0 };
  3008. Vector3 maxVertex = { 0 };
  3009. if (mesh.vertices != NULL)
  3010. {
  3011. minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };
  3012. maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };
  3013. for (int i = 1; i < mesh.vertexCount; i++)
  3014. {
  3015. minVertex = Vector3Min(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });
  3016. maxVertex = Vector3Max(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });
  3017. }
  3018. }
  3019. // Create the bounding box
  3020. BoundingBox box = { 0 };
  3021. box.min = minVertex;
  3022. box.max = maxVertex;
  3023. return box;
  3024. }
  3025. // Compute mesh tangents
  3026. void GenMeshTangents(Mesh *mesh)
  3027. {
  3028. // Check if input mesh data is useful
  3029. if ((mesh == NULL) || (mesh->vertices == NULL) || (mesh->texcoords == NULL) || (mesh->normals == NULL))
  3030. {
  3031. TRACELOG(LOG_WARNING, "MESH: Tangents generation requires vertices, texcoords and normals vertex attribute data");
  3032. return;
  3033. }
  3034. // Allocate or reallocate tangents data
  3035. if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
  3036. else
  3037. {
  3038. RL_FREE(mesh->tangents);
  3039. mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
  3040. }
  3041. // Allocate temporary arrays for tangents calculation
  3042. Vector3 *tan1 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
  3043. Vector3 *tan2 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
  3044. if (tan1 == NULL || tan2 == NULL)
  3045. {
  3046. TRACELOG(LOG_WARNING, "MESH: Failed to allocate temporary memory for tangent calculation");
  3047. if (tan1) RL_FREE(tan1);
  3048. if (tan2) RL_FREE(tan2);
  3049. return;
  3050. }
  3051. // Process all triangles of the mesh
  3052. // 'triangleCount' must be always valid
  3053. for (int t = 0; t < mesh->triangleCount; t++)
  3054. {
  3055. // Get triangle vertex indices
  3056. int i0, i1, i2;
  3057. if (mesh->indices != NULL)
  3058. {
  3059. // Use indices if available
  3060. i0 = mesh->indices[t*3 + 0];
  3061. i1 = mesh->indices[t*3 + 1];
  3062. i2 = mesh->indices[t*3 + 2];
  3063. }
  3064. else
  3065. {
  3066. // Sequential access for non-indexed mesh
  3067. i0 = t*3 + 0;
  3068. i1 = t*3 + 1;
  3069. i2 = t*3 + 2;
  3070. }
  3071. // Get triangle vertices position
  3072. Vector3 v1 = { mesh->vertices[i0*3 + 0], mesh->vertices[i0*3 + 1], mesh->vertices[i0*3 + 2] };
  3073. Vector3 v2 = { mesh->vertices[i1*3 + 0], mesh->vertices[i1*3 + 1], mesh->vertices[i1*3 + 2] };
  3074. Vector3 v3 = { mesh->vertices[i2*3 + 0], mesh->vertices[i2*3 + 1], mesh->vertices[i2*3 + 2] };
  3075. // Get triangle texcoords
  3076. Vector2 uv1 = { mesh->texcoords[i0*2 + 0], mesh->texcoords[i0*2 + 1] };
  3077. Vector2 uv2 = { mesh->texcoords[i1*2 + 0], mesh->texcoords[i1*2 + 1] };
  3078. Vector2 uv3 = { mesh->texcoords[i2*2 + 0], mesh->texcoords[i2*2 + 1] };
  3079. // Calculate triangle edges
  3080. float x1 = v2.x - v1.x;
  3081. float y1 = v2.y - v1.y;
  3082. float z1 = v2.z - v1.z;
  3083. float x2 = v3.x - v1.x;
  3084. float y2 = v3.y - v1.y;
  3085. float z2 = v3.z - v1.z;
  3086. // Calculate texture coordinate differences
  3087. float s1 = uv2.x - uv1.x;
  3088. float t1 = uv2.y - uv1.y;
  3089. float s2 = uv3.x - uv1.x;
  3090. float t2 = uv3.y - uv1.y;
  3091. // Calculate denominator and check for degenerate UV
  3092. float div = s1*t2 - s2*t1;
  3093. float r = (fabsf(div) < 0.0001f)? 0.0f : 1.0f/div;
  3094. // Calculate tangent and bitangent directions
  3095. Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };
  3096. Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };
  3097. // Accumulate tangents and bitangents for each vertex of the triangle
  3098. tan1[i0] = Vector3Add(tan1[i0], sdir);
  3099. tan1[i1] = Vector3Add(tan1[i1], sdir);
  3100. tan1[i2] = Vector3Add(tan1[i2], sdir);
  3101. tan2[i0] = Vector3Add(tan2[i0], tdir);
  3102. tan2[i1] = Vector3Add(tan2[i1], tdir);
  3103. tan2[i2] = Vector3Add(tan2[i2], tdir);
  3104. }
  3105. // Calculate final tangents for each vertex
  3106. for (int i = 0; i < mesh->vertexCount; i++)
  3107. {
  3108. Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };
  3109. Vector3 tangent = tan1[i];
  3110. // Handle zero tangent (can happen with degenerate UVs)
  3111. if (Vector3Length(tangent) < 0.0001f)
  3112. {
  3113. // Create a tangent perpendicular to the normal
  3114. if (fabsf(normal.z) > 0.707f) tangent = (Vector3){ 1.0f, 0.0f, 0.0f };
  3115. else tangent = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
  3116. mesh->tangents[i*4 + 0] = tangent.x;
  3117. mesh->tangents[i*4 + 1] = tangent.y;
  3118. mesh->tangents[i*4 + 2] = tangent.z;
  3119. mesh->tangents[i*4 + 3] = 1.0f;
  3120. continue;
  3121. }
  3122. // Gram-Schmidt orthogonalization to make tangent orthogonal to normal
  3123. // T_prime = T - N*dot(N, T)
  3124. Vector3 orthogonalized = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
  3125. // Handle cases where orthogonalized vector is too small
  3126. if (Vector3Length(orthogonalized) < 0.0001f)
  3127. {
  3128. // Create a tangent perpendicular to the normal
  3129. if (fabsf(normal.z) > 0.707f) orthogonalized = (Vector3){ 1.0f, 0.0f, 0.0f };
  3130. else orthogonalized = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
  3131. }
  3132. else
  3133. {
  3134. // Normalize the orthogonalized tangent
  3135. orthogonalized = Vector3Normalize(orthogonalized);
  3136. }
  3137. // Store the calculated tangent
  3138. mesh->tangents[i*4 + 0] = orthogonalized.x;
  3139. mesh->tangents[i*4 + 1] = orthogonalized.y;
  3140. mesh->tangents[i*4 + 2] = orthogonalized.z;
  3141. // Calculate the handedness (w component)
  3142. mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, orthogonalized), tan2[i]) < 0.0f)? -1.0f : 1.0f;
  3143. }
  3144. // Free temporary arrays
  3145. RL_FREE(tan1);
  3146. RL_FREE(tan2);
  3147. // Update vertex buffers if available
  3148. if (mesh->vboId != NULL)
  3149. {
  3150. if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
  3151. {
  3152. // Update existing tangent vertex buffer
  3153. rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
  3154. }
  3155. else
  3156. {
  3157. // Create new tangent vertex buffer
  3158. mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
  3159. }
  3160. // Set up vertex attributes for shader
  3161. rlEnableVertexArray(mesh->vaoId);
  3162. rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);
  3163. rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);
  3164. rlDisableVertexArray();
  3165. }
  3166. TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh");
  3167. }
  3168. // Draw a model (with texture if set)
  3169. void DrawModel(Model model, Vector3 position, float scale, Color tint)
  3170. {
  3171. Vector3 vScale = { scale, scale, scale };
  3172. Vector3 rotationAxis = { 0.0f, 1.0f, 0.0f };
  3173. DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint);
  3174. }
  3175. // Draw a model with extended parameters
  3176. void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
  3177. {
  3178. // Calculate transformation matrix from function parameters
  3179. // Get transform matrix (rotation -> scale -> translation)
  3180. Matrix matScale = MatrixScale(scale.x, scale.y, scale.z);
  3181. Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD);
  3182. Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z);
  3183. Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
  3184. // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform)
  3185. model.transform = MatrixMultiply(model.transform, matTransform);
  3186. for (int i = 0; i < model.meshCount; i++)
  3187. {
  3188. Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color;
  3189. Color colorTint = WHITE;
  3190. colorTint.r = (unsigned char)(((int)color.r*(int)tint.r)/255);
  3191. colorTint.g = (unsigned char)(((int)color.g*(int)tint.g)/255);
  3192. colorTint.b = (unsigned char)(((int)color.b*(int)tint.b)/255);
  3193. colorTint.a = (unsigned char)(((int)color.a*(int)tint.a)/255);
  3194. model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;
  3195. DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform);
  3196. model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color;
  3197. }
  3198. }
  3199. // Draw a model wires (with texture if set)
  3200. void DrawModelWires(Model model, Vector3 position, float scale, Color tint)
  3201. {
  3202. rlEnableWireMode();
  3203. DrawModel(model, position, scale, tint);
  3204. rlDisableWireMode();
  3205. }
  3206. // Draw a model wires (with texture if set) with extended parameters
  3207. void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
  3208. {
  3209. rlEnableWireMode();
  3210. DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
  3211. rlDisableWireMode();
  3212. }
  3213. // Draw a model points
  3214. // WARNING: OpenGL ES 2.0 does not support point mode drawing
  3215. // TODO: gate these properly for non es 2.0 versions only
  3216. void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
  3217. {
  3218. rlEnablePointMode();
  3219. rlDisableBackfaceCulling();
  3220. DrawModel(model, position, scale, tint);
  3221. rlEnableBackfaceCulling();
  3222. rlDisablePointMode();
  3223. }
  3224. // Draw a model points
  3225. // WARNING: OpenGL ES 2.0 does not support point mode drawing
  3226. void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
  3227. {
  3228. rlEnablePointMode();
  3229. rlDisableBackfaceCulling();
  3230. DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
  3231. rlEnableBackfaceCulling();
  3232. rlDisablePointMode();
  3233. }
  3234. // Draw a billboard
  3235. void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
  3236. {
  3237. Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };
  3238. DrawBillboardRec(camera, texture, source, position, (Vector2){ scale*fabsf((float)source.width/source.height), scale }, tint);
  3239. }
  3240. // Draw a billboard (part of a texture defined by a rectangle)
  3241. void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint)
  3242. {
  3243. // NOTE: Billboard locked on axis-Y
  3244. Vector3 up = { 0.0f, 1.0f, 0.0f };
  3245. DrawBillboardPro(camera, texture, source, position, up, size, Vector2Scale(size, 0.5), 0.0f, tint);
  3246. }
  3247. // Draw a billboard with additional parameters
  3248. void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)
  3249. {
  3250. // Compute the up vector and the right vector
  3251. Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
  3252. Vector3 right = { matView.m0, matView.m4, matView.m8 };
  3253. right = Vector3Scale(right, size.x);
  3254. up = Vector3Scale(up, size.y);
  3255. // Flip the content of the billboard while maintaining the counterclockwise edge rendering order
  3256. if (size.x < 0.0f)
  3257. {
  3258. source.x += size.x;
  3259. source.width *= -1.0;
  3260. right = Vector3Negate(right);
  3261. origin.x *= -1.0f;
  3262. }
  3263. if (size.y < 0.0f)
  3264. {
  3265. source.y += size.y;
  3266. source.height *= -1.0;
  3267. up = Vector3Negate(up);
  3268. origin.y *= -1.0f;
  3269. }
  3270. // Draw the texture region described by source on the following rectangle in 3D space:
  3271. //
  3272. // size.x <--.
  3273. // 3 ^---------------------------+ 2 \ rotation
  3274. // | | /
  3275. // | |
  3276. // | origin.x position |
  3277. // up |.............. | size.y
  3278. // | . |
  3279. // | . origin.y |
  3280. // | . |
  3281. // 0 +---------------------------> 1
  3282. // right
  3283. Vector3 forward;
  3284. if (rotation != 0.0) forward = Vector3CrossProduct(right, up);
  3285. Vector3 origin3D = Vector3Add(Vector3Scale(Vector3Normalize(right), origin.x), Vector3Scale(Vector3Normalize(up), origin.y));
  3286. Vector3 points[4];
  3287. points[0] = Vector3Zero();
  3288. points[1] = right;
  3289. points[2] = Vector3Add(up, right);
  3290. points[3] = up;
  3291. for (int i = 0; i < 4; i++)
  3292. {
  3293. points[i] = Vector3Subtract(points[i], origin3D);
  3294. if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation*DEG2RAD);
  3295. points[i] = Vector3Add(points[i], position);
  3296. }
  3297. Vector2 texcoords[4];
  3298. texcoords[0] = (Vector2){ (float)source.x/texture.width, (float)(source.y + source.height)/texture.height };
  3299. texcoords[1] = (Vector2){ (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height };
  3300. texcoords[2] = (Vector2){ (float)(source.x + source.width)/texture.width, (float)source.y/texture.height };
  3301. texcoords[3] = (Vector2){ (float)source.x/texture.width, (float)source.y/texture.height };
  3302. rlSetTexture(texture.id);
  3303. rlBegin(RL_QUADS);
  3304. rlColor4ub(tint.r, tint.g, tint.b, tint.a);
  3305. for (int i = 0; i < 4; i++)
  3306. {
  3307. rlTexCoord2f(texcoords[i].x, texcoords[i].y);
  3308. rlVertex3f(points[i].x, points[i].y, points[i].z);
  3309. }
  3310. rlEnd();
  3311. rlSetTexture(0);
  3312. }
  3313. // Draw a bounding box with wires
  3314. void DrawBoundingBox(BoundingBox box, Color color)
  3315. {
  3316. Vector3 size = { 0 };
  3317. size.x = fabsf(box.max.x - box.min.x);
  3318. size.y = fabsf(box.max.y - box.min.y);
  3319. size.z = fabsf(box.max.z - box.min.z);
  3320. Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };
  3321. DrawCubeWires(center, size.x, size.y, size.z, color);
  3322. }
  3323. // Check collision between two spheres
  3324. bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2)
  3325. {
  3326. bool collision = false;
  3327. // Simple way to check for collision, just checking distance between two points
  3328. // Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution
  3329. /*
  3330. float dx = center1.x - center2.x; // X distance between centers
  3331. float dy = center1.y - center2.y; // Y distance between centers
  3332. float dz = center1.z - center2.z; // Z distance between centers
  3333. float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers
  3334. if (distance <= (radius1 + radius2)) collision = true;
  3335. */
  3336. // Check for distances squared to avoid sqrtf()
  3337. if (Vector3DotProduct(Vector3Subtract(center2, center1), Vector3Subtract(center2, center1)) <= (radius1 + radius2)*(radius1 + radius2)) collision = true;
  3338. return collision;
  3339. }
  3340. // Check collision between two boxes
  3341. // NOTE: Boxes are defined by two points minimum and maximum
  3342. bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2)
  3343. {
  3344. bool collision = true;
  3345. if ((box1.max.x >= box2.min.x) && (box1.min.x <= box2.max.x))
  3346. {
  3347. if ((box1.max.y < box2.min.y) || (box1.min.y > box2.max.y)) collision = false;
  3348. if ((box1.max.z < box2.min.z) || (box1.min.z > box2.max.z)) collision = false;
  3349. }
  3350. else collision = false;
  3351. return collision;
  3352. }
  3353. // Check collision between box and sphere
  3354. bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)
  3355. {
  3356. bool collision = false;
  3357. float dmin = 0;
  3358. if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2);
  3359. else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);
  3360. if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);
  3361. else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);
  3362. if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);
  3363. else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);
  3364. if (dmin <= (radius*radius)) collision = true;
  3365. return collision;
  3366. }
  3367. // Get collision info between ray and sphere
  3368. RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius)
  3369. {
  3370. RayCollision collision = { 0 };
  3371. Vector3 raySpherePos = Vector3Subtract(center, ray.position);
  3372. float vector = Vector3DotProduct(raySpherePos, ray.direction);
  3373. float distance = Vector3Length(raySpherePos);
  3374. float d = radius*radius - (distance*distance - vector*vector);
  3375. collision.hit = d >= 0.0f;
  3376. // Check if ray origin is inside the sphere to calculate the correct collision point
  3377. if (distance < radius)
  3378. {
  3379. collision.distance = vector + sqrtf(d);
  3380. // Calculate collision point
  3381. collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));
  3382. // Calculate collision normal (pointing outwards)
  3383. collision.normal = Vector3Negate(Vector3Normalize(Vector3Subtract(collision.point, center)));
  3384. }
  3385. else
  3386. {
  3387. collision.distance = vector - sqrtf(d);
  3388. // Calculate collision point
  3389. collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));
  3390. // Calculate collision normal (pointing inwards)
  3391. collision.normal = Vector3Normalize(Vector3Subtract(collision.point, center));
  3392. }
  3393. return collision;
  3394. }
  3395. // Get collision info between ray and box
  3396. RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)
  3397. {
  3398. RayCollision collision = { 0 };
  3399. // Note: If ray.position is inside the box, the distance is negative (as if the ray was reversed)
  3400. // Reversing ray.direction will give use the correct result
  3401. bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&
  3402. (ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&
  3403. (ray.position.z > box.min.z) && (ray.position.z < box.max.z);
  3404. if (insideBox) ray.direction = Vector3Negate(ray.direction);
  3405. float t[11] = { 0 };
  3406. t[8] = 1.0f/ray.direction.x;
  3407. t[9] = 1.0f/ray.direction.y;
  3408. t[10] = 1.0f/ray.direction.z;
  3409. t[0] = (box.min.x - ray.position.x)*t[8];
  3410. t[1] = (box.max.x - ray.position.x)*t[8];
  3411. t[2] = (box.min.y - ray.position.y)*t[9];
  3412. t[3] = (box.max.y - ray.position.y)*t[9];
  3413. t[4] = (box.min.z - ray.position.z)*t[10];
  3414. t[5] = (box.max.z - ray.position.z)*t[10];
  3415. t[6] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));
  3416. t[7] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));
  3417. collision.hit = !((t[7] < 0) || (t[6] > t[7]));
  3418. collision.distance = t[6];
  3419. collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));
  3420. // Get box center point
  3421. collision.normal = Vector3Lerp(box.min, box.max, 0.5f);
  3422. // Get vector center point->hit point
  3423. collision.normal = Vector3Subtract(collision.point, collision.normal);
  3424. // Scale vector to unit cube
  3425. // NOTE: We use an additional .01 to fix numerical errors
  3426. collision.normal = Vector3Scale(collision.normal, 2.01f);
  3427. collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));
  3428. // The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
  3429. // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal!
  3430. collision.normal.x = (float)((int)collision.normal.x);
  3431. collision.normal.y = (float)((int)collision.normal.y);
  3432. collision.normal.z = (float)((int)collision.normal.z);
  3433. collision.normal = Vector3Normalize(collision.normal);
  3434. if (insideBox)
  3435. {
  3436. // Reset ray.direction
  3437. ray.direction = Vector3Negate(ray.direction);
  3438. // Fix result
  3439. collision.distance *= -1.0f;
  3440. collision.normal = Vector3Negate(collision.normal);
  3441. }
  3442. return collision;
  3443. }
  3444. // Get collision info between ray and mesh
  3445. RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)
  3446. {
  3447. RayCollision collision = { 0 };
  3448. // Check if mesh vertex data on CPU for testing
  3449. if (mesh.vertices != NULL)
  3450. {
  3451. int triangleCount = mesh.triangleCount;
  3452. // Test against all triangles in mesh
  3453. for (int i = 0; i < triangleCount; i++)
  3454. {
  3455. Vector3 a, b, c;
  3456. Vector3 *vertdata = (Vector3 *)mesh.vertices;
  3457. if (mesh.indices)
  3458. {
  3459. a = vertdata[mesh.indices[i*3 + 0]];
  3460. b = vertdata[mesh.indices[i*3 + 1]];
  3461. c = vertdata[mesh.indices[i*3 + 2]];
  3462. }
  3463. else
  3464. {
  3465. a = vertdata[i*3 + 0];
  3466. b = vertdata[i*3 + 1];
  3467. c = vertdata[i*3 + 2];
  3468. }
  3469. a = Vector3Transform(a, transform);
  3470. b = Vector3Transform(b, transform);
  3471. c = Vector3Transform(c, transform);
  3472. RayCollision triHitInfo = GetRayCollisionTriangle(ray, a, b, c);
  3473. if (triHitInfo.hit)
  3474. {
  3475. // Save the closest hit triangle
  3476. if ((!collision.hit) || (collision.distance > triHitInfo.distance)) collision = triHitInfo;
  3477. }
  3478. }
  3479. }
  3480. return collision;
  3481. }
  3482. // Get collision info between ray and triangle
  3483. // NOTE: The points are expected to be in counter-clockwise winding
  3484. // NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
  3485. RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3)
  3486. {
  3487. #define EPSILON 0.000001f // A small number
  3488. RayCollision collision = { 0 };
  3489. Vector3 edge1 = { 0 };
  3490. Vector3 edge2 = { 0 };
  3491. Vector3 p, q, tv;
  3492. float det, invDet, u, v, t;
  3493. // Find vectors for two edges sharing V1
  3494. edge1 = Vector3Subtract(p2, p1);
  3495. edge2 = Vector3Subtract(p3, p1);
  3496. // Begin calculating determinant - also used to calculate u parameter
  3497. p = Vector3CrossProduct(ray.direction, edge2);
  3498. // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle
  3499. det = Vector3DotProduct(edge1, p);
  3500. // Avoid culling!
  3501. if ((det > -EPSILON) && (det < EPSILON)) return collision;
  3502. invDet = 1.0f/det;
  3503. // Calculate distance from V1 to ray origin
  3504. tv = Vector3Subtract(ray.position, p1);
  3505. // Calculate u parameter and test bound
  3506. u = Vector3DotProduct(tv, p)*invDet;
  3507. // The intersection lies outside the triangle
  3508. if ((u < 0.0f) || (u > 1.0f)) return collision;
  3509. // Prepare to test v parameter
  3510. q = Vector3CrossProduct(tv, edge1);
  3511. // Calculate V parameter and test bound
  3512. v = Vector3DotProduct(ray.direction, q)*invDet;
  3513. // The intersection lies outside the triangle
  3514. if ((v < 0.0f) || ((u + v) > 1.0f)) return collision;
  3515. t = Vector3DotProduct(edge2, q)*invDet;
  3516. if (t > EPSILON)
  3517. {
  3518. // Ray hit, get hit point and normal
  3519. collision.hit = true;
  3520. collision.distance = t;
  3521. collision.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2));
  3522. collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, t));
  3523. }
  3524. return collision;
  3525. }
  3526. // Get collision info between ray and quad
  3527. // NOTE: The points are expected to be in counter-clockwise winding
  3528. RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)
  3529. {
  3530. RayCollision collision = { 0 };
  3531. collision = GetRayCollisionTriangle(ray, p1, p2, p4);
  3532. if (!collision.hit) collision = GetRayCollisionTriangle(ray, p2, p3, p4);
  3533. return collision;
  3534. }
  3535. //----------------------------------------------------------------------------------
  3536. // Module Internal Functions Definition
  3537. //----------------------------------------------------------------------------------
  3538. #if defined(SUPPORT_FILEFORMAT_IQM) || defined(SUPPORT_FILEFORMAT_GLTF)
  3539. // Build pose from parent joints
  3540. // NOTE: Required for animations loading (required by IQM and GLTF)
  3541. static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform *transforms)
  3542. {
  3543. for (int i = 0; i < boneCount; i++)
  3544. {
  3545. if (bones[i].parent >= 0)
  3546. {
  3547. if (bones[i].parent > i)
  3548. {
  3549. TRACELOG(LOG_WARNING, "Assumes bones are toplogically sorted, but bone %d has parent %d. Skipping.", i, bones[i].parent);
  3550. continue;
  3551. }
  3552. transforms[i].rotation = QuaternionMultiply(transforms[bones[i].parent].rotation, transforms[i].rotation);
  3553. transforms[i].scale = Vector3Multiply(transforms[i].scale, transforms[bones[i].parent].scale);
  3554. transforms[i].translation = Vector3Multiply(transforms[i].translation, transforms[bones[i].parent].scale);
  3555. transforms[i].translation = Vector3RotateByQuaternion(transforms[i].translation, transforms[bones[i].parent].rotation);
  3556. transforms[i].translation = Vector3Add(transforms[i].translation, transforms[bones[i].parent].translation);
  3557. }
  3558. }
  3559. }
  3560. #endif
  3561. #if defined(SUPPORT_FILEFORMAT_OBJ)
  3562. // Load OBJ mesh data
  3563. //
  3564. // Keep the following information in mind when reading this
  3565. // - A mesh is created for every material present in the obj file
  3566. // - the model.meshCount is therefore the materialCount returned from tinyobj
  3567. // - the mesh is automatically triangulated by tinyobj
  3568. static Model LoadOBJ(const char *fileName)
  3569. {
  3570. tinyobj_attrib_t objAttributes = { 0 };
  3571. tinyobj_shape_t *objShapes = NULL;
  3572. unsigned int objShapeCount = 0;
  3573. tinyobj_material_t *objMaterials = NULL;
  3574. unsigned int objMaterialCount = 0;
  3575. Model model = { 0 };
  3576. model.transform = MatrixIdentity();
  3577. char *fileText = LoadFileText(fileName);
  3578. if (fileText == NULL)
  3579. {
  3580. TRACELOG(LOG_WARNING, "MODEL: [%s] Unable to read obj file", fileName);
  3581. return model;
  3582. }
  3583. char currentDir[1024] = { 0 };
  3584. strcpy(currentDir, GetWorkingDirectory()); // Save current working directory
  3585. const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
  3586. if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
  3587. unsigned int dataSize = (unsigned int)strlen(fileText);
  3588. unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;
  3589. int ret = tinyobj_parse_obj(&objAttributes, &objShapes, &objShapeCount, &objMaterials, &objMaterialCount, fileText, dataSize, flags);
  3590. if (ret != TINYOBJ_SUCCESS)
  3591. {
  3592. TRACELOG(LOG_WARNING, "MODEL: Unable to read obj data %s", fileName);
  3593. return model;
  3594. }
  3595. UnloadFileText(fileText);
  3596. unsigned int faceVertIndex = 0;
  3597. unsigned int nextShape = 1;
  3598. int lastMaterial = -1;
  3599. unsigned int meshIndex = 0;
  3600. // Count meshes
  3601. unsigned int nextShapeEnd = objAttributes.num_face_num_verts;
  3602. // See how many verts till the next shape
  3603. if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
  3604. // Walk all the faces
  3605. for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
  3606. {
  3607. if (faceId >= nextShapeEnd)
  3608. {
  3609. // Try to find the last vert in the next shape
  3610. nextShape++;
  3611. if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
  3612. else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
  3613. meshIndex++;
  3614. }
  3615. else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
  3616. {
  3617. meshIndex++; // If this is a new material, we need to allocate a new mesh
  3618. }
  3619. lastMaterial = objAttributes.material_ids[faceId];
  3620. faceVertIndex += objAttributes.face_num_verts[faceId];
  3621. }
  3622. // Allocate the base meshes and materials
  3623. model.meshCount = meshIndex + 1;
  3624. model.meshes = (Mesh *)MemAlloc(sizeof(Mesh)*model.meshCount);
  3625. if (objMaterialCount > 0)
  3626. {
  3627. model.materialCount = objMaterialCount;
  3628. model.materials = (Material *)MemAlloc(sizeof(Material)*objMaterialCount);
  3629. }
  3630. else // We must allocate at least one material
  3631. {
  3632. model.materialCount = 1;
  3633. model.materials = (Material *)MemAlloc(sizeof(Material)*1);
  3634. }
  3635. model.meshMaterial = (int *)MemAlloc(sizeof(int)*model.meshCount);
  3636. // See how many verts are in each mesh
  3637. unsigned int *localMeshVertexCounts = (unsigned int *)MemAlloc(sizeof(unsigned int)*model.meshCount);
  3638. faceVertIndex = 0;
  3639. nextShapeEnd = objAttributes.num_face_num_verts;
  3640. lastMaterial = -1;
  3641. meshIndex = 0;
  3642. unsigned int localMeshVertexCount = 0;
  3643. nextShape = 1;
  3644. if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
  3645. // Walk all the faces
  3646. for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
  3647. {
  3648. bool newMesh = false; // Do we need a new mesh?
  3649. if (faceId >= nextShapeEnd)
  3650. {
  3651. // Try to find the last vert in the next shape
  3652. nextShape++;
  3653. if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
  3654. else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
  3655. newMesh = true;
  3656. }
  3657. else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
  3658. {
  3659. newMesh = true;
  3660. }
  3661. lastMaterial = objAttributes.material_ids[faceId];
  3662. if (newMesh)
  3663. {
  3664. localMeshVertexCounts[meshIndex] = localMeshVertexCount;
  3665. localMeshVertexCount = 0;
  3666. meshIndex++;
  3667. }
  3668. faceVertIndex += objAttributes.face_num_verts[faceId];
  3669. localMeshVertexCount += objAttributes.face_num_verts[faceId];
  3670. }
  3671. localMeshVertexCounts[meshIndex] = localMeshVertexCount;
  3672. for (int i = 0; i < model.meshCount; i++)
  3673. {
  3674. // Allocate the buffers for each mesh
  3675. unsigned int vertexCount = localMeshVertexCounts[i];
  3676. model.meshes[i].vertexCount = vertexCount;
  3677. model.meshes[i].triangleCount = vertexCount/3;
  3678. model.meshes[i].vertices = (float *)MemAlloc(sizeof(float)*vertexCount*3);
  3679. model.meshes[i].normals = (float *)MemAlloc(sizeof(float)*vertexCount*3);
  3680. model.meshes[i].texcoords = (float *)MemAlloc(sizeof(float)*vertexCount*2);
  3681. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3682. model.meshes[i].colors = (unsigned char *)MemAlloc(sizeof(unsigned char)*vertexCount*4);
  3683. #else
  3684. model.meshes[i].colors = NULL;
  3685. #endif
  3686. }
  3687. MemFree(localMeshVertexCounts);
  3688. localMeshVertexCounts = NULL;
  3689. // Fill meshes
  3690. faceVertIndex = 0;
  3691. nextShapeEnd = objAttributes.num_face_num_verts;
  3692. // See how many verts till the next shape
  3693. nextShape = 1;
  3694. if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
  3695. lastMaterial = -1;
  3696. meshIndex = 0;
  3697. localMeshVertexCount = 0;
  3698. // Walk all the faces
  3699. for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
  3700. {
  3701. bool newMesh = false; // Do we need a new mesh?
  3702. if (faceId >= nextShapeEnd)
  3703. {
  3704. // Try to find the last vert in the next shape
  3705. nextShape++;
  3706. if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
  3707. else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
  3708. newMesh = true;
  3709. }
  3710. // If this is a new material, we need to allocate a new mesh
  3711. if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;
  3712. lastMaterial = objAttributes.material_ids[faceId];
  3713. if (newMesh)
  3714. {
  3715. localMeshVertexCount = 0;
  3716. meshIndex++;
  3717. }
  3718. int matId = 0;
  3719. if ((lastMaterial >= 0) && (lastMaterial < (int)objMaterialCount)) matId = lastMaterial;
  3720. model.meshMaterial[meshIndex] = matId;
  3721. for (int f = 0; f < objAttributes.face_num_verts[faceId]; f++)
  3722. {
  3723. int vertIndex = objAttributes.faces[faceVertIndex].v_idx;
  3724. int normalIndex = objAttributes.faces[faceVertIndex].vn_idx;
  3725. int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx;
  3726. for (int i = 0; i < 3; i++) model.meshes[meshIndex].vertices[localMeshVertexCount*3 + i] = objAttributes.vertices[vertIndex*3 + i];
  3727. if ((objAttributes.texcoords != NULL) && (texcordIndex != TINYOBJ_INVALID_INDEX) && (texcordIndex >= 0))
  3728. {
  3729. for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
  3730. model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
  3731. }
  3732. else
  3733. {
  3734. model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 0] = 0.0f;
  3735. model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 0.0f;
  3736. }
  3737. if ((objAttributes.normals != NULL) && (normalIndex != TINYOBJ_INVALID_INDEX) && (normalIndex >= 0))
  3738. {
  3739. for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
  3740. }
  3741. else
  3742. {
  3743. model.meshes[meshIndex].normals[localMeshVertexCount*3 + 0] = 0.0f;
  3744. model.meshes[meshIndex].normals[localMeshVertexCount*3 + 1] = 1.0f;
  3745. model.meshes[meshIndex].normals[localMeshVertexCount*3 + 2] = 0.0f;
  3746. }
  3747. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3748. for (int i = 0; i < 4; i++) model.meshes[meshIndex].colors[localMeshVertexCount*4 + i] = 255;
  3749. #endif
  3750. faceVertIndex++;
  3751. localMeshVertexCount++;
  3752. }
  3753. }
  3754. if (objMaterialCount > 0) ProcessMaterialsOBJ(model.materials, objMaterials, objMaterialCount);
  3755. else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh
  3756. tinyobj_attrib_free(&objAttributes);
  3757. tinyobj_shapes_free(objShapes, objShapeCount);
  3758. tinyobj_materials_free(objMaterials, objMaterialCount);
  3759. // Restore current working directory
  3760. if (CHDIR(currentDir) != 0)
  3761. {
  3762. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);
  3763. }
  3764. return model;
  3765. }
  3766. #endif
  3767. #if defined(SUPPORT_FILEFORMAT_IQM)
  3768. // Load IQM mesh data
  3769. static Model LoadIQM(const char *fileName)
  3770. {
  3771. #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
  3772. #define IQM_VERSION 2 // only IQM version 2 supported
  3773. #define BONE_NAME_LENGTH 32 // BoneInfo name string length
  3774. #define MESH_NAME_LENGTH 32 // Mesh name string length
  3775. #define MATERIAL_NAME_LENGTH 32 // Material name string length
  3776. int dataSize = 0;
  3777. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  3778. unsigned char *fileDataPtr = fileData;
  3779. // IQM file structs
  3780. //-----------------------------------------------------------------------------------
  3781. typedef struct IQMHeader {
  3782. char magic[16];
  3783. unsigned int version;
  3784. unsigned int dataSize;
  3785. unsigned int flags;
  3786. unsigned int num_text, ofs_text;
  3787. unsigned int num_meshes, ofs_meshes;
  3788. unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
  3789. unsigned int num_triangles, ofs_triangles, ofs_adjacency;
  3790. unsigned int num_joints, ofs_joints;
  3791. unsigned int num_poses, ofs_poses;
  3792. unsigned int num_anims, ofs_anims;
  3793. unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
  3794. unsigned int num_comment, ofs_comment;
  3795. unsigned int num_extensions, ofs_extensions;
  3796. } IQMHeader;
  3797. typedef struct IQMMesh {
  3798. unsigned int name;
  3799. unsigned int material;
  3800. unsigned int first_vertex, num_vertexes;
  3801. unsigned int first_triangle, num_triangles;
  3802. } IQMMesh;
  3803. typedef struct IQMTriangle {
  3804. unsigned int vertex[3];
  3805. } IQMTriangle;
  3806. typedef struct IQMJoint {
  3807. unsigned int name;
  3808. int parent;
  3809. float translate[3], rotate[4], scale[3];
  3810. } IQMJoint;
  3811. typedef struct IQMVertexArray {
  3812. unsigned int type;
  3813. unsigned int flags;
  3814. unsigned int format;
  3815. unsigned int size;
  3816. unsigned int offset;
  3817. } IQMVertexArray;
  3818. // NOTE: Below IQM structures are not used but listed for reference
  3819. /*
  3820. typedef struct IQMAdjacency {
  3821. unsigned int triangle[3];
  3822. } IQMAdjacency;
  3823. typedef struct IQMPose {
  3824. int parent;
  3825. unsigned int mask;
  3826. float channeloffset[10];
  3827. float channelscale[10];
  3828. } IQMPose;
  3829. typedef struct IQMAnim {
  3830. unsigned int name;
  3831. unsigned int first_frame, num_frames;
  3832. float framerate;
  3833. unsigned int flags;
  3834. } IQMAnim;
  3835. typedef struct IQMBounds {
  3836. float bbmin[3], bbmax[3];
  3837. float xyradius, radius;
  3838. } IQMBounds;
  3839. */
  3840. //-----------------------------------------------------------------------------------
  3841. // IQM vertex data types
  3842. enum {
  3843. IQM_POSITION = 0,
  3844. IQM_TEXCOORD = 1,
  3845. IQM_NORMAL = 2,
  3846. IQM_TANGENT = 3, // NOTE: Tangents unused by default
  3847. IQM_BLENDINDEXES = 4,
  3848. IQM_BLENDWEIGHTS = 5,
  3849. IQM_COLOR = 6,
  3850. IQM_CUSTOM = 0x10 // NOTE: Custom vertex values unused by default
  3851. };
  3852. Model model = { 0 };
  3853. IQMMesh *imesh = NULL;
  3854. IQMTriangle *tri = NULL;
  3855. IQMVertexArray *va = NULL;
  3856. IQMJoint *ijoint = NULL;
  3857. float *vertex = NULL;
  3858. float *normal = NULL;
  3859. float *text = NULL;
  3860. char *blendi = NULL;
  3861. unsigned char *blendw = NULL;
  3862. unsigned char *color = NULL;
  3863. // In case file can not be read, return an empty model
  3864. if (fileDataPtr == NULL) return model;
  3865. const char *basePath = GetDirectoryPath(fileName);
  3866. // Read IQM header
  3867. IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;
  3868. if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)
  3869. {
  3870. TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);
  3871. UnloadFileData(fileData);
  3872. return model;
  3873. }
  3874. if (iqmHeader->version != IQM_VERSION)
  3875. {
  3876. TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);
  3877. UnloadFileData(fileData);
  3878. return model;
  3879. }
  3880. //fileDataPtr += sizeof(IQMHeader); // Move file data pointer
  3881. // Meshes data processing
  3882. imesh = (IQMMesh *)RL_MALLOC(iqmHeader->num_meshes*sizeof(IQMMesh));
  3883. //fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET);
  3884. //fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile);
  3885. memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh));
  3886. model.meshCount = iqmHeader->num_meshes;
  3887. model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  3888. model.materialCount = model.meshCount;
  3889. model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
  3890. model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  3891. char name[MESH_NAME_LENGTH] = { 0 };
  3892. char material[MATERIAL_NAME_LENGTH] = { 0 };
  3893. for (int i = 0; i < model.meshCount; i++)
  3894. {
  3895. //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].name, SEEK_SET);
  3896. //fread(name, sizeof(char), MESH_NAME_LENGTH, iqmFile);
  3897. memcpy(name, fileDataPtr + iqmHeader->ofs_text + imesh[i].name, MESH_NAME_LENGTH*sizeof(char));
  3898. //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].material, SEEK_SET);
  3899. //fread(material, sizeof(char), MATERIAL_NAME_LENGTH, iqmFile);
  3900. memcpy(material, fileDataPtr + iqmHeader->ofs_text + imesh[i].material, MATERIAL_NAME_LENGTH*sizeof(char));
  3901. model.materials[i] = LoadMaterialDefault();
  3902. model.materials[i].maps[MATERIAL_MAP_ALBEDO].texture = LoadTexture(TextFormat("%s/%s", basePath, material));
  3903. model.meshMaterial[i] = i;
  3904. TRACELOG(LOG_DEBUG, "MODEL: [%s] mesh name (%s), material (%s)", fileName, name, material);
  3905. model.meshes[i].vertexCount = imesh[i].num_vertexes;
  3906. model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions
  3907. model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals
  3908. model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords
  3909. model.meshes[i].boneIds = (unsigned char *)RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(unsigned char)); // Up-to 4 bones supported!
  3910. model.meshes[i].boneWeights = (float *)RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!
  3911. model.meshes[i].triangleCount = imesh[i].num_triangles;
  3912. model.meshes[i].indices = (unsigned short *)RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
  3913. // Animated vertex data, what we actually process for rendering
  3914. // NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
  3915. model.meshes[i].animVertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
  3916. model.meshes[i].animNormals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
  3917. }
  3918. // Triangles data processing
  3919. tri = (IQMTriangle *)RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle));
  3920. //fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET);
  3921. //fread(tri, sizeof(IQMTriangle), iqmHeader->num_triangles, iqmFile);
  3922. memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle));
  3923. for (int m = 0; m < model.meshCount; m++)
  3924. {
  3925. int tcounter = 0;
  3926. for (unsigned int i = imesh[m].first_triangle; i < (imesh[m].first_triangle + imesh[m].num_triangles); i++)
  3927. {
  3928. // IQM triangles indexes are stored in counter-clockwise, but raylib processes the index in linear order,
  3929. // expecting they point to the counter-clockwise vertex triangle, so we need to reverse triangle indexes
  3930. // NOTE: raylib renders vertex data in counter-clockwise order (standard convention) by default
  3931. model.meshes[m].indices[tcounter + 2] = tri[i].vertex[0] - imesh[m].first_vertex;
  3932. model.meshes[m].indices[tcounter + 1] = tri[i].vertex[1] - imesh[m].first_vertex;
  3933. model.meshes[m].indices[tcounter] = tri[i].vertex[2] - imesh[m].first_vertex;
  3934. tcounter += 3;
  3935. }
  3936. }
  3937. // Vertex arrays data processing
  3938. va = (IQMVertexArray *)RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
  3939. //fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET);
  3940. //fread(va, sizeof(IQMVertexArray), iqmHeader->num_vertexarrays, iqmFile);
  3941. memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
  3942. for (unsigned int i = 0; i < iqmHeader->num_vertexarrays; i++)
  3943. {
  3944. switch (va[i].type)
  3945. {
  3946. case IQM_POSITION:
  3947. {
  3948. vertex = (float *)RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
  3949. //fseek(iqmFile, va[i].offset, SEEK_SET);
  3950. //fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
  3951. memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
  3952. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  3953. {
  3954. int vCounter = 0;
  3955. for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)
  3956. {
  3957. model.meshes[m].vertices[vCounter] = vertex[i];
  3958. model.meshes[m].animVertices[vCounter] = vertex[i];
  3959. vCounter++;
  3960. }
  3961. }
  3962. } break;
  3963. case IQM_NORMAL:
  3964. {
  3965. normal = (float *)RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
  3966. //fseek(iqmFile, va[i].offset, SEEK_SET);
  3967. //fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
  3968. memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
  3969. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  3970. {
  3971. int vCounter = 0;
  3972. for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)
  3973. {
  3974. model.meshes[m].normals[vCounter] = normal[i];
  3975. model.meshes[m].animNormals[vCounter] = normal[i];
  3976. vCounter++;
  3977. }
  3978. }
  3979. } break;
  3980. case IQM_TEXCOORD:
  3981. {
  3982. text = (float *)RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float));
  3983. //fseek(iqmFile, va[i].offset, SEEK_SET);
  3984. //fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile);
  3985. memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float));
  3986. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  3987. {
  3988. int vCounter = 0;
  3989. for (unsigned int i = imesh[m].first_vertex*2; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*2; i++)
  3990. {
  3991. model.meshes[m].texcoords[vCounter] = text[i];
  3992. vCounter++;
  3993. }
  3994. }
  3995. } break;
  3996. case IQM_BLENDINDEXES:
  3997. {
  3998. blendi = (char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char));
  3999. //fseek(iqmFile, va[i].offset, SEEK_SET);
  4000. //fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile);
  4001. memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char));
  4002. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  4003. {
  4004. int boneCounter = 0;
  4005. for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
  4006. {
  4007. model.meshes[m].boneIds[boneCounter] = blendi[i];
  4008. boneCounter++;
  4009. }
  4010. }
  4011. } break;
  4012. case IQM_BLENDWEIGHTS:
  4013. {
  4014. blendw = (unsigned char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
  4015. //fseek(iqmFile, va[i].offset, SEEK_SET);
  4016. //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
  4017. memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
  4018. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  4019. {
  4020. int boneCounter = 0;
  4021. for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
  4022. {
  4023. model.meshes[m].boneWeights[boneCounter] = blendw[i]/255.0f;
  4024. boneCounter++;
  4025. }
  4026. }
  4027. } break;
  4028. case IQM_COLOR:
  4029. {
  4030. color = (unsigned char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
  4031. //fseek(iqmFile, va[i].offset, SEEK_SET);
  4032. //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
  4033. memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
  4034. for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
  4035. {
  4036. model.meshes[m].colors = (unsigned char *)RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char));
  4037. int vCounter = 0;
  4038. for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
  4039. {
  4040. model.meshes[m].colors[vCounter] = color[i];
  4041. vCounter++;
  4042. }
  4043. }
  4044. } break;
  4045. }
  4046. }
  4047. // Bones (joints) data processing
  4048. ijoint = (IQMJoint *)RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
  4049. //fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET);
  4050. //fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);
  4051. memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
  4052. model.boneCount = iqmHeader->num_joints;
  4053. model.bones = (BoneInfo *)RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo));
  4054. model.bindPose = (Transform *)RL_MALLOC(iqmHeader->num_joints*sizeof(Transform));
  4055. for (unsigned int i = 0; i < iqmHeader->num_joints; i++)
  4056. {
  4057. // Bones
  4058. model.bones[i].parent = ijoint[i].parent;
  4059. //fseek(iqmFile, iqmHeader->ofs_text + ijoint[i].name, SEEK_SET);
  4060. //fread(model.bones[i].name, sizeof(char), BONE_NAME_LENGTH, iqmFile);
  4061. memcpy(model.bones[i].name, fileDataPtr + iqmHeader->ofs_text + ijoint[i].name, BONE_NAME_LENGTH*sizeof(char));
  4062. // Bind pose (base pose)
  4063. model.bindPose[i].translation.x = ijoint[i].translate[0];
  4064. model.bindPose[i].translation.y = ijoint[i].translate[1];
  4065. model.bindPose[i].translation.z = ijoint[i].translate[2];
  4066. model.bindPose[i].rotation.x = ijoint[i].rotate[0];
  4067. model.bindPose[i].rotation.y = ijoint[i].rotate[1];
  4068. model.bindPose[i].rotation.z = ijoint[i].rotate[2];
  4069. model.bindPose[i].rotation.w = ijoint[i].rotate[3];
  4070. model.bindPose[i].scale.x = ijoint[i].scale[0];
  4071. model.bindPose[i].scale.y = ijoint[i].scale[1];
  4072. model.bindPose[i].scale.z = ijoint[i].scale[2];
  4073. }
  4074. BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);
  4075. for (int i = 0; i < model.meshCount; i++)
  4076. {
  4077. model.meshes[i].boneCount = model.boneCount;
  4078. model.meshes[i].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
  4079. for (int j = 0; j < model.meshes[i].boneCount; j++)
  4080. {
  4081. model.meshes[i].boneMatrices[j] = MatrixIdentity();
  4082. }
  4083. }
  4084. UnloadFileData(fileData);
  4085. RL_FREE(imesh);
  4086. RL_FREE(tri);
  4087. RL_FREE(va);
  4088. RL_FREE(vertex);
  4089. RL_FREE(normal);
  4090. RL_FREE(text);
  4091. RL_FREE(blendi);
  4092. RL_FREE(blendw);
  4093. RL_FREE(ijoint);
  4094. RL_FREE(color);
  4095. return model;
  4096. }
  4097. // Load IQM animation data
  4098. static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount)
  4099. {
  4100. #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
  4101. #define IQM_VERSION 2 // only IQM version 2 supported
  4102. int dataSize = 0;
  4103. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  4104. unsigned char *fileDataPtr = fileData;
  4105. typedef struct IQMHeader {
  4106. char magic[16];
  4107. unsigned int version;
  4108. unsigned int dataSize;
  4109. unsigned int flags;
  4110. unsigned int num_text, ofs_text;
  4111. unsigned int num_meshes, ofs_meshes;
  4112. unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
  4113. unsigned int num_triangles, ofs_triangles, ofs_adjacency;
  4114. unsigned int num_joints, ofs_joints;
  4115. unsigned int num_poses, ofs_poses;
  4116. unsigned int num_anims, ofs_anims;
  4117. unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
  4118. unsigned int num_comment, ofs_comment;
  4119. unsigned int num_extensions, ofs_extensions;
  4120. } IQMHeader;
  4121. typedef struct IQMJoint {
  4122. unsigned int name;
  4123. int parent;
  4124. float translate[3], rotate[4], scale[3];
  4125. } IQMJoint;
  4126. typedef struct IQMPose {
  4127. int parent;
  4128. unsigned int mask;
  4129. float channeloffset[10];
  4130. float channelscale[10];
  4131. } IQMPose;
  4132. typedef struct IQMAnim {
  4133. unsigned int name;
  4134. unsigned int first_frame, num_frames;
  4135. float framerate;
  4136. unsigned int flags;
  4137. } IQMAnim;
  4138. // In case file can not be read, return an empty model
  4139. if (fileDataPtr == NULL) return NULL;
  4140. // Read IQM header
  4141. IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;
  4142. if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)
  4143. {
  4144. TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);
  4145. UnloadFileData(fileData);
  4146. return NULL;
  4147. }
  4148. if (iqmHeader->version != IQM_VERSION)
  4149. {
  4150. TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);
  4151. UnloadFileData(fileData);
  4152. return NULL;
  4153. }
  4154. // Get bones data
  4155. IQMPose *poses = (IQMPose *)RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose));
  4156. //fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET);
  4157. //fread(poses, sizeof(IQMPose), iqmHeader->num_poses, iqmFile);
  4158. memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose));
  4159. // Get animations data
  4160. *animCount = iqmHeader->num_anims;
  4161. IQMAnim *anim = (IQMAnim *)RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim));
  4162. //fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET);
  4163. //fread(anim, sizeof(IQMAnim), iqmHeader->num_anims, iqmFile);
  4164. memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim));
  4165. ModelAnimation *animations = (ModelAnimation *)RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation));
  4166. // frameposes
  4167. unsigned short *framedata = (unsigned short *)RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
  4168. //fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET);
  4169. //fread(framedata, sizeof(unsigned short), iqmHeader->num_frames*iqmHeader->num_framechannels, iqmFile);
  4170. memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
  4171. // joints
  4172. IQMJoint *joints = (IQMJoint *)RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
  4173. memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
  4174. for (unsigned int a = 0; a < iqmHeader->num_anims; a++)
  4175. {
  4176. animations[a].frameCount = anim[a].num_frames;
  4177. animations[a].boneCount = iqmHeader->num_poses;
  4178. animations[a].bones = (BoneInfo *)RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
  4179. animations[a].framePoses = (Transform **)RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
  4180. memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here
  4181. TRACELOG(LOG_INFO, "IQM Anim %s", animations[a].name);
  4182. // animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
  4183. for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
  4184. {
  4185. // If animations and skeleton are in the same file, copy bone names to anim
  4186. if (iqmHeader->num_joints > 0)
  4187. memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char));
  4188. else
  4189. strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // default bone name otherwise
  4190. animations[a].bones[j].parent = poses[j].parent;
  4191. }
  4192. for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = (Transform *)RL_MALLOC(iqmHeader->num_poses*sizeof(Transform));
  4193. int dcounter = anim[a].first_frame*iqmHeader->num_framechannels;
  4194. for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
  4195. {
  4196. for (unsigned int i = 0; i < iqmHeader->num_poses; i++)
  4197. {
  4198. animations[a].framePoses[frame][i].translation.x = poses[i].channeloffset[0];
  4199. if (poses[i].mask & 0x01)
  4200. {
  4201. animations[a].framePoses[frame][i].translation.x += framedata[dcounter]*poses[i].channelscale[0];
  4202. dcounter++;
  4203. }
  4204. animations[a].framePoses[frame][i].translation.y = poses[i].channeloffset[1];
  4205. if (poses[i].mask & 0x02)
  4206. {
  4207. animations[a].framePoses[frame][i].translation.y += framedata[dcounter]*poses[i].channelscale[1];
  4208. dcounter++;
  4209. }
  4210. animations[a].framePoses[frame][i].translation.z = poses[i].channeloffset[2];
  4211. if (poses[i].mask & 0x04)
  4212. {
  4213. animations[a].framePoses[frame][i].translation.z += framedata[dcounter]*poses[i].channelscale[2];
  4214. dcounter++;
  4215. }
  4216. animations[a].framePoses[frame][i].rotation.x = poses[i].channeloffset[3];
  4217. if (poses[i].mask & 0x08)
  4218. {
  4219. animations[a].framePoses[frame][i].rotation.x += framedata[dcounter]*poses[i].channelscale[3];
  4220. dcounter++;
  4221. }
  4222. animations[a].framePoses[frame][i].rotation.y = poses[i].channeloffset[4];
  4223. if (poses[i].mask & 0x10)
  4224. {
  4225. animations[a].framePoses[frame][i].rotation.y += framedata[dcounter]*poses[i].channelscale[4];
  4226. dcounter++;
  4227. }
  4228. animations[a].framePoses[frame][i].rotation.z = poses[i].channeloffset[5];
  4229. if (poses[i].mask & 0x20)
  4230. {
  4231. animations[a].framePoses[frame][i].rotation.z += framedata[dcounter]*poses[i].channelscale[5];
  4232. dcounter++;
  4233. }
  4234. animations[a].framePoses[frame][i].rotation.w = poses[i].channeloffset[6];
  4235. if (poses[i].mask & 0x40)
  4236. {
  4237. animations[a].framePoses[frame][i].rotation.w += framedata[dcounter]*poses[i].channelscale[6];
  4238. dcounter++;
  4239. }
  4240. animations[a].framePoses[frame][i].scale.x = poses[i].channeloffset[7];
  4241. if (poses[i].mask & 0x80)
  4242. {
  4243. animations[a].framePoses[frame][i].scale.x += framedata[dcounter]*poses[i].channelscale[7];
  4244. dcounter++;
  4245. }
  4246. animations[a].framePoses[frame][i].scale.y = poses[i].channeloffset[8];
  4247. if (poses[i].mask & 0x100)
  4248. {
  4249. animations[a].framePoses[frame][i].scale.y += framedata[dcounter]*poses[i].channelscale[8];
  4250. dcounter++;
  4251. }
  4252. animations[a].framePoses[frame][i].scale.z = poses[i].channeloffset[9];
  4253. if (poses[i].mask & 0x200)
  4254. {
  4255. animations[a].framePoses[frame][i].scale.z += framedata[dcounter]*poses[i].channelscale[9];
  4256. dcounter++;
  4257. }
  4258. animations[a].framePoses[frame][i].rotation = QuaternionNormalize(animations[a].framePoses[frame][i].rotation);
  4259. }
  4260. }
  4261. // Build frameposes
  4262. for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
  4263. {
  4264. for (int i = 0; i < animations[a].boneCount; i++)
  4265. {
  4266. if (animations[a].bones[i].parent >= 0)
  4267. {
  4268. animations[a].framePoses[frame][i].rotation = QuaternionMultiply(animations[a].framePoses[frame][animations[a].bones[i].parent].rotation, animations[a].framePoses[frame][i].rotation);
  4269. animations[a].framePoses[frame][i].translation = Vector3RotateByQuaternion(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].rotation);
  4270. animations[a].framePoses[frame][i].translation = Vector3Add(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].translation);
  4271. animations[a].framePoses[frame][i].scale = Vector3Multiply(animations[a].framePoses[frame][i].scale, animations[a].framePoses[frame][animations[a].bones[i].parent].scale);
  4272. }
  4273. }
  4274. }
  4275. }
  4276. UnloadFileData(fileData);
  4277. RL_FREE(joints);
  4278. RL_FREE(framedata);
  4279. RL_FREE(poses);
  4280. RL_FREE(anim);
  4281. return animations;
  4282. }
  4283. #endif
  4284. #if defined(SUPPORT_FILEFORMAT_GLTF)
  4285. // Load file data callback for cgltf
  4286. static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, const char *path, cgltf_size *size, void **data)
  4287. {
  4288. int filesize;
  4289. unsigned char *filedata = LoadFileData(path, &filesize);
  4290. if (filedata == NULL) return cgltf_result_io_error;
  4291. *size = filesize;
  4292. *data = filedata;
  4293. return cgltf_result_success;
  4294. }
  4295. // Release file data callback for cgltf
  4296. static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)
  4297. {
  4298. UnloadFileData(data);
  4299. }
  4300. // Load image from different glTF provided methods (uri, path, buffer_view)
  4301. static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPath)
  4302. {
  4303. Image image = { 0 };
  4304. if (cgltfImage == NULL) return image;
  4305. if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path)
  4306. {
  4307. if ((strlen(cgltfImage->uri) > 5) &&
  4308. (cgltfImage->uri[0] == 'd') &&
  4309. (cgltfImage->uri[1] == 'a') &&
  4310. (cgltfImage->uri[2] == 't') &&
  4311. (cgltfImage->uri[3] == 'a') &&
  4312. (cgltfImage->uri[4] == ':')) // Check if image is provided as base64 text data
  4313. {
  4314. // Data URI Format: data:<mediatype>;base64,<data>
  4315. // Find the comma
  4316. int i = 0;
  4317. while ((cgltfImage->uri[i] != ',') && (cgltfImage->uri[i] != 0)) i++;
  4318. if (cgltfImage->uri[i] == 0) TRACELOG(LOG_WARNING, "IMAGE: glTF data URI is not a valid image");
  4319. else
  4320. {
  4321. int base64Size = (int)strlen(cgltfImage->uri + i + 1);
  4322. while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
  4323. int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
  4324. int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes
  4325. void *data = NULL;
  4326. cgltf_options options = { 0 };
  4327. options.file.read = LoadFileGLTFCallback;
  4328. options.file.release = ReleaseFileGLTFCallback;
  4329. cgltf_result result = cgltf_load_buffer_base64(&options, outSize, cgltfImage->uri + i + 1, &data);
  4330. if (result == cgltf_result_success)
  4331. {
  4332. image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
  4333. RL_FREE(data);
  4334. }
  4335. }
  4336. }
  4337. else // Check if image is provided as image path
  4338. {
  4339. image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));
  4340. }
  4341. }
  4342. else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer
  4343. {
  4344. unsigned char *data = (unsigned char *)RL_MALLOC(cgltfImage->buffer_view->size);
  4345. int offset = (int)cgltfImage->buffer_view->offset;
  4346. int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1;
  4347. // Copy buffer data to memory for loading
  4348. for (unsigned int i = 0; i < cgltfImage->buffer_view->size; i++)
  4349. {
  4350. data[i] = ((unsigned char *)cgltfImage->buffer_view->buffer->data)[offset];
  4351. offset += stride;
  4352. }
  4353. // Check mime_type for image: (cgltfImage->mime_type == "image/png")
  4354. // NOTE: Detected that some models define mime_type as "image\\/png"
  4355. if ((strcmp(cgltfImage->mime_type, "image\\/png") == 0) || (strcmp(cgltfImage->mime_type, "image/png") == 0))
  4356. {
  4357. image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size);
  4358. }
  4359. else if ((strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) || (strcmp(cgltfImage->mime_type, "image/jpeg") == 0))
  4360. {
  4361. image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size);
  4362. }
  4363. else TRACELOG(LOG_WARNING, "MODEL: glTF image data MIME type not recognized", TextFormat("%s/%s", texPath, cgltfImage->uri));
  4364. RL_FREE(data);
  4365. }
  4366. return image;
  4367. }
  4368. // Load bone info from GLTF skin data
  4369. static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
  4370. {
  4371. *boneCount = (int)skin.joints_count;
  4372. BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
  4373. for (unsigned int i = 0; i < skin.joints_count; i++)
  4374. {
  4375. cgltf_node node = *skin.joints[i];
  4376. if (node.name != NULL) strncpy(bones[i].name, node.name, sizeof(bones[i].name) - 1);
  4377. // Find parent bone index
  4378. int parentIndex = -1;
  4379. for (unsigned int j = 0; j < skin.joints_count; j++)
  4380. {
  4381. if (skin.joints[j] == node.parent)
  4382. {
  4383. parentIndex = (int)j;
  4384. break;
  4385. }
  4386. }
  4387. bones[i].parent = parentIndex;
  4388. }
  4389. return bones;
  4390. }
  4391. // Load glTF file into model struct, .gltf and .glb supported
  4392. static Model LoadGLTF(const char *fileName)
  4393. {
  4394. /*********************************************************************************************
  4395. Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend)
  4396. Transform handling implemented by Paul Melis (@paulmelis)
  4397. Reviewed by Ramon Santamaria (@raysan5)
  4398. FEATURES:
  4399. - Supports .gltf and .glb files
  4400. - Supports embedded (base64) or external textures
  4401. - Supports PBR metallic/roughness flow, loads material textures, values and colors
  4402. PBR specular/glossiness flow and extended texture flows not supported
  4403. - Supports multiple meshes per model (every primitives is loaded as a separate mesh)
  4404. - Supports basic animations
  4405. - Transforms, including parent-child relations, are applied on the mesh data,
  4406. but the hierarchy is not kept (as it can't be represented)
  4407. - Mesh instances in the glTF file (i.e. same mesh linked from multiple nodes)
  4408. are turned into separate raylib Meshes
  4409. RESTRICTIONS:
  4410. - Only triangle meshes supported
  4411. - Vertex attribute types and formats supported:
  4412. > Vertices (position): vec3: float
  4413. > Normals: vec3: float
  4414. > Texcoords: vec2: float
  4415. > Colors: vec4: u8, u16, f32 (normalized)
  4416. > Indices: u16, u32 (truncated to u16)
  4417. - Scenes defined in the glTF file are ignored. All nodes in the file are used
  4418. ***********************************************************************************************/
  4419. // Macro to simplify attributes loading code
  4420. #define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType)
  4421. #define LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, dstType) \
  4422. { \
  4423. int n = 0; \
  4424. srcType *buffer = (srcType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(srcType) + accesor->offset/sizeof(srcType); \
  4425. for (unsigned int k = 0; k < accesor->count; k++) \
  4426. {\
  4427. for (int l = 0; l < numComp; l++) \
  4428. {\
  4429. dstPtr[numComp*k + l] = (dstType)buffer[n + l];\
  4430. }\
  4431. n += (int)(accesor->stride/sizeof(srcType));\
  4432. }\
  4433. }
  4434. Model model = { 0 };
  4435. // glTF file loading
  4436. int dataSize = 0;
  4437. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  4438. if (fileData == NULL) return model;
  4439. // glTF data loading
  4440. cgltf_options options = { 0 };
  4441. options.file.read = LoadFileGLTFCallback;
  4442. options.file.release = ReleaseFileGLTFCallback;
  4443. cgltf_data *data = NULL;
  4444. cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);
  4445. if (result == cgltf_result_success)
  4446. {
  4447. if (data->file_type == cgltf_file_type_glb) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glb) loaded successfully", fileName);
  4448. else if (data->file_type == cgltf_file_type_gltf) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glTF) loaded successfully", fileName);
  4449. else TRACELOG(LOG_WARNING, "MODEL: [%s] Model format not recognized", fileName);
  4450. TRACELOG(LOG_INFO, " > Meshes count: %i", data->meshes_count);
  4451. TRACELOG(LOG_INFO, " > Materials count: %i (+1 default)", data->materials_count);
  4452. TRACELOG(LOG_DEBUG, " > Buffers count: %i", data->buffers_count);
  4453. TRACELOG(LOG_DEBUG, " > Images count: %i", data->images_count);
  4454. TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count);
  4455. // Force reading data buffers (fills buffer_view->buffer->data)
  4456. // NOTE: If an uri is defined to base64 data or external path, it's automatically loaded
  4457. result = cgltf_load_buffers(&options, data, fileName);
  4458. if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName);
  4459. int primitivesCount = 0;
  4460. // NOTE: We will load every primitive in the glTF as a separate raylib Mesh
  4461. // Determine total number of meshes needed from the node hierarchy
  4462. for (unsigned int i = 0; i < data->nodes_count; i++)
  4463. {
  4464. cgltf_node *node = &(data->nodes[i]);
  4465. cgltf_mesh *mesh = node->mesh;
  4466. if (!mesh) continue;
  4467. for (unsigned int p = 0; p < mesh->primitives_count; p++)
  4468. {
  4469. if (mesh->primitives[p].type == cgltf_primitive_type_triangles) primitivesCount++;
  4470. }
  4471. }
  4472. TRACELOG(LOG_DEBUG, " > Primitives (triangles only) count based on hierarchy : %i", primitivesCount);
  4473. // Load our model data: meshes and materials
  4474. model.meshCount = primitivesCount;
  4475. model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  4476. // NOTE: We keep an extra slot for default material, in case some mesh requires it
  4477. model.materialCount = (int)data->materials_count + 1;
  4478. model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
  4479. model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)
  4480. // Load mesh-material indices, by default all meshes are mapped to material index: 0
  4481. model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  4482. // Load materials data
  4483. //----------------------------------------------------------------------------------------------------
  4484. for (unsigned int i = 0, j = 1; i < data->materials_count; i++, j++)
  4485. {
  4486. model.materials[j] = LoadMaterialDefault();
  4487. const char *texPath = GetDirectoryPath(fileName);
  4488. // Check glTF material flow: PBR metallic/roughness flow
  4489. // NOTE: Alternatively, materials can follow PBR specular/glossiness flow
  4490. if (data->materials[i].has_pbr_metallic_roughness)
  4491. {
  4492. // Load base color texture (albedo)
  4493. if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture)
  4494. {
  4495. Image imAlbedo = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath);
  4496. if (imAlbedo.data != NULL)
  4497. {
  4498. model.materials[j].maps[MATERIAL_MAP_ALBEDO].texture = LoadTextureFromImage(imAlbedo);
  4499. UnloadImage(imAlbedo);
  4500. }
  4501. }
  4502. // Load base color factor (tint)
  4503. model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255);
  4504. model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255);
  4505. model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255);
  4506. model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255);
  4507. // Load metallic/roughness texture
  4508. if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture)
  4509. {
  4510. Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath);
  4511. if (imMetallicRoughness.data != NULL)
  4512. {
  4513. Image imMetallic = { 0 };
  4514. Image imRoughness = { 0 };
  4515. imMetallic.data = RL_MALLOC(imMetallicRoughness.width*imMetallicRoughness.height);
  4516. imRoughness.data = RL_MALLOC(imMetallicRoughness.width*imMetallicRoughness.height);
  4517. imMetallic.width = imRoughness.width = imMetallicRoughness.width;
  4518. imMetallic.height = imRoughness.height = imMetallicRoughness.height;
  4519. imMetallic.format = imRoughness.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
  4520. imMetallic.mipmaps = imRoughness.mipmaps = 1;
  4521. for (int x = 0; x < imRoughness.width; x++)
  4522. {
  4523. for (int y = 0; y < imRoughness.height; y++)
  4524. {
  4525. Color color = GetImageColor(imMetallicRoughness, x, y);
  4526. ((unsigned char *)imRoughness.data)[y*imRoughness.width + x] = color.g; // Roughness color channel
  4527. ((unsigned char *)imMetallic.data)[y*imMetallic.width + x] = color.b; // Metallic color channel
  4528. }
  4529. }
  4530. model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imRoughness);
  4531. model.materials[j].maps[MATERIAL_MAP_METALNESS].texture = LoadTextureFromImage(imMetallic);
  4532. UnloadImage(imRoughness);
  4533. UnloadImage(imMetallic);
  4534. UnloadImage(imMetallicRoughness);
  4535. }
  4536. // Load metallic/roughness material properties
  4537. float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor;
  4538. model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].value = roughness;
  4539. float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor;
  4540. model.materials[j].maps[MATERIAL_MAP_METALNESS].value = metallic;
  4541. }
  4542. // Load normal texture
  4543. if (data->materials[i].normal_texture.texture)
  4544. {
  4545. Image imNormal = LoadImageFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath);
  4546. if (imNormal.data != NULL)
  4547. {
  4548. model.materials[j].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(imNormal);
  4549. UnloadImage(imNormal);
  4550. }
  4551. }
  4552. // Load ambient occlusion texture
  4553. if (data->materials[i].occlusion_texture.texture)
  4554. {
  4555. Image imOcclusion = LoadImageFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath);
  4556. if (imOcclusion.data != NULL)
  4557. {
  4558. model.materials[j].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(imOcclusion);
  4559. UnloadImage(imOcclusion);
  4560. }
  4561. }
  4562. // Load emissive texture
  4563. if (data->materials[i].emissive_texture.texture)
  4564. {
  4565. Image imEmissive = LoadImageFromCgltfImage(data->materials[i].emissive_texture.texture->image, texPath);
  4566. if (imEmissive.data != NULL)
  4567. {
  4568. model.materials[j].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(imEmissive);
  4569. UnloadImage(imEmissive);
  4570. }
  4571. // Load emissive color factor
  4572. model.materials[j].maps[MATERIAL_MAP_EMISSION].color.r = (unsigned char)(data->materials[i].emissive_factor[0]*255);
  4573. model.materials[j].maps[MATERIAL_MAP_EMISSION].color.g = (unsigned char)(data->materials[i].emissive_factor[1]*255);
  4574. model.materials[j].maps[MATERIAL_MAP_EMISSION].color.b = (unsigned char)(data->materials[i].emissive_factor[2]*255);
  4575. model.materials[j].maps[MATERIAL_MAP_EMISSION].color.a = 255;
  4576. }
  4577. }
  4578. // Other possible materials not supported by raylib pipeline:
  4579. // has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen
  4580. }
  4581. //----------------------------------------------------------------------------------------------------
  4582. // Load meshes data
  4583. //
  4584. // NOTE: Visit each node in the hierarchy and process any mesh linked from it
  4585. // - Each primitive within a glTF node becomes a raylib Mesh
  4586. // - The local-to-world transform of each node is used to transform the points/normals/tangents of the created Mesh(es)
  4587. // - Any glTF mesh linked from more than one Node (i.e. instancing) is turned into multiple Mesh's, as each Node will have its own transform applied
  4588. //
  4589. // WARNING: The code below disregards the scenes defined in the file, all nodes are used
  4590. //----------------------------------------------------------------------------------------------------
  4591. int meshIndex = 0;
  4592. for (unsigned int i = 0; i < data->nodes_count; i++)
  4593. {
  4594. cgltf_node *node = &(data->nodes[i]);
  4595. cgltf_mesh *mesh = node->mesh;
  4596. if (!mesh) continue;
  4597. cgltf_float worldTransform[16];
  4598. cgltf_node_transform_world(node, worldTransform);
  4599. Matrix worldMatrix = {
  4600. worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],
  4601. worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],
  4602. worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],
  4603. worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]
  4604. };
  4605. Matrix worldMatrixNormals = MatrixTranspose(MatrixInvert(worldMatrix));
  4606. for (unsigned int p = 0; p < mesh->primitives_count; p++)
  4607. {
  4608. // NOTE: We only support primitives defined by triangles
  4609. // Other alternatives: points, lines, line_strip, triangle_strip
  4610. if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
  4611. // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...),
  4612. // Only some formats for each attribute type are supported, read info at the top of this function!
  4613. for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
  4614. {
  4615. // Check the different attributes for every primitive
  4616. if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_position) // POSITION, vec3, float
  4617. {
  4618. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4619. // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined
  4620. if (model.meshes[meshIndex].vertices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data already loaded", fileName);
  4621. else
  4622. {
  4623. if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
  4624. {
  4625. // Init raylib mesh vertices to copy glTF attribute data
  4626. model.meshes[meshIndex].vertexCount = (int)attribute->count;
  4627. model.meshes[meshIndex].vertices = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
  4628. // Load 3 components of float data type into mesh.vertices
  4629. LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)
  4630. // Transform the vertices
  4631. float *vertices = model.meshes[meshIndex].vertices;
  4632. for (unsigned int k = 0; k < attribute->count; k++)
  4633. {
  4634. Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix);
  4635. vertices[3*k] = vt.x;
  4636. vertices[3*k+1] = vt.y;
  4637. vertices[3*k+2] = vt.z;
  4638. }
  4639. }
  4640. else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName);
  4641. }
  4642. }
  4643. else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float
  4644. {
  4645. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4646. if (model.meshes[meshIndex].normals != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data already loaded", fileName);
  4647. else
  4648. {
  4649. if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
  4650. {
  4651. // Init raylib mesh normals to copy glTF attribute data
  4652. model.meshes[meshIndex].normals = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
  4653. // Load 3 components of float data type into mesh.normals
  4654. LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)
  4655. // Transform the normals
  4656. float *normals = model.meshes[meshIndex].normals;
  4657. for (unsigned int k = 0; k < attribute->count; k++)
  4658. {
  4659. Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals);
  4660. normals[3*k] = nt.x;
  4661. normals[3*k+1] = nt.y;
  4662. normals[3*k+2] = nt.z;
  4663. }
  4664. }
  4665. else TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data format not supported, use vec3 float", fileName);
  4666. }
  4667. }
  4668. else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign
  4669. {
  4670. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4671. if (model.meshes[meshIndex].tangents != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data already loaded", fileName);
  4672. else
  4673. {
  4674. if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
  4675. {
  4676. // Init raylib mesh tangent to copy glTF attribute data
  4677. model.meshes[meshIndex].tangents = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
  4678. // Load 4 components of float data type into mesh.tangents
  4679. LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)
  4680. // Transform the tangents
  4681. float *tangents = model.meshes[meshIndex].tangents;
  4682. for (unsigned int k = 0; k < attribute->count; k++)
  4683. {
  4684. Vector3 tt = Vector3Transform((Vector3){ tangents[4*k], tangents[4*k+1], tangents[4*k+2] }, worldMatrix);
  4685. tangents[4*k] = tt.x;
  4686. tangents[4*k+1] = tt.y;
  4687. tangents[4*k+2] = tt.z;
  4688. }
  4689. }
  4690. else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data format not supported, use vec4 float", fileName);
  4691. }
  4692. }
  4693. else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_n, vec2, float/u8n/u16n
  4694. {
  4695. // Support up to 2 texture coordinates attributes
  4696. float *texcoordPtr = NULL;
  4697. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4698. if (attribute->type == cgltf_type_vec2)
  4699. {
  4700. if (attribute->component_type == cgltf_component_type_r_32f) // vec2, float
  4701. {
  4702. // Init raylib mesh texcoords to copy glTF attribute data
  4703. texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));
  4704. // Load 3 components of float data type into mesh.texcoords
  4705. LOAD_ATTRIBUTE(attribute, 2, float, texcoordPtr)
  4706. }
  4707. else if (attribute->component_type == cgltf_component_type_r_8u) // vec2, u8n
  4708. {
  4709. // Init raylib mesh texcoords to copy glTF attribute data
  4710. texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));
  4711. // Load data into a temp buffer to be converted to raylib data type
  4712. unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*2*sizeof(unsigned char));
  4713. LOAD_ATTRIBUTE(attribute, 2, unsigned char, temp);
  4714. // Convert data to raylib texcoord data type (float)
  4715. for (unsigned int t = 0; t < attribute->count*2; t++) texcoordPtr[t] = (float)temp[t]/255.0f;
  4716. RL_FREE(temp);
  4717. }
  4718. else if (attribute->component_type == cgltf_component_type_r_16u) // vec2, u16n
  4719. {
  4720. // Init raylib mesh texcoords to copy glTF attribute data
  4721. texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));
  4722. // Load data into a temp buffer to be converted to raylib data type
  4723. unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*2*sizeof(unsigned short));
  4724. LOAD_ATTRIBUTE(attribute, 2, unsigned short, temp);
  4725. // Convert data to raylib texcoord data type (float)
  4726. for (unsigned int t = 0; t < attribute->count*2; t++) texcoordPtr[t] = (float)temp[t]/65535.0f;
  4727. RL_FREE(temp);
  4728. }
  4729. else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported", fileName);
  4730. }
  4731. else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported, use vec2 float", fileName);
  4732. int index = mesh->primitives[p].attributes[j].index;
  4733. if (index == 0) model.meshes[meshIndex].texcoords = texcoordPtr;
  4734. else if (index == 1) model.meshes[meshIndex].texcoords2 = texcoordPtr;
  4735. else
  4736. {
  4737. TRACELOG(LOG_WARNING, "MODEL: [%s] No more than 2 texture coordinates attributes supported", fileName);
  4738. if (texcoordPtr != NULL) RL_FREE(texcoordPtr);
  4739. }
  4740. }
  4741. else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_n, vec3/vec4, float/u8n/u16n
  4742. {
  4743. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4744. // WARNING: SPECS: All components of each COLOR_n accessor element MUST be clamped to [0.0, 1.0] range
  4745. if (model.meshes[meshIndex].colors != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Colors attribute data already loaded", fileName);
  4746. else
  4747. {
  4748. if (attribute->type == cgltf_type_vec3) // RGB
  4749. {
  4750. if (attribute->component_type == cgltf_component_type_r_8u)
  4751. {
  4752. // Init raylib mesh color to copy glTF attribute data
  4753. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4754. // Load data into a temp buffer to be converted to raylib data type
  4755. unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*3*sizeof(unsigned char));
  4756. LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);
  4757. // Convert data to raylib color data type (4 bytes)
  4758. for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
  4759. {
  4760. model.meshes[meshIndex].colors[c] = temp[k];
  4761. model.meshes[meshIndex].colors[c + 1] = temp[k + 1];
  4762. model.meshes[meshIndex].colors[c + 2] = temp[k + 2];
  4763. model.meshes[meshIndex].colors[c + 3] = 255;
  4764. }
  4765. RL_FREE(temp);
  4766. }
  4767. else if (attribute->component_type == cgltf_component_type_r_16u)
  4768. {
  4769. // Init raylib mesh color to copy glTF attribute data
  4770. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4771. // Load data into a temp buffer to be converted to raylib data type
  4772. unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*3*sizeof(unsigned short));
  4773. LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);
  4774. // Convert data to raylib color data type (4 bytes)
  4775. for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
  4776. {
  4777. model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[k]/65535.0f)*255.0f);
  4778. model.meshes[meshIndex].colors[c + 1] = (unsigned char)(((float)temp[k + 1]/65535.0f)*255.0f);
  4779. model.meshes[meshIndex].colors[c + 2] = (unsigned char)(((float)temp[k + 2]/65535.0f)*255.0f);
  4780. model.meshes[meshIndex].colors[c + 3] = 255;
  4781. }
  4782. RL_FREE(temp);
  4783. }
  4784. else if (attribute->component_type == cgltf_component_type_r_32f)
  4785. {
  4786. // Init raylib mesh color to copy glTF attribute data
  4787. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4788. // Load data into a temp buffer to be converted to raylib data type
  4789. float *temp = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
  4790. LOAD_ATTRIBUTE(attribute, 3, float, temp);
  4791. // Convert data to raylib color data type (4 bytes)
  4792. for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
  4793. {
  4794. model.meshes[meshIndex].colors[c] = (unsigned char)(temp[k]*255.0f);
  4795. model.meshes[meshIndex].colors[c + 1] = (unsigned char)(temp[k + 1]*255.0f);
  4796. model.meshes[meshIndex].colors[c + 2] = (unsigned char)(temp[k + 2]*255.0f);
  4797. model.meshes[meshIndex].colors[c + 3] = 255;
  4798. }
  4799. RL_FREE(temp);
  4800. }
  4801. else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
  4802. }
  4803. else if (attribute->type == cgltf_type_vec4) // RGBA
  4804. {
  4805. if (attribute->component_type == cgltf_component_type_r_8u)
  4806. {
  4807. // Init raylib mesh color to copy glTF attribute data
  4808. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4809. // Load 4 components of unsigned char data type into mesh.colors
  4810. LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
  4811. }
  4812. else if (attribute->component_type == cgltf_component_type_r_16u)
  4813. {
  4814. // Init raylib mesh color to copy glTF attribute data
  4815. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4816. // Load data into a temp buffer to be converted to raylib data type
  4817. unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
  4818. LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
  4819. // Convert data to raylib color data type (4 bytes)
  4820. for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f);
  4821. RL_FREE(temp);
  4822. }
  4823. else if (attribute->component_type == cgltf_component_type_r_32f)
  4824. {
  4825. // Init raylib mesh color to copy glTF attribute data
  4826. model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4827. // Load data into a temp buffer to be converted to raylib data type
  4828. float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
  4829. LOAD_ATTRIBUTE(attribute, 4, float, temp);
  4830. // Convert data to raylib color data type (4 bytes), we expect the color data normalized
  4831. for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);
  4832. RL_FREE(temp);
  4833. }
  4834. else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
  4835. }
  4836. else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
  4837. }
  4838. }
  4839. // NOTE: Attributes related to animations data are processed after mesh data loading
  4840. }
  4841. // Load primitive indices data (if provided)
  4842. if ((mesh->primitives[p].indices != NULL) && (mesh->primitives[p].indices->buffer_view != NULL))
  4843. {
  4844. cgltf_accessor *attribute = mesh->primitives[p].indices;
  4845. model.meshes[meshIndex].triangleCount = (int)attribute->count/3;
  4846. if (model.meshes[meshIndex].indices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Indices attribute data already loaded", fileName);
  4847. else
  4848. {
  4849. if (attribute->component_type == cgltf_component_type_r_16u)
  4850. {
  4851. // Init raylib mesh indices to copy glTF attribute data
  4852. model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
  4853. // Load unsigned short data type into mesh.indices
  4854. LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)
  4855. }
  4856. else if (attribute->component_type == cgltf_component_type_r_8u)
  4857. {
  4858. // Init raylib mesh indices to copy glTF attribute data
  4859. model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
  4860. LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
  4861. }
  4862. else if (attribute->component_type == cgltf_component_type_r_32u)
  4863. {
  4864. // Init raylib mesh indices to copy glTF attribute data
  4865. model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
  4866. LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
  4867. TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
  4868. }
  4869. else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
  4870. }
  4871. }
  4872. else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh
  4873. // Assign to the primitive mesh the corresponding material index
  4874. // NOTE: If no material defined, mesh uses the already assigned default material (index: 0)
  4875. for (unsigned int m = 0; m < data->materials_count; m++)
  4876. {
  4877. // The primitive actually keeps the pointer to the corresponding material,
  4878. // raylib instead assigns to the mesh the by its index, as loaded in model.materials array
  4879. // To get the index, we check if material pointers match, and we assign the corresponding index,
  4880. // skipping index 0, the default material
  4881. if (&data->materials[m] == mesh->primitives[p].material)
  4882. {
  4883. model.meshMaterial[meshIndex] = m + 1;
  4884. break;
  4885. }
  4886. }
  4887. meshIndex++; // Move to next mesh
  4888. }
  4889. }
  4890. //----------------------------------------------------------------------------------------------------
  4891. // Load animation data
  4892. // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins
  4893. // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
  4894. //
  4895. // LIMITATIONS:
  4896. // - Only supports 1 armature per file, and skips loading it if there are multiple armatures
  4897. // - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file)
  4898. // - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets)
  4899. //----------------------------------------------------------------------------------------------------
  4900. if (data->skins_count > 0)
  4901. {
  4902. cgltf_skin skin = data->skins[0];
  4903. model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
  4904. model.bindPose = (Transform *)RL_MALLOC(model.boneCount*sizeof(Transform));
  4905. for (int i = 0; i < model.boneCount; i++)
  4906. {
  4907. cgltf_node *node = skin.joints[i];
  4908. cgltf_float worldTransform[16];
  4909. cgltf_node_transform_world(node, worldTransform);
  4910. Matrix worldMatrix = {
  4911. worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],
  4912. worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],
  4913. worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],
  4914. worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]
  4915. };
  4916. MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
  4917. }
  4918. if (data->skins_count > 1) TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
  4919. }
  4920. meshIndex = 0;
  4921. for (unsigned int i = 0; i < data->nodes_count; i++)
  4922. {
  4923. cgltf_node *node = &(data->nodes[i]);
  4924. cgltf_mesh *mesh = node->mesh;
  4925. if (!mesh) continue;
  4926. for (unsigned int p = 0; p < mesh->primitives_count; p++)
  4927. {
  4928. bool hasJoints = false;
  4929. // NOTE: We only support primitives defined by triangles
  4930. if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
  4931. for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
  4932. {
  4933. // NOTE: JOINTS_1 + WEIGHT_1 will be used for +4 joints influencing a vertex -> Not supported by raylib
  4934. if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints) // JOINTS_n (vec4: 4 bones max per vertex / u8, u16)
  4935. {
  4936. hasJoints = true;
  4937. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4938. // NOTE: JOINTS_n can only be vec4 and u8/u16
  4939. // SPECS: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview
  4940. // WARNING: raylib only supports model.meshes[].boneIds as u8 (unsigned char),
  4941. // if data is provided in any other format, it is converted to supported format but
  4942. // it could imply data loss (a warning message is issued in that case)
  4943. if (attribute->type == cgltf_type_vec4)
  4944. {
  4945. if (attribute->component_type == cgltf_component_type_r_8u)
  4946. {
  4947. // Init raylib mesh boneIds to copy glTF attribute data
  4948. model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
  4949. // Load attribute: vec4, u8 (unsigned char)
  4950. LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)
  4951. }
  4952. else if (attribute->component_type == cgltf_component_type_r_16u)
  4953. {
  4954. // Init raylib mesh boneIds to copy glTF attribute data
  4955. model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
  4956. // Load data into a temp buffer to be converted to raylib data type
  4957. unsigned short *temp = (unsigned short *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned short));
  4958. LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
  4959. // Convert data to raylib color data type (4 bytes)
  4960. bool boneIdOverflowWarning = false;
  4961. for (int b = 0; b < model.meshes[meshIndex].vertexCount*4; b++)
  4962. {
  4963. if ((temp[b] > 255) && !boneIdOverflowWarning)
  4964. {
  4965. TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format (u16) overflow", fileName);
  4966. boneIdOverflowWarning = true;
  4967. }
  4968. // Despite the possible overflow, we convert data to unsigned char
  4969. model.meshes[meshIndex].boneIds[b] = (unsigned char)temp[b];
  4970. }
  4971. RL_FREE(temp);
  4972. }
  4973. else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);
  4974. }
  4975. else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);
  4976. }
  4977. else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4, u8n/u16n/f32)
  4978. {
  4979. cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
  4980. if (attribute->type == cgltf_type_vec4)
  4981. {
  4982. if (attribute->component_type == cgltf_component_type_r_8u)
  4983. {
  4984. // Init raylib mesh bone weight to copy glTF attribute data
  4985. model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
  4986. // Load data into a temp buffer to be converted to raylib data type
  4987. unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
  4988. LOAD_ATTRIBUTE(attribute, 4, unsigned char, temp);
  4989. // Convert data to raylib bone weight data type (4 bytes)
  4990. for (unsigned int b = 0; b < attribute->count*4; b++) model.meshes[meshIndex].boneWeights[b] = (float)temp[b]/255.0f;
  4991. RL_FREE(temp);
  4992. }
  4993. else if (attribute->component_type == cgltf_component_type_r_16u)
  4994. {
  4995. // Init raylib mesh bone weight to copy glTF attribute data
  4996. model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
  4997. // Load data into a temp buffer to be converted to raylib data type
  4998. unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
  4999. LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
  5000. // Convert data to raylib bone weight data type
  5001. for (unsigned int b = 0; b < attribute->count*4; b++) model.meshes[meshIndex].boneWeights[b] = (float)temp[b]/65535.0f;
  5002. RL_FREE(temp);
  5003. }
  5004. else if (attribute->component_type == cgltf_component_type_r_32f)
  5005. {
  5006. // Init raylib mesh bone weight to copy glTF attribute data
  5007. model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
  5008. // Load 4 components of float data type into mesh.boneWeights
  5009. // for cgltf_attribute_type_weights we have:
  5010. // - data.meshes[0] (256 vertices)
  5011. // - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)
  5012. LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)
  5013. }
  5014. else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint weight attribute data format not supported, use vec4 float", fileName);
  5015. }
  5016. else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint weight attribute data format not supported, use vec4 float", fileName);
  5017. }
  5018. }
  5019. // Check if we are animated, and the mesh was not given any bone assignments, but is the child of a bone node
  5020. // in this case we need to fully attach all the verts to the parent bone so it will animate with the bone
  5021. if (data->skins_count > 0 && !hasJoints && node->parent != NULL && node->parent->mesh == NULL)
  5022. {
  5023. int parentBoneId = -1;
  5024. for (int joint = 0; joint < model.boneCount; joint++)
  5025. {
  5026. if (data->skins[0].joints[joint] == node->parent)
  5027. {
  5028. parentBoneId = joint;
  5029. break;
  5030. }
  5031. }
  5032. if (parentBoneId >= 0)
  5033. {
  5034. model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
  5035. model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
  5036. for (int vertexIndex = 0; vertexIndex < model.meshes[meshIndex].vertexCount*4; vertexIndex += 4)
  5037. {
  5038. model.meshes[meshIndex].boneIds[vertexIndex] = (unsigned char)parentBoneId;
  5039. model.meshes[meshIndex].boneWeights[vertexIndex] = 1.0f;
  5040. }
  5041. }
  5042. }
  5043. // Animated vertex data
  5044. model.meshes[meshIndex].animVertices = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
  5045. memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));
  5046. model.meshes[meshIndex].animNormals = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
  5047. if (model.meshes[meshIndex].normals != NULL)
  5048. {
  5049. memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));
  5050. }
  5051. // Bone Transform Matrices
  5052. model.meshes[meshIndex].boneCount = model.boneCount;
  5053. model.meshes[meshIndex].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
  5054. for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
  5055. {
  5056. model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity();
  5057. }
  5058. meshIndex++; // Move to next mesh
  5059. }
  5060. }
  5061. //----------------------------------------------------------------------------------------------------
  5062. // Free all cgltf loaded data
  5063. cgltf_free(data);
  5064. }
  5065. else TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);
  5066. // WARNING: cgltf requires the file pointer available while reading data
  5067. UnloadFileData(fileData);
  5068. return model;
  5069. }
  5070. // Get interpolated pose for bone sampler at a specific time. Returns true on success
  5071. static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_accessor *input, cgltf_accessor *output, float time, void *data)
  5072. {
  5073. if (interpolationType >= cgltf_interpolation_type_max_enum) return false;
  5074. // Input and output should have the same count
  5075. float tstart = 0.0f;
  5076. float tend = 0.0f;
  5077. int keyframe = 0; // Defaults to first pose
  5078. for (int i = 0; i < (int)input->count - 1; i++)
  5079. {
  5080. cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);
  5081. if (!r1) return false;
  5082. cgltf_bool r2 = cgltf_accessor_read_float(input, i + 1, &tend, 1);
  5083. if (!r2) return false;
  5084. if ((tstart <= time) && (time < tend))
  5085. {
  5086. keyframe = i;
  5087. break;
  5088. }
  5089. }
  5090. // Constant animation, no need to interpolate
  5091. if (FloatEquals(tend, tstart)) return true;
  5092. float duration = fmaxf((tend - tstart), EPSILON);
  5093. float t = (time - tstart)/duration;
  5094. t = (t < 0.0f)? 0.0f : t;
  5095. t = (t > 1.0f)? 1.0f : t;
  5096. if (output->component_type != cgltf_component_type_r_32f) return false;
  5097. if (output->type == cgltf_type_vec3)
  5098. {
  5099. switch (interpolationType)
  5100. {
  5101. case cgltf_interpolation_type_step:
  5102. {
  5103. float tmp[3] = { 0.0f };
  5104. cgltf_accessor_read_float(output, keyframe, tmp, 3);
  5105. Vector3 v1 = {tmp[0], tmp[1], tmp[2]};
  5106. Vector3 *r = data;
  5107. *r = v1;
  5108. } break;
  5109. case cgltf_interpolation_type_linear:
  5110. {
  5111. float tmp[3] = { 0.0f };
  5112. cgltf_accessor_read_float(output, keyframe, tmp, 3);
  5113. Vector3 v1 = {tmp[0], tmp[1], tmp[2]};
  5114. cgltf_accessor_read_float(output, keyframe+1, tmp, 3);
  5115. Vector3 v2 = {tmp[0], tmp[1], tmp[2]};
  5116. Vector3 *r = data;
  5117. *r = Vector3Lerp(v1, v2, t);
  5118. } break;
  5119. case cgltf_interpolation_type_cubic_spline:
  5120. {
  5121. float tmp[3] = { 0.0f };
  5122. cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 3);
  5123. Vector3 v1 = {tmp[0], tmp[1], tmp[2]};
  5124. cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 3);
  5125. Vector3 tangent1 = {tmp[0], tmp[1], tmp[2]};
  5126. cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 3);
  5127. Vector3 v2 = {tmp[0], tmp[1], tmp[2]};
  5128. cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 3);
  5129. Vector3 tangent2 = {tmp[0], tmp[1], tmp[2]};
  5130. Vector3 *r = data;
  5131. *r = Vector3CubicHermite(v1, tangent1, v2, tangent2, t);
  5132. } break;
  5133. default: break;
  5134. }
  5135. }
  5136. else if (output->type == cgltf_type_vec4)
  5137. {
  5138. // Only v4 is for rotations, so we know it's a quaternion
  5139. switch (interpolationType)
  5140. {
  5141. case cgltf_interpolation_type_step:
  5142. {
  5143. float tmp[4] = { 0.0f };
  5144. cgltf_accessor_read_float(output, keyframe, tmp, 4);
  5145. Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};
  5146. Vector4 *r = data;
  5147. *r = v1;
  5148. } break;
  5149. case cgltf_interpolation_type_linear:
  5150. {
  5151. float tmp[4] = { 0.0f };
  5152. cgltf_accessor_read_float(output, keyframe, tmp, 4);
  5153. Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};
  5154. cgltf_accessor_read_float(output, keyframe+1, tmp, 4);
  5155. Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
  5156. Vector4 *r = data;
  5157. *r = QuaternionSlerp(v1, v2, t);
  5158. } break;
  5159. case cgltf_interpolation_type_cubic_spline:
  5160. {
  5161. float tmp[4] = { 0.0f };
  5162. cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 4);
  5163. Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};
  5164. cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 4);
  5165. Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2], 0.0f};
  5166. cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 4);
  5167. Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
  5168. cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 4);
  5169. Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2], 0.0f};
  5170. Vector4 *r = data;
  5171. v1 = QuaternionNormalize(v1);
  5172. v2 = QuaternionNormalize(v2);
  5173. if (Vector4DotProduct(v1, v2) < 0.0f)
  5174. {
  5175. v2 = Vector4Negate(v2);
  5176. }
  5177. outTangent1 = Vector4Scale(outTangent1, duration);
  5178. inTangent2 = Vector4Scale(inTangent2, duration);
  5179. *r = QuaternionCubicHermiteSpline(v1, outTangent1, v2, inTangent2, t);
  5180. } break;
  5181. default: break;
  5182. }
  5183. }
  5184. return true;
  5185. }
  5186. #define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
  5187. static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)
  5188. {
  5189. // glTF file loading
  5190. int dataSize = 0;
  5191. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  5192. ModelAnimation *animations = NULL;
  5193. // glTF data loading
  5194. cgltf_options options = { 0 };
  5195. options.file.read = LoadFileGLTFCallback;
  5196. options.file.release = ReleaseFileGLTFCallback;
  5197. cgltf_data *data = NULL;
  5198. cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);
  5199. if (result != cgltf_result_success)
  5200. {
  5201. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);
  5202. *animCount = 0;
  5203. return NULL;
  5204. }
  5205. result = cgltf_load_buffers(&options, data, fileName);
  5206. if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load animation buffers", fileName);
  5207. if (result == cgltf_result_success)
  5208. {
  5209. if (data->skins_count > 0)
  5210. {
  5211. cgltf_skin skin = data->skins[0];
  5212. *animCount = (int)data->animations_count;
  5213. animations = (ModelAnimation *)RL_CALLOC(data->animations_count, sizeof(ModelAnimation));
  5214. Transform worldTransform = { 0 };
  5215. cgltf_float cgltf_worldTransform[16] = { 0 };
  5216. cgltf_node *node = skin.joints[0];
  5217. cgltf_node_transform_world(node->parent, cgltf_worldTransform);
  5218. Matrix worldMatrix = {
  5219. cgltf_worldTransform[0], cgltf_worldTransform[4], cgltf_worldTransform[8], cgltf_worldTransform[12],
  5220. cgltf_worldTransform[1], cgltf_worldTransform[5], cgltf_worldTransform[9], cgltf_worldTransform[13],
  5221. cgltf_worldTransform[2], cgltf_worldTransform[6], cgltf_worldTransform[10], cgltf_worldTransform[14],
  5222. cgltf_worldTransform[3], cgltf_worldTransform[7], cgltf_worldTransform[11], cgltf_worldTransform[15]
  5223. };
  5224. MatrixDecompose(worldMatrix, &worldTransform.translation, &worldTransform.rotation, &worldTransform.scale);
  5225. for (unsigned int i = 0; i < data->animations_count; i++)
  5226. {
  5227. animations[i].bones = LoadBoneInfoGLTF(skin, &animations[i].boneCount);
  5228. cgltf_animation animData = data->animations[i];
  5229. struct Channels {
  5230. cgltf_animation_channel *translate;
  5231. cgltf_animation_channel *rotate;
  5232. cgltf_animation_channel *scale;
  5233. cgltf_interpolation_type interpolationType;
  5234. };
  5235. struct Channels *boneChannels = (struct Channels *)RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));
  5236. float animDuration = 0.0f;
  5237. for (unsigned int j = 0; j < animData.channels_count; j++)
  5238. {
  5239. cgltf_animation_channel channel = animData.channels[j];
  5240. int boneIndex = -1;
  5241. for (unsigned int k = 0; k < skin.joints_count; k++)
  5242. {
  5243. if (animData.channels[j].target_node == skin.joints[k])
  5244. {
  5245. boneIndex = k;
  5246. break;
  5247. }
  5248. }
  5249. if (boneIndex == -1)
  5250. {
  5251. // Animation channel for a node not in the armature
  5252. continue;
  5253. }
  5254. boneChannels[boneIndex].interpolationType = animData.channels[j].sampler->interpolation;
  5255. if (animData.channels[j].sampler->interpolation != cgltf_interpolation_type_max_enum)
  5256. {
  5257. if (channel.target_path == cgltf_animation_path_type_translation)
  5258. {
  5259. boneChannels[boneIndex].translate = &animData.channels[j];
  5260. }
  5261. else if (channel.target_path == cgltf_animation_path_type_rotation)
  5262. {
  5263. boneChannels[boneIndex].rotate = &animData.channels[j];
  5264. }
  5265. else if (channel.target_path == cgltf_animation_path_type_scale)
  5266. {
  5267. boneChannels[boneIndex].scale = &animData.channels[j];
  5268. }
  5269. else
  5270. {
  5271. TRACELOG(LOG_WARNING, "MODEL: [%s] Unsupported target_path on channel %d's sampler for animation %d. Skipping.", fileName, j, i);
  5272. }
  5273. }
  5274. else TRACELOG(LOG_WARNING, "MODEL: [%s] Invalid interpolation curve encountered for GLTF animation.", fileName);
  5275. float t = 0.0f;
  5276. cgltf_bool r = cgltf_accessor_read_float(channel.sampler->input, channel.sampler->input->count - 1, &t, 1);
  5277. if (!r)
  5278. {
  5279. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load input time", fileName);
  5280. continue;
  5281. }
  5282. animDuration = (t > animDuration)? t : animDuration;
  5283. }
  5284. if (animData.name != NULL) strncpy(animations[i].name, animData.name, sizeof(animations[i].name) - 1);
  5285. animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY) + 1;
  5286. animations[i].framePoses = (Transform **)RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
  5287. for (int j = 0; j < animations[i].frameCount; j++)
  5288. {
  5289. animations[i].framePoses[j] = (Transform *)RL_MALLOC(animations[i].boneCount*sizeof(Transform));
  5290. float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;
  5291. for (int k = 0; k < animations[i].boneCount; k++)
  5292. {
  5293. Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
  5294. Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
  5295. Vector3 scale = {skin.joints[k]->scale[0], skin.joints[k]->scale[1], skin.joints[k]->scale[2]};
  5296. if (boneChannels[k].translate)
  5297. {
  5298. if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))
  5299. {
  5300. TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load translate pose data for bone %s", fileName, animations[i].bones[k].name);
  5301. }
  5302. }
  5303. if (boneChannels[k].rotate)
  5304. {
  5305. if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].rotate->sampler->input, boneChannels[k].rotate->sampler->output, time, &rotation))
  5306. {
  5307. TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load rotate pose data for bone %s", fileName, animations[i].bones[k].name);
  5308. }
  5309. }
  5310. if (boneChannels[k].scale)
  5311. {
  5312. if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].scale->sampler->input, boneChannels[k].scale->sampler->output, time, &scale))
  5313. {
  5314. TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load scale pose data for bone %s", fileName, animations[i].bones[k].name);
  5315. }
  5316. }
  5317. animations[i].framePoses[j][k] = (Transform){
  5318. .translation = translation,
  5319. .rotation = rotation,
  5320. .scale = scale
  5321. };
  5322. }
  5323. Transform* root = &animations[i].framePoses[j][0];
  5324. root->rotation = QuaternionMultiply(worldTransform.rotation, root->rotation);
  5325. root->scale = Vector3Multiply(root->scale, worldTransform.scale);
  5326. root->translation = Vector3Multiply(root->translation, worldTransform.scale);
  5327. root->translation = Vector3RotateByQuaternion(root->translation, worldTransform.rotation);
  5328. root->translation = Vector3Add(root->translation, worldTransform.translation);
  5329. BuildPoseFromParentJoints(animations[i].bones, animations[i].boneCount, animations[i].framePoses[j]);
  5330. }
  5331. TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s (%d frames, %fs)", fileName, (animData.name != NULL)? animData.name : "NULL", animations[i].frameCount, animDuration);
  5332. RL_FREE(boneChannels);
  5333. }
  5334. }
  5335. if (data->skins_count > 1)
  5336. {
  5337. TRACELOG(LOG_WARNING, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
  5338. }
  5339. cgltf_free(data);
  5340. }
  5341. UnloadFileData(fileData);
  5342. return animations;
  5343. }
  5344. #endif
  5345. #if defined(SUPPORT_FILEFORMAT_VOX)
  5346. // Load VOX (MagicaVoxel) mesh data
  5347. static Model LoadVOX(const char *fileName)
  5348. {
  5349. Model model = { 0 };
  5350. int nbvertices = 0;
  5351. int meshescount = 0;
  5352. // Read vox file into buffer
  5353. int dataSize = 0;
  5354. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  5355. if (fileData == 0)
  5356. {
  5357. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
  5358. return model;
  5359. }
  5360. // Read and build voxarray description
  5361. VoxArray3D voxarray = { 0 };
  5362. int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);
  5363. if (ret != VOX_SUCCESS)
  5364. {
  5365. // Error
  5366. UnloadFileData(fileData);
  5367. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName);
  5368. return model;
  5369. }
  5370. else
  5371. {
  5372. // Success: Compute meshes count
  5373. nbvertices = voxarray.vertices.used;
  5374. meshescount = 1 + (nbvertices/65536);
  5375. TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount);
  5376. }
  5377. // Build models from meshes
  5378. model.transform = MatrixIdentity();
  5379. model.meshCount = meshescount;
  5380. model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  5381. model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  5382. model.materialCount = 1;
  5383. model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
  5384. model.materials[0] = LoadMaterialDefault();
  5385. // Init model meshes
  5386. int verticesRemain = voxarray.vertices.used;
  5387. int verticesMax = 65532; // 5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536)
  5388. // 6*4 = 12 vertices per voxel
  5389. Vector3 *pvertices = (Vector3 *)voxarray.vertices.array;
  5390. Vector3 *pnormals = (Vector3 *)voxarray.normals.array;
  5391. Color *pcolors = (Color *)voxarray.colors.array;
  5392. unsigned short *pindices = voxarray.indices.array; // 5461*6*6 = 196596 indices max per mesh
  5393. int size = 0;
  5394. for (int i = 0; i < meshescount; i++)
  5395. {
  5396. Mesh *pmesh = &model.meshes[i];
  5397. memset(pmesh, 0, sizeof(Mesh));
  5398. // Copy vertices
  5399. pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain);
  5400. size = pmesh->vertexCount*sizeof(float)*3;
  5401. pmesh->vertices = (float *)RL_MALLOC(size);
  5402. memcpy(pmesh->vertices, pvertices, size);
  5403. // Copy normals
  5404. pmesh->normals = (float *)RL_MALLOC(size);
  5405. memcpy(pmesh->normals, pnormals, size);
  5406. // Copy indices
  5407. size = voxarray.indices.used*sizeof(unsigned short);
  5408. pmesh->indices = (unsigned short *)RL_MALLOC(size);
  5409. memcpy(pmesh->indices, pindices, size);
  5410. pmesh->triangleCount = (pmesh->vertexCount/4)*2;
  5411. // Copy colors
  5412. size = pmesh->vertexCount*sizeof(Color);
  5413. pmesh->colors = (unsigned char *)RL_MALLOC(size);
  5414. memcpy(pmesh->colors, pcolors, size);
  5415. // First material index
  5416. model.meshMaterial[i] = 0;
  5417. verticesRemain -= verticesMax;
  5418. pvertices += verticesMax;
  5419. pnormals += verticesMax;
  5420. pcolors += verticesMax;
  5421. }
  5422. // Free buffers
  5423. Vox_FreeArrays(&voxarray);
  5424. UnloadFileData(fileData);
  5425. return model;
  5426. }
  5427. #endif
  5428. #if defined(SUPPORT_FILEFORMAT_M3D)
  5429. // Hook LoadFileData()/UnloadFileData() calls to M3D loaders
  5430. unsigned char *m3d_loaderhook(char *fn, unsigned int *len) { return LoadFileData((const char *)fn, (int *)len); }
  5431. void m3d_freehook(void *data) { UnloadFileData((unsigned char *)data); }
  5432. // Load M3D mesh data
  5433. static Model LoadM3D(const char *fileName)
  5434. {
  5435. Model model = { 0 };
  5436. m3d_t *m3d = NULL;
  5437. m3dp_t *prop = NULL;
  5438. int i, j, k, l, n, mi = -2, vcolor = 0;
  5439. int dataSize = 0;
  5440. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  5441. if (fileData != NULL)
  5442. {
  5443. m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
  5444. if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
  5445. {
  5446. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);
  5447. if (m3d) m3d_free(m3d);
  5448. UnloadFileData(fileData);
  5449. return model;
  5450. }
  5451. else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i faces/%i materials", fileName, m3d->numface, m3d->nummaterial);
  5452. // no face? this is probably just a material library
  5453. if (!m3d->numface)
  5454. {
  5455. m3d_free(m3d);
  5456. UnloadFileData(fileData);
  5457. return model;
  5458. }
  5459. if (m3d->nummaterial > 0)
  5460. {
  5461. model.meshCount = model.materialCount = m3d->nummaterial;
  5462. TRACELOG(LOG_INFO, "MODEL: model has %i material meshes", model.materialCount);
  5463. }
  5464. else
  5465. {
  5466. model.meshCount = 1; model.materialCount = 0;
  5467. TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
  5468. }
  5469. // We always need a default material, so we add +1
  5470. model.materialCount++;
  5471. // Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise
  5472. // WARNING: Sorting is not needed, valid M3D model files should already be sorted
  5473. // Just keeping the sorting function for reference (Check PR #3363 #3385)
  5474. /*
  5475. for (i = 1; i < m3d->numface; i++)
  5476. {
  5477. if (m3d->face[i-1].materialid <= m3d->face[i].materialid) continue;
  5478. // face[i-1] > face[i]. slide face[i] lower
  5479. m3df_t slider = m3d->face[i];
  5480. j = i-1;
  5481. do
  5482. { // face[j] > slider, face[j+1] is svailable vacant gap
  5483. m3d->face[j+1] = m3d->face[j];
  5484. j = j-1;
  5485. }
  5486. while (j >= 0 && m3d->face[j].materialid > slider.materialid);
  5487. m3d->face[j+1] = slider;
  5488. }
  5489. */
  5490. model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  5491. model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  5492. model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
  5493. // Map no material to index 0 with default shader, everything else materialid + 1
  5494. model.materials[0] = LoadMaterialDefault();
  5495. for (i = l = 0, k = -1; i < (int)m3d->numface; i++, l++)
  5496. {
  5497. // Materials are grouped together
  5498. if (mi != m3d->face[i].materialid)
  5499. {
  5500. // There should be only one material switch per material kind,
  5501. // but be bulletproof for non-optimal model files
  5502. if (k + 1 >= model.meshCount)
  5503. {
  5504. model.meshCount++;
  5505. // Create a second buffer for mesh re-allocation
  5506. Mesh *tempMeshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
  5507. memcpy(tempMeshes, model.meshes, (model.meshCount - 1)*sizeof(Mesh));
  5508. RL_FREE(model.meshes);
  5509. model.meshes = tempMeshes;
  5510. // Create a second buffer for material re-allocation
  5511. int *tempMeshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
  5512. memcpy(tempMeshMaterial, model.meshMaterial, (model.meshCount - 1)*sizeof(int));
  5513. RL_FREE(model.meshMaterial);
  5514. model.meshMaterial = tempMeshMaterial;
  5515. }
  5516. k++;
  5517. mi = m3d->face[i].materialid;
  5518. // Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
  5519. // if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors
  5520. for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
  5521. {
  5522. if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
  5523. !m3d->vertex[m3d->face[j].vertex[1]].color ||
  5524. !m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;
  5525. }
  5526. model.meshes[k].vertexCount = l*3;
  5527. model.meshes[k].triangleCount = l;
  5528. model.meshes[k].vertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
  5529. model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
  5530. model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
  5531. // If no map is provided, or we have colors defined, we allocate storage for vertex colors
  5532. // M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
  5533. if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
  5534. // If no map is provided and we allocated vertex colors, set them to white
  5535. if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))
  5536. {
  5537. for (int c = 0; c < model.meshes[k].vertexCount*4; c++) model.meshes[k].colors[c] = 255;
  5538. }
  5539. if (m3d->numbone && m3d->numskin)
  5540. {
  5541. model.meshes[k].boneIds = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
  5542. model.meshes[k].boneWeights = (float *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(float));
  5543. model.meshes[k].animVertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
  5544. model.meshes[k].animNormals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
  5545. }
  5546. model.meshMaterial[k] = mi + 1;
  5547. l = 0;
  5548. }
  5549. // Process meshes per material, add triangles
  5550. model.meshes[k].vertices[l*9 + 0] = m3d->vertex[m3d->face[i].vertex[0]].x*m3d->scale;
  5551. model.meshes[k].vertices[l*9 + 1] = m3d->vertex[m3d->face[i].vertex[0]].y*m3d->scale;
  5552. model.meshes[k].vertices[l*9 + 2] = m3d->vertex[m3d->face[i].vertex[0]].z*m3d->scale;
  5553. model.meshes[k].vertices[l*9 + 3] = m3d->vertex[m3d->face[i].vertex[1]].x*m3d->scale;
  5554. model.meshes[k].vertices[l*9 + 4] = m3d->vertex[m3d->face[i].vertex[1]].y*m3d->scale;
  5555. model.meshes[k].vertices[l*9 + 5] = m3d->vertex[m3d->face[i].vertex[1]].z*m3d->scale;
  5556. model.meshes[k].vertices[l*9 + 6] = m3d->vertex[m3d->face[i].vertex[2]].x*m3d->scale;
  5557. model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
  5558. model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
  5559. // Without vertex color (full transparency), we use the default color
  5560. if (model.meshes[k].colors != NULL)
  5561. {
  5562. if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xff000000)
  5563. memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);
  5564. if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xff000000)
  5565. memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);
  5566. if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xff000000)
  5567. memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);
  5568. }
  5569. if (m3d->face[i].texcoord[0] != M3D_UNDEF)
  5570. {
  5571. model.meshes[k].texcoords[l*6 + 0] = m3d->tmap[m3d->face[i].texcoord[0]].u;
  5572. model.meshes[k].texcoords[l*6 + 1] = 1.0f - m3d->tmap[m3d->face[i].texcoord[0]].v;
  5573. model.meshes[k].texcoords[l*6 + 2] = m3d->tmap[m3d->face[i].texcoord[1]].u;
  5574. model.meshes[k].texcoords[l*6 + 3] = 1.0f - m3d->tmap[m3d->face[i].texcoord[1]].v;
  5575. model.meshes[k].texcoords[l*6 + 4] = m3d->tmap[m3d->face[i].texcoord[2]].u;
  5576. model.meshes[k].texcoords[l*6 + 5] = 1.0f - m3d->tmap[m3d->face[i].texcoord[2]].v;
  5577. }
  5578. if (m3d->face[i].normal[0] != M3D_UNDEF)
  5579. {
  5580. model.meshes[k].normals[l*9 + 0] = m3d->vertex[m3d->face[i].normal[0]].x;
  5581. model.meshes[k].normals[l*9 + 1] = m3d->vertex[m3d->face[i].normal[0]].y;
  5582. model.meshes[k].normals[l*9 + 2] = m3d->vertex[m3d->face[i].normal[0]].z;
  5583. model.meshes[k].normals[l*9 + 3] = m3d->vertex[m3d->face[i].normal[1]].x;
  5584. model.meshes[k].normals[l*9 + 4] = m3d->vertex[m3d->face[i].normal[1]].y;
  5585. model.meshes[k].normals[l*9 + 5] = m3d->vertex[m3d->face[i].normal[1]].z;
  5586. model.meshes[k].normals[l*9 + 6] = m3d->vertex[m3d->face[i].normal[2]].x;
  5587. model.meshes[k].normals[l*9 + 7] = m3d->vertex[m3d->face[i].normal[2]].y;
  5588. model.meshes[k].normals[l*9 + 8] = m3d->vertex[m3d->face[i].normal[2]].z;
  5589. }
  5590. // Add skin (vertex / bone weight pairs)
  5591. if (m3d->numbone && m3d->numskin)
  5592. {
  5593. for (n = 0; n < 3; n++)
  5594. {
  5595. int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;
  5596. // Check if there is a skin for this mesh, should be, just failsafe
  5597. if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin))
  5598. {
  5599. for (j = 0; j < 4; j++)
  5600. {
  5601. model.meshes[k].boneIds[l*12 + n*4 + j] = m3d->skin[skinid].boneid[j];
  5602. model.meshes[k].boneWeights[l*12 + n*4 + j] = m3d->skin[skinid].weight[j];
  5603. }
  5604. }
  5605. else
  5606. {
  5607. // raylib does not handle boneless meshes with skeletal animations, so
  5608. // we put all vertices without a bone into a special "no bone" bone
  5609. model.meshes[k].boneIds[l*12 + n*4] = m3d->numbone;
  5610. model.meshes[k].boneWeights[l*12 + n*4] = 1.0f;
  5611. }
  5612. }
  5613. }
  5614. }
  5615. // Load materials
  5616. for (i = 0; i < (int)m3d->nummaterial; i++)
  5617. {
  5618. model.materials[i + 1] = LoadMaterialDefault();
  5619. for (j = 0; j < m3d->material[i].numprop; j++)
  5620. {
  5621. prop = &m3d->material[i].prop[j];
  5622. switch (prop->type)
  5623. {
  5624. case m3dp_Kd:
  5625. {
  5626. memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].color, &prop->value.color, 4);
  5627. model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
  5628. } break;
  5629. case m3dp_Ks:
  5630. {
  5631. memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].color, &prop->value.color, 4);
  5632. } break;
  5633. case m3dp_Ns:
  5634. {
  5635. model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].value = prop->value.fnum;
  5636. } break;
  5637. case m3dp_Ke:
  5638. {
  5639. memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].color, &prop->value.color, 4);
  5640. model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].value = 0.0f;
  5641. } break;
  5642. case m3dp_Pm:
  5643. {
  5644. model.materials[i + 1].maps[MATERIAL_MAP_METALNESS].value = prop->value.fnum;
  5645. } break;
  5646. case m3dp_Pr:
  5647. {
  5648. model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].value = prop->value.fnum;
  5649. } break;
  5650. case m3dp_Ps:
  5651. {
  5652. model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].color = WHITE;
  5653. model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].value = prop->value.fnum;
  5654. } break;
  5655. default:
  5656. {
  5657. if (prop->type >= 128)
  5658. {
  5659. Image image = { 0 };
  5660. image.data = m3d->texture[prop->value.textureid].d;
  5661. image.width = m3d->texture[prop->value.textureid].w;
  5662. image.height = m3d->texture[prop->value.textureid].h;
  5663. image.mipmaps = 1;
  5664. image.format = (m3d->texture[prop->value.textureid].f == 4)? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 :
  5665. ((m3d->texture[prop->value.textureid].f == 3)? PIXELFORMAT_UNCOMPRESSED_R8G8B8 :
  5666. ((m3d->texture[prop->value.textureid].f == 2)? PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA : PIXELFORMAT_UNCOMPRESSED_GRAYSCALE));
  5667. switch (prop->type)
  5668. {
  5669. case m3dp_map_Kd: model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTextureFromImage(image); break;
  5670. case m3dp_map_Ks: model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].texture = LoadTextureFromImage(image); break;
  5671. case m3dp_map_Ke: model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(image); break;
  5672. case m3dp_map_Km: model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(image); break;
  5673. case m3dp_map_Ka: model.materials[i + 1].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(image); break;
  5674. case m3dp_map_Pm: model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(image); break;
  5675. default: break;
  5676. }
  5677. }
  5678. } break;
  5679. }
  5680. }
  5681. }
  5682. // Load bones
  5683. if (m3d->numbone)
  5684. {
  5685. model.boneCount = m3d->numbone + 1;
  5686. model.bones = (BoneInfo *)RL_CALLOC(model.boneCount, sizeof(BoneInfo));
  5687. model.bindPose = (Transform *)RL_CALLOC(model.boneCount, sizeof(Transform));
  5688. for (i = 0; i < (int)m3d->numbone; i++)
  5689. {
  5690. model.bones[i].parent = m3d->bone[i].parent;
  5691. strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name) - 1);
  5692. model.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;
  5693. model.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;
  5694. model.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;
  5695. model.bindPose[i].rotation.x = m3d->vertex[m3d->bone[i].ori].x;
  5696. model.bindPose[i].rotation.y = m3d->vertex[m3d->bone[i].ori].y;
  5697. model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;
  5698. model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;
  5699. // TODO: If the orientation quaternion is not normalized, then that's encoding scaling
  5700. model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);
  5701. model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;
  5702. // Child bones are stored in parent bone relative space, convert that into model space
  5703. if (model.bones[i].parent >= 0)
  5704. {
  5705. model.bindPose[i].rotation = QuaternionMultiply(model.bindPose[model.bones[i].parent].rotation, model.bindPose[i].rotation);
  5706. model.bindPose[i].translation = Vector3RotateByQuaternion(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].rotation);
  5707. model.bindPose[i].translation = Vector3Add(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].translation);
  5708. model.bindPose[i].scale = Vector3Multiply(model.bindPose[i].scale, model.bindPose[model.bones[i].parent].scale);
  5709. }
  5710. }
  5711. // Add a special "no bone" bone
  5712. model.bones[i].parent = -1;
  5713. strcpy(model.bones[i].name, "NO BONE");
  5714. model.bindPose[i].translation.x = 0.0f;
  5715. model.bindPose[i].translation.y = 0.0f;
  5716. model.bindPose[i].translation.z = 0.0f;
  5717. model.bindPose[i].rotation.x = 0.0f;
  5718. model.bindPose[i].rotation.y = 0.0f;
  5719. model.bindPose[i].rotation.z = 0.0f;
  5720. model.bindPose[i].rotation.w = 1.0f;
  5721. model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;
  5722. }
  5723. // Load bone-pose default mesh into animation vertices. These will be updated when UpdateModelAnimation gets
  5724. // called, but not before, however DrawMesh uses these if they exist (so not good if they are left empty)
  5725. if (m3d->numbone && m3d->numskin)
  5726. {
  5727. for (i = 0; i < model.meshCount; i++)
  5728. {
  5729. memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float));
  5730. memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
  5731. model.meshes[i].boneCount = model.boneCount;
  5732. model.meshes[i].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
  5733. for (j = 0; j < model.meshes[i].boneCount; j++)
  5734. {
  5735. model.meshes[i].boneMatrices[j] = MatrixIdentity();
  5736. }
  5737. }
  5738. }
  5739. m3d_free(m3d);
  5740. UnloadFileData(fileData);
  5741. }
  5742. return model;
  5743. }
  5744. #define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
  5745. // Load M3D animation data
  5746. static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)
  5747. {
  5748. ModelAnimation *animations = NULL;
  5749. m3d_t *m3d = NULL;
  5750. int i = 0, j = 0;
  5751. *animCount = 0;
  5752. int dataSize = 0;
  5753. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  5754. if (fileData != NULL)
  5755. {
  5756. m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
  5757. if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
  5758. {
  5759. TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);
  5760. UnloadFileData(fileData);
  5761. return NULL;
  5762. }
  5763. else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i animations, %i bones, %i skins", fileName,
  5764. m3d->numaction, m3d->numbone, m3d->numskin);
  5765. // No animation or bone+skin?
  5766. if (!m3d->numaction || !m3d->numbone || !m3d->numskin)
  5767. {
  5768. m3d_free(m3d);
  5769. UnloadFileData(fileData);
  5770. return NULL;
  5771. }
  5772. animations = (ModelAnimation *)RL_CALLOC(m3d->numaction, sizeof(ModelAnimation));
  5773. *animCount = m3d->numaction;
  5774. for (unsigned int a = 0; a < m3d->numaction; a++)
  5775. {
  5776. animations[a].frameCount = m3d->action[a].durationmsec/M3D_ANIMDELAY;
  5777. animations[a].boneCount = m3d->numbone + 1;
  5778. animations[a].bones = (BoneInfo *)RL_MALLOC((m3d->numbone + 1)*sizeof(BoneInfo));
  5779. animations[a].framePoses = (Transform **)RL_MALLOC(animations[a].frameCount*sizeof(Transform *));
  5780. strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name) - 1);
  5781. TRACELOG(LOG_INFO, "MODEL: [%s] animation #%i: %i msec, %i frames", fileName, a, m3d->action[a].durationmsec, animations[a].frameCount);
  5782. for (i = 0; i < (int)m3d->numbone; i++)
  5783. {
  5784. animations[a].bones[i].parent = m3d->bone[i].parent;
  5785. strncpy(animations[a].bones[i].name, m3d->bone[i].name, sizeof(animations[a].bones[i].name) - 1);
  5786. }
  5787. // A special, never transformed "no bone" bone, used for boneless vertices
  5788. animations[a].bones[i].parent = -1;
  5789. strcpy(animations[a].bones[i].name, "NO BONE");
  5790. // M3D stores frames at arbitrary intervals with sparse skeletons. We need full skeletons at
  5791. // regular intervals, so let the M3D SDK do the heavy lifting and calculate interpolated bones
  5792. for (i = 0; i < animations[a].frameCount; i++)
  5793. {
  5794. animations[a].framePoses[i] = (Transform *)RL_MALLOC((m3d->numbone + 1)*sizeof(Transform));
  5795. m3db_t *pose = m3d_pose(m3d, a, i*M3D_ANIMDELAY);
  5796. if (pose != NULL)
  5797. {
  5798. for (j = 0; j < (int)m3d->numbone; j++)
  5799. {
  5800. animations[a].framePoses[i][j].translation.x = m3d->vertex[pose[j].pos].x*m3d->scale;
  5801. animations[a].framePoses[i][j].translation.y = m3d->vertex[pose[j].pos].y*m3d->scale;
  5802. animations[a].framePoses[i][j].translation.z = m3d->vertex[pose[j].pos].z*m3d->scale;
  5803. animations[a].framePoses[i][j].rotation.x = m3d->vertex[pose[j].ori].x;
  5804. animations[a].framePoses[i][j].rotation.y = m3d->vertex[pose[j].ori].y;
  5805. animations[a].framePoses[i][j].rotation.z = m3d->vertex[pose[j].ori].z;
  5806. animations[a].framePoses[i][j].rotation.w = m3d->vertex[pose[j].ori].w;
  5807. animations[a].framePoses[i][j].rotation = QuaternionNormalize(animations[a].framePoses[i][j].rotation);
  5808. animations[a].framePoses[i][j].scale.x = animations[a].framePoses[i][j].scale.y = animations[a].framePoses[i][j].scale.z = 1.0f;
  5809. // Child bones are stored in parent bone relative space, convert that into model space
  5810. if (animations[a].bones[j].parent >= 0)
  5811. {
  5812. animations[a].framePoses[i][j].rotation = QuaternionMultiply(animations[a].framePoses[i][animations[a].bones[j].parent].rotation, animations[a].framePoses[i][j].rotation);
  5813. animations[a].framePoses[i][j].translation = Vector3RotateByQuaternion(animations[a].framePoses[i][j].translation, animations[a].framePoses[i][animations[a].bones[j].parent].rotation);
  5814. animations[a].framePoses[i][j].translation = Vector3Add(animations[a].framePoses[i][j].translation, animations[a].framePoses[i][animations[a].bones[j].parent].translation);
  5815. animations[a].framePoses[i][j].scale = Vector3Multiply(animations[a].framePoses[i][j].scale, animations[a].framePoses[i][animations[a].bones[j].parent].scale);
  5816. }
  5817. }
  5818. // Default transform for the "no bone" bone
  5819. animations[a].framePoses[i][j].translation.x = 0.0f;
  5820. animations[a].framePoses[i][j].translation.y = 0.0f;
  5821. animations[a].framePoses[i][j].translation.z = 0.0f;
  5822. animations[a].framePoses[i][j].rotation.x = 0.0f;
  5823. animations[a].framePoses[i][j].rotation.y = 0.0f;
  5824. animations[a].framePoses[i][j].rotation.z = 0.0f;
  5825. animations[a].framePoses[i][j].rotation.w = 1.0f;
  5826. animations[a].framePoses[i][j].scale.x = animations[a].framePoses[i][j].scale.y = animations[a].framePoses[i][j].scale.z = 1.0f;
  5827. RL_FREE(pose);
  5828. }
  5829. }
  5830. }
  5831. m3d_free(m3d);
  5832. UnloadFileData(fileData);
  5833. }
  5834. return animations;
  5835. }
  5836. #endif
  5837. #endif // SUPPORT_MODULE_RMODELS