From 470574517ab61ed71d769261cdcc136e8d0220d8 Mon Sep 17 00:00:00 2001 From: Hristo Stamenov Date: Wed, 26 May 2021 21:23:13 +0300 Subject: [PATCH] Implement vertex color attribute for GLTF and IQM (#1790) Added a simple cube with vertex colors for testing both. --- examples/models/models_gltf_model.c | 5 +- .../resources/gltf/vertex_colored_object.glb | Bin 0 -> 2512 bytes .../models/vertex_colored_object.iqm | Bin 0 -> 1800 bytes src/models.c | 56 +++++++++++++++++- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 examples/models/resources/gltf/vertex_colored_object.glb create mode 100644 examples/models/resources/models/vertex_colored_object.iqm diff --git a/examples/models/models_gltf_model.c b/examples/models/models_gltf_model.c index d5bd1687e..3475b3f0c 100644 --- a/examples/models/models_gltf_model.c +++ b/examples/models/models_gltf_model.c @@ -21,7 +21,7 @@ #include -#define MAX_MODELS 6 +#define MAX_MODELS 7 int main(void) { @@ -30,7 +30,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [models] example - model animation"); + InitWindow(screenWidth, screenHeight, "raylib [models] example - model"); // Define the camera to look into our 3d world Camera camera = { 0 }; @@ -48,6 +48,7 @@ int main(void) model[3] = LoadModel("resources/gltf/BoxAnimated.glb"); model[4] = LoadModel("resources/gltf/AnimatedTriangle.gltf"); model[5] = LoadModel("resources/gltf/AnimatedMorphCube.glb"); + model[6] = LoadModel("resources/gltf/vertex_colored_object.glb"); int currentModel = 0; diff --git a/examples/models/resources/gltf/vertex_colored_object.glb b/examples/models/resources/gltf/vertex_colored_object.glb new file mode 100644 index 0000000000000000000000000000000000000000..0b57eddbdfdd1666dbf812f5b8d6e3151fec59e4 GIT binary patch literal 2512 zcmYe#32|d$U|_hw$-uCNm4U%4*x#>ODY3XXwM5CPS}8p>FSRJKB)>?>O36E;C_gX1 zSOKI(!6_#-FD11|!BgK~q0CUvM9;)PNk^$HwWv5VKTpX@$w<#Ysa8j+I5{;hRmsW# z$|_c}imq15OUzAGvQi2L%jqcP<)@^ABn)&6b&O(bV-X_NO1Y`U8DQ;DJ`sYgXEi8JQaynj0FMTNoOfnpqecn(7$nnVK6|nwXm!nOj(xni!kM>L`^ICFT|9 zz)UyMGcY$ZGBGtaFt;=^GBz{TG1ap)Ft#u=w6wG|H8eCgwA9fx)H5(JH8C}|G%+zU zFf%eXw}?e@vvXo@YEdG(qfIP~O^wYAj7=d+}Oy#+``n<2;?^l0}~4)ki!kkEey;|FdS{JXKZR=VQFY$VQy$-Xlh}k zW1?qiYGG_(X=rY2YGG_?VWMNEXK7?=ZfRg{VP8*40E#uJJX}oA!~gKM2G& zuGLY>%uC5k25C3ZQG)qh$;zM>92kko$*IM~`9+YxNGeTBODzh^Of3gnker`eke`>D zR}xZLkg8;5YG`Dpqm-OqnpdJ^Wdt^@Ldh!HP{&ZmFjhw?H#1MkDq7c22aG@w2G*q% z=IU$=PT$C;8-fhNZ+ZzH?M9?%H^Q*p7@KymAlz?x`9-;jIhj?6WPxyx35J0t_zg5R z(@}zI4|aC+aST!dB>_ZuAcsCU{%L98BFq4k@gSNB zD>kyQz@yyI(g@XTQ*$#?l$)F3Gu<4`a7!}-gukJFM)Ihkfw56-Y^?$Z3j>3brym0Y zLxVjO?}ySLJ~lQ;41{6w*w`RBLKvnGqz)S!CI+HG7^V)L4dN5RAiW?AQU{_z7@ZB{ zgJ=+jse!T?prBztgaHaKh6YGjfkhg?Bm-C;$_9ym_+YhQ4v2tYm>8HQ#vG7)>>+x= z_CnnOVnanCc0=P5Bo4A0EC+QDm=9%x#6f%z2C+fv!8A-ij0U+4%`UJWWOM8p7!*Km z!$KdhV_;ygXJA05LFyaqAo`GLkU9__od&6QfSM1Y6QK5i)PeX6NcMpEAoZZI1<@dX zfz-pz1?jb8V1V%%7*xgn|Hp>^|F@0)7y17`Ce0wsAPf>mr`KNL69kE)(tB81SU{ra z^#A`g9yJ~y8FYG^&eRhiaa7vaqU1M76rE;d;A0SBU}O+sU}xZBU}F$w;9?MF5N8l& z5MtnA5M|(D;AaqEU}oTC5MbbB5My9vU}E54U}fN7;ARkH;ALQ75M*FrU||3Neh$0F literal 0 HcmV?d00001 diff --git a/examples/models/resources/models/vertex_colored_object.iqm b/examples/models/resources/models/vertex_colored_object.iqm new file mode 100644 index 0000000000000000000000000000000000000000..ad0db07eb55daa54f5b68b9112b55faddce2c2f7 GIT binary patch literal 1800 zcmebD3vmq!40ZH&_4Rjg^EXg12Pn34~Pa~kh7RU?qh_g zg^7XOtii+pb~{WAr0xY10|SVLiLrq6vM?~f>;U--B-R1)7(;_S0|M`7U}ykgkQj^x zu|XJ_4`L%@kUR*3#9%atjSYk3K^P_nW5Z~WIE)RWVPeR9kQfMq#6TFvhS4A~WDF9A zVURe84WeNfoevV<&%mHy&%nT7&%lrX;@d%J5FaGoV8_64z>a|dM1%OC5C_p9K1dwI z2hpG~28lb^L(Bv5LE<1jgB`?t5Ff4&WGB>IkT|k^Aag)`kT^^|$Q+nBhz9XN@*s5} zH-Iq6P7n>kgxH`o08$6SgxG}S(aiwyL6}&5gxm@?3lv@;1{9N`2gMzrINlF6gaMi_ z2=HO5L3V;Lz4?^dNpJU}+86vk`2YWsr~g$|{{R2)>-+!zYfmsA#BTii|33(WI z5yS?Su^>JN0|Nsm0|NsWsLW(wVBm)GLFF+o0|Nsev<~2BU|<08L3M>70|SE)0|Nty eEzH2c0OE@num_vertexes*4*sizeof(unsigned char)); + //fseek(iqmFile, va[i].offset, SEEK_SET); + //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile); + memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char)); + + for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) + { + model.meshes[m].colors = RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char)); + + int vCounter = 0; + for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++) + { + model.meshes[m].colors[vCounter] = color[i]; + vCounter++; + } + } + } break; } } @@ -4301,6 +4321,40 @@ static Model LoadGLTF(const char *fileName) TRACELOG(LOG_WARNING, "MODEL: [%s] glTF normals must be float or int", fileName); } } + else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_color) + { + cgltf_accessor *acc = data->meshes[i].primitives[p].attributes[j].data; + model.meshes[primitiveIndex].colors = RL_MALLOC(acc->count*4*sizeof(unsigned char)); + + if (acc->component_type == cgltf_component_type_r_8u) + { + for (int a = 0; a < acc->count; a++) + { + GLTFReadValue(acc, a, model.meshes[primitiveIndex].colors + (a*4), 4, sizeof(unsigned char)); + } + } + if (acc->component_type == cgltf_component_type_r_16u) + { + TRACELOG(LOG_WARNING, "MODEL: [%s] converting glTF colors to unsigned char", fileName); + for (int a = 0; a < acc->count; a++) + { + unsigned short readValue[4]; + for (int a = 0; a < acc->count; a++) + { + GLTFReadValue(acc, a, readValue, 4, sizeof(unsigned short)); + // 257 = 65535/255 + model.meshes[primitiveIndex].colors[(a*4) + 0] = (unsigned char)(readValue[0] / 257); + model.meshes[primitiveIndex].colors[(a*4) + 1] = (unsigned char)(readValue[1] / 257); + model.meshes[primitiveIndex].colors[(a*4) + 2] = (unsigned char)(readValue[2] / 257); + model.meshes[primitiveIndex].colors[(a*4) + 3] = (unsigned char)(readValue[3] / 257); + } + } + } + else + { + TRACELOG(LOG_WARNING, "MODEL: [%s] glTF colors must be uchar or ushort", fileName); + } + } } cgltf_accessor *acc = data->meshes[i].primitives[p].indices;