Objmc
A tool to bypass Minecraft Java Edition model limits by baking vertex data into texture.
Install / Use
/learn @Godlander/ObjmcREADME
i cannot guarantee modded compatibility. core shaders are a vanilla resourcepack feature, if a mod breaks this vanilla feature its likely a decision by the mod creator.
usage:
make sure Python and Pillow is installed, and place the script in the same directory as the input obj and texture files.
either edit the script with your inputs, or run python objmc.py with correct arguments in command line to generate the model and texture outputs that go in a resourcepack.
running the script without any arguments will open a gui with slightly more limited options.

place the model and texture output generated with this tool in the correct location in the resourcepack along with the shaders folder, and should display properly.
make sure your minecraft version is 1.21+ as the shader may not work with lower versions.
script inputs
objs: array of string names of obj files in the same folder to read. these must have same number of vertices if used in same animation.
frames: array of strings of digits defining which index of the obj to use as each frame.
texs: array of names of the texture files. the minimum size is 8x8, but a wider texture is recommended if model has a lot of vertices or is animated.
script output
output: array of two string file names: the json model, and the texture.
advanced:
offset and scale: just adds & multiplies vertex positions before encoding, so you dont have to re-export the model.
duration: total duration of the animation in ticks.
noshadow: disable shading the model based on face normals.
easing: interpolation method shader uses inbetween vertex animation frames. 0: none, 1: linear, 2: in-out cubic, 3: 4-point bezier.
interpolation: interpolation method shader uses inbetween texture frames. 0: none, 1: fade.
flipuv: if your model renders but doesn't look right, try toggling this. see #flipped-uv.
for custom entity model rotation and controllable animation to work, the model has to be an item with overlay color, like Potion or dyed Leather Armor (can use CustomModelData).
colorbehavior: defines the behavior of each byte of the overlay color of the item r,g,b. x: pitch rotation, y: yaw rotation, z: roll rotation, t: animation time offset, o: overlay color hue.
example: yaw time overlay defines 1 byte of red color as yaw rotation, the next byte of blue color as animation time offset , and the last byte of green being overlay color hue.
autorotate: tells the shader to estimate rotation from Normals instead of defining it by color. due to byte inaccuracy this will be a little jittery. allows color to be used for other inputs like controlling animation.
autoplay: make the animation continuously play, color can still be used to define the starting frame. colorbehavior = 'time time time' will override this.
visibility: 3 bit number, defines where a model is visible. 1: in gui, 2: in first person hand, 4: in world. (7 would mean visible everywhere.) models with limited visibility can be joined together allowing for different models to show up in different places.
join: used by itself to combine generated models. --join model1.json model2.json will combine the two or more models into one. the textures still need to be placed in the right paths for all of the models.
The script can be run with arguments to each of these. Example:
python objmc.py --objs cube.obj --texs cube.png --autorotate --flipuv --out potion.json texture.png
samples:
https://user-images.githubusercontent.com/16228717/177398816-cf919f1d-8de1-4346-9024-068c48f47cbf.mp4





heads
arbitrary model display using player skin to encode model data
model geometry complexity is limited per skin, and textures must be 32x32
python objh.py --obj model.obj --tex texture.png --out skin.png --scale 5
will output a skin image and a command missing a base64 url in the nbt
upload the skin to your account, then run python objh.py --skin username to get the base64 url
or rerun python objh.py --obj model.obj --tex texture.png --out skin.png --scale 5 --skin username/base64 to automatically insert the url
complete the command, then you can run it to summon the model. anyone with the resourcepack will be able to see the model.
example
tree model:

summon area_effect_cloud ~ ~1 ~ {Passengers:[{id:"item_display",Tags:["objh"],transformation:{translation:[-1000f,-1000f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[-500f,-1000f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[0f,-1000f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[500f,-1000f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[-1000f,-500f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[-500f,-500f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[0f,-500f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[500f,-500f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[-1000f,0f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[-500f,0f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX0="}]}}}}},{id:"item_display",Tags:["objh"],transformation:{translation:[0f,0f,-1000f],scale:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]},item:{id:"player_head",Count:1b,tag:{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:"eyd0ZXh0dXJlcyc6IHsnU0tJTic6IHsndXJsJzogJ2h0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjI1YjM1NDhjMjFiZWE5MmU2YjQ5NTViMTZkMTQ1M2YzYmExMzE4MTE3YTgwNGE4ZmIzZTliZGJjNDQwMGM0Myd9fX
