├── .gitattributes ├── .github ├── images │ ├── image1.png │ └── image2.png └── workflows │ ├── preview_build.yml │ └── released.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── icon ├── icon.png └── icon_min.png ├── settings.gradle ├── src ├── client │ ├── java │ │ └── dev │ │ │ └── felnull │ │ │ └── specialmodelloader │ │ │ ├── api │ │ │ ├── SpecialModelLoaderAPI.java │ │ │ ├── data │ │ │ │ └── SpecialModelDataGenHelper.java │ │ │ ├── event │ │ │ │ └── SpecialModelLoaderEvents.java │ │ │ └── model │ │ │ │ ├── LoadedResource.java │ │ │ │ ├── ModelLoader.java │ │ │ │ ├── ModelOption.java │ │ │ │ └── obj │ │ │ │ ├── ObjModelLoader.java │ │ │ │ └── ObjModelOption.java │ │ │ └── impl │ │ │ ├── SpecialModelLoaderAPIImpl.java │ │ │ ├── SpecialModelLoaderClient.java │ │ │ ├── handler │ │ │ ├── SMLClientHandler.java │ │ │ ├── SMLModelLoadingHandler.java │ │ │ └── package-info.java │ │ │ ├── mixin │ │ │ ├── BlockModelAccessor.java │ │ │ └── package-info.java │ │ │ ├── model │ │ │ ├── ModelOptionImpl.java │ │ │ ├── NeoForgeCompat.java │ │ │ ├── SimpleMeshModel.java │ │ │ ├── SpecialBaseModel.java │ │ │ ├── SpecialBaseUnbakedModel.java │ │ │ ├── obj │ │ │ │ ├── ObjModelLoadedResource.java │ │ │ │ ├── ObjModelLoaderImp.java │ │ │ │ ├── ObjModelOptionImpl.java │ │ │ │ ├── ObjUnbakedModelModel.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── util │ │ │ ├── JsonUtils.java │ │ │ └── package-info.java │ └── resources │ │ └── special-model-loader.mixins.json ├── main │ ├── java │ │ └── dev │ │ │ └── felnull │ │ │ └── specialmodelloader │ │ │ └── impl │ │ │ └── SpecialModelLoader.java │ └── resources │ │ ├── assets │ │ └── special-model-loader │ │ │ └── icon.png │ │ └── fabric.mod.json └── test │ ├── generated │ ├── .cache │ │ └── d26dbd274f1ce9df6c32c695a40e10fe4203dafa │ └── assets │ │ └── special-model-loader-test │ │ ├── blockstates │ │ ├── facing_model_block.json │ │ ├── facing_obj_model_block.json │ │ └── normal_model_block.json │ │ └── models │ │ ├── block │ │ ├── facing_model_block.json │ │ └── normal_model_block.json │ │ └── item │ │ ├── mtloverride_obj_model_item.json │ │ ├── normal_model_item.json │ │ ├── obj_model_item.json │ │ └── textures_obj_model_item.json │ ├── java │ └── dev │ │ └── felnull │ │ └── smltest │ │ ├── SMLTest.java │ │ ├── block │ │ ├── FacingBlock.java │ │ └── SMLTestBlocks.java │ │ ├── client │ │ ├── DynamicObjModelItemSpecialRenderer.java │ │ └── SMLTestClient.java │ │ ├── data │ │ ├── SMLTestDataGenerator.java │ │ └── SMLTestModelProvider.java │ │ └── item │ │ └── SMLTestItems.java │ └── resources │ ├── assets │ └── special-model-loader-test │ │ ├── blockstates │ │ └── obj_model_block.json │ │ ├── items │ │ ├── dynamic_obj_model_item.json │ │ ├── forge_obj_model_item.json │ │ └── obj2_model_item.json │ │ ├── models │ │ ├── block │ │ │ ├── apple │ │ │ │ ├── apple.mtl │ │ │ │ └── apple.obj │ │ │ └── obj_model_block.json │ │ └── item │ │ │ ├── cylinder │ │ │ ├── cylinder.blend │ │ │ ├── cylinder.mtl │ │ │ └── cylinder.obj │ │ │ ├── dynamic_obj_model_item.json │ │ │ ├── forge_obj_model_item.json │ │ │ ├── obj2_model_item.json │ │ │ ├── obj_model_block.json │ │ │ ├── obj_model_item_dynamic.json │ │ │ ├── parabolic_antenna │ │ │ ├── parabolic_antenna.mtl │ │ │ ├── parabolic_antenna.obj │ │ │ └── parabolic_antenna_2.mtl │ │ │ ├── ring │ │ │ ├── ring.mtl │ │ │ ├── ring.obj │ │ │ └── ring_2.mtl │ │ │ ├── sea_cheken_pack │ │ │ ├── sea_chicken.blend │ │ │ ├── sea_chicken.mtl │ │ │ └── sea_chicken.obj │ │ │ └── test │ │ │ ├── test.mtl │ │ │ └── test.obj │ │ ├── sml_load_scopes │ │ └── test.json │ │ └── textures │ │ ├── block │ │ ├── body.png │ │ ├── eay.png │ │ ├── facing_model_block_front.png │ │ ├── facing_model_block_side.png │ │ ├── facing_model_block_top.png │ │ └── normal_model_block.png │ │ └── item │ │ ├── cheken.png │ │ ├── cheken_pack.png │ │ ├── normal_model_item.png │ │ └── parabolic_antenna.png │ └── fabric.mod.json └── test-resourcepacks ├── SMLTestPack.zip └── SMLTestPack ├── assets ├── minecraft │ ├── models │ │ └── item │ │ │ ├── 3d_apple.mtl │ │ │ ├── 3d_apple.obj │ │ │ └── apple.json │ └── textures │ │ └── item │ │ └── 3d_apple.png └── sml-test-pack │ └── sml_load_scopes │ └── test_scopes.json ├── pack.mcmeta └── pack.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # Linux start script should use lf 5 | /gradlew text eol=lf 6 | 7 | # These are Windows script files and should use crlf 8 | *.bat text eol=crlf 9 | 10 | -------------------------------------------------------------------------------- /.github/images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/.github/images/image1.png -------------------------------------------------------------------------------- /.github/images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/.github/images/image2.png -------------------------------------------------------------------------------- /.github/workflows/preview_build.yml: -------------------------------------------------------------------------------- 1 | name: Preview Build 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | preview_build: 8 | uses: TeamFelnull/actions-reusable-workflows/.github/workflows/mcmod-preview-build.yml@master 9 | with: 10 | build_tasks: "build publish" 11 | secrets: 12 | maven_password: ${{ secrets.MAVEN_PASSWORD }} -------------------------------------------------------------------------------- /.github/workflows/released.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | release: 10 | uses: TeamFelnull/actions-reusable-workflows/.github/workflows/mcmod-release.yml@master 11 | with: 12 | build_tasks: "build publishCurseForge modrinth publish" 13 | secrets: 14 | curseforge_token: ${{ secrets.CURSEFORGE_TOKEN_MORI }} 15 | modrinth_token: ${{ secrets.MODRINTH_TOKEN_MORI }} 16 | maven_password: ${{ secrets.MAVEN_PASSWORD }} 17 | 18 | postRelease: 19 | name: Update after release 20 | needs: release 21 | uses: TeamFelnull/actions-reusable-workflows/.github/workflows/mcmod-post-release.yml@master 22 | with: 23 | update_forge_version_check: false 24 | update_neoforge_version_check: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gradle 2 | 3 | .gradle/ 4 | build/ 5 | out/ 6 | classes/ 7 | 8 | # eclipse 9 | 10 | *.launch 11 | 12 | # idea 13 | 14 | .idea/ 15 | *.iml 16 | *.ipr 17 | *.iws 18 | 19 | # vscode 20 | 21 | .settings/ 22 | .vscode/ 23 | bin/ 24 | .classpath 25 | .project 26 | 27 | # macos 28 | 29 | *.DS_Store 30 | 31 | # fabric 32 | 33 | run/ 34 | 35 | # java 36 | 37 | hs_err_*.log 38 | replay_*.log 39 | *.hprof 40 | *.jfr 41 | 42 | src/main/generated/ 43 | src/test/generated/ 44 | 45 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | Changelog to track updates for this mod. 3 | Add your changes to Unreleased if you want to commit. 4 | Please write according to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 5 | 6 | ## [Unreleased] 7 | 8 | ### Added 9 | 10 | ### Changed 11 | 12 | ### Deprecated 13 | 14 | ### Removed 15 | 16 | ### Fixed 17 | 18 | ### Security 19 | 20 | ## [1.4.0] - 2025-01-19 21 | 22 | ### Changed 23 | - Port MC1.21.4 24 | 25 | ## [1.3.0] - 2024-09-21 26 | 27 | ### Changed 28 | - Port MC1.21.1 29 | 30 | ## [1.2.0] - 2023-06-11 31 | 32 | ### Added 33 | - Added ability to add model load scopes using resource packs 34 | 35 | ### Changed 36 | - Port MC1.20 [#2](https://github.com/TeamFelnull/SpecialModelLoader/pull/2) 37 | 38 | ## [1.1.0] - 2023-03-31 39 | 40 | ### Changed 41 | - Port MC1.19.4 42 | 43 | ## [1.0.1] - 2023-03-29 44 | 45 | ### Changed 46 | - Changed dependent Fabric Loader version to 0.14.17 and Fabruc API version to 0.76.0+1.19.3 47 | 48 | ### Deprecated 49 | - Adding this version to a MC1.19.4 project is deprecated, please use the 1.1.0 version to be uploaded at a later date. 50 | 51 | ### Fixed 52 | - Fixed error when adding to Fabric Loom 1.1 project 53 | 54 | [Unreleased]: https://github.com/TeamFelnull/SpecialModelLoader/compare/v1.4.0...HEAD 55 | [1.4.0]: https://github.com/TeamFelnull/SpecialModelLoader/compare/v1.3.0...v1.4.0 56 | [1.3.0]: https://github.com/TeamFelnull/SpecialModelLoader/compare/v1.2.0...v1.3.0 57 | [1.2.0]: https://github.com/TeamFelnull/SpecialModelLoader/compare/v1.1.0...v1.2.0 58 | [1.1.0]: https://github.com/TeamFelnull/SpecialModelLoader/compare/v1.0.1...v1.1.0 59 | [1.0.1]: https://github.com/TeamFelnull/SpecialModelLoader/commits/v1.0.1 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 TeamFelNull 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Special Model Loader

4 | Special Model Loader is a library for loading OBJ models in Fabric. 5 | 6 | [Example](https://github.com/TeamFelnull/SpecialModelLoader-Example) · [Report an Issue](https://github.com/TeamFelnull/SpecialModelLoader/issues/new/choose) · [Getting Started](https://github.com/TeamFelnull/SpecialModelLoader/wiki/Getting-Started) 7 | 8 | Modrinth 9 | Curseforge 10 | 11 |
12 | 13 | *** 14 | 15 | Development inspired by [FOML](https://github.com/OnyxStudios/FOML) and [Myron](https://github.com/Haven-King/myron), but neither libraries are available for use in the 1.19 version of Fabric. 16 | 17 | Please see the Wiki for more information or see [SpecialModelLoader-Example](https://github.com/TeamFelnull/SpecialModelLoader-Example) for usage examples. 18 | 19 | ## Discord Support 20 | Feel free to ask for additional support in the Discord server, just open a thread in the `#special-model-loader` channel. 21 | 22 | 23 | 24 | ## Using Libraries: 25 | 26 | - [de.javagl.obj](https://github.com/javagl/Obj) 27 | 28 | Since it is built into the jar file, there is no need to add it as a separate dependency. 29 | 30 | *** 31 | ![License](https://img.shields.io/github/license/TeamFelnull/SpecialModelLoader?color=9F9F9F&style=for-the-badge) 32 | ![GitHub contributors](https://img.shields.io/github/contributors/TeamFelnull/SpecialModelLoader?color=9F9F9F&style=for-the-badge) 33 | ![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/TeamFelnull/SpecialModelLoader/latest?color=9F9F9F&style=for-the-badge) 34 | ![GitHub last commit](https://img.shields.io/github/last-commit/TeamFelnull/SpecialModelLoader?style=for-the-badge) 35 | ![GitHub issues](https://img.shields.io/github/issues-raw/TeamFelnull/SpecialModelLoader?style=for-the-badge) 36 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import net.darkhax.curseforgegradle.TaskPublishCurseForge 2 | 3 | plugins { 4 | id 'fabric-loom' version '1.9-SNAPSHOT' 5 | id 'maven-publish' 6 | id 'net.darkhax.curseforgegradle' version '1.1.25' 7 | id "com.modrinth.minotaur" version '2.8.7' 8 | id 'org.jetbrains.changelog' version "2.0.0" 9 | } 10 | 11 | // Version Check 12 | if (System.getenv("GITHUB_REF") != null && System.getenv("GITHUB_REF").startsWith("refs/tags/v")) { 13 | if (System.getenv("GITHUB_REF").substring("refs/tags/v".length()) != project.mod_version) 14 | throw new IllegalStateException("The version and tag specification are different") 15 | } 16 | 17 | version = project.mod_version 18 | group = project.maven_group 19 | 20 | base { 21 | archivesName = project.archives_base_name 22 | } 23 | 24 | fabricApi { 25 | configureDataGeneration() { 26 | client = true 27 | } 28 | } 29 | 30 | loom { 31 | splitEnvironmentSourceSets() 32 | 33 | mods { 34 | "special-model-loader" { 35 | sourceSet sourceSets.main 36 | sourceSet sourceSets.client 37 | } 38 | } 39 | 40 | runs { 41 | testmodClient { 42 | client() 43 | ideConfigGenerated project.rootProject == project 44 | name = "Testmod Client" 45 | source sourceSets.test 46 | } 47 | 48 | testmodDatagen { 49 | client() 50 | 51 | ideConfigGenerated project.rootProject == project 52 | 53 | name = "Testmod Data" 54 | vmArg "-Dfabric-api.datagen" 55 | vmArg "-Dfabric-api.datagen.output-dir=${file("src/test/generated")}" 56 | 57 | runDir "build/datagen" 58 | source sourceSets.test 59 | } 60 | } 61 | } 62 | 63 | sourceSets { 64 | test { 65 | compileClasspath += main.compileClasspath 66 | runtimeClasspath += main.runtimeClasspath 67 | compileClasspath += client.compileClasspath 68 | runtimeClasspath += client.runtimeClasspath 69 | 70 | resources { 71 | srcDirs += [ 72 | 'src/test/generated' 73 | ] 74 | } 75 | } 76 | } 77 | 78 | changelog { 79 | repositoryUrl = rootProject.repository_url 80 | introduction = """ 81 | Changelog to track updates for this mod. 82 | Add your changes to Unreleased if you want to commit. 83 | Please write according to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 84 | """ 85 | combinePreReleases = false 86 | } 87 | 88 | repositories { 89 | maven { url "https://maven.parchmentmc.org" } 90 | } 91 | 92 | configurations { 93 | modImplementation.extendsFrom includeIn 94 | include.extendsFrom includeIn 95 | } 96 | 97 | dependencies { 98 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 99 | 100 | mappings loom.layered() { 101 | officialMojangMappings() 102 | parchment("org.parchmentmc.data:parchment-1.21.4:2025.01.05@zip") 103 | } 104 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 105 | 106 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" 107 | 108 | includeIn "de.javagl:obj:0.4.0" 109 | 110 | testImplementation sourceSets.client.output 111 | } 112 | 113 | remapJar { 114 | archiveClassifier.set(null) 115 | setArchivesBaseName("${rootProject.archives_base_name}-mc${rootProject.minecraft_version}") 116 | } 117 | 118 | processResources { 119 | inputs.property "version", project.version 120 | 121 | filesMatching("fabric.mod.json") { 122 | expand "version": project.version 123 | } 124 | } 125 | 126 | tasks.withType(JavaCompile).configureEach { 127 | it.options.release = 21 128 | } 129 | 130 | java { 131 | withSourcesJar() 132 | 133 | sourceCompatibility = JavaVersion.VERSION_21 134 | targetCompatibility = JavaVersion.VERSION_21 135 | } 136 | 137 | jar { 138 | from("LICENSE") { 139 | rename { "${it}_${project.base.archivesName.get()}" } 140 | } 141 | } 142 | 143 | publishing { 144 | publications { 145 | mavenFabric(MavenPublication) { 146 | artifactId = rootProject.archives_base_name 147 | from components.java 148 | pom { 149 | name = 'SpecialModelLoader' 150 | description = 'Support for loading special models.' 151 | developers { 152 | developer { 153 | id = 'MORIMORI0317' 154 | name = 'MORIMORI0317' 155 | } 156 | developer { 157 | id = 'FelNull' 158 | name = 'TeamFelNull' 159 | email = 'teamfelnull@felnull.dev' 160 | } 161 | } 162 | } 163 | } 164 | } 165 | 166 | repositories { 167 | maven { 168 | url "https://maven.felnull.dev/" 169 | credentials { 170 | username = "felnull" 171 | password = "${project.maven_put_pass}" != '' ? "${project.maven_put_pass}" : System.getenv('mavenpassword') 172 | } 173 | } 174 | } 175 | } 176 | 177 | def mainJar = file("${project.layout.buildDirectory.get().asFile}/libs/${project.archives_base_name}-mc${project.minecraft_version}-${project.mod_version}.jar") 178 | def sourcesJar = file("${project.layout.buildDirectory.get().asFile}/libs/${project.archives_base_name}-mc${project.minecraft_version}-${project.mod_version}-sources.jar") 179 | def changeLogFile = file('./LATEST_CHANGELOG.md') 180 | def uploadMainName = "${project.mod_display_name}-${project.minecraft_version}-${project.mod_version}" 181 | def uploadSourcesName = "${project.mod_display_name}-${project.minecraft_version}-${project.mod_version}-sources" 182 | 183 | tasks.register('publishCurseForge', TaskPublishCurseForge) { 184 | if (System.getenv('curesforgeapikey') != null && "${project.curesforge_id}" != '') { 185 | apiToken = System.getenv('curesforgeapikey') 186 | 187 | def mainFile = upload(findProperty('curesforge_id'), mainJar) 188 | mainFile.changelogType = 'markdown' 189 | mainFile.changelog = changeLogFile.text 190 | mainFile.releaseType = "${project.release_type}" 191 | mainFile.displayName = uploadMainName 192 | 193 | project.support_versions.split(",").each { 194 | String version -> mainFile.addGameVersion(version) 195 | } 196 | 197 | mainFile.addJavaVersion('Java 21') 198 | 199 | mainFile.addModLoader('Fabric') 200 | mainFile.addModLoader('Quilt') 201 | 202 | mainFile.addGameVersion('Client') 203 | 204 | mainFile.addRequirement("fabric-api") 205 | 206 | def sourcesFile = mainFile.withAdditionalFile(sourcesJar) 207 | sourcesFile.displayName = uploadSourcesName 208 | } 209 | } 210 | 211 | if (System.getenv('modrinthapikey') != null && "${modrinth_id}" != '') { 212 | modrinth { 213 | token = System.getenv('modrinthapikey') 214 | projectId = "${project.modrinth_id}" 215 | versionName = uploadMainName 216 | versionNumber = "${project.minecraft_version}-${project.mod_version}" 217 | versionType = "${project.release_type}" 218 | uploadFile = mainJar 219 | gameVersions = List.of(project.support_versions.split(",")) 220 | loaders = ["fabric", "quilt"] 221 | dependencies { 222 | required.project("P7dR8mSH") //Fabric API 223 | } 224 | changelog = changeLogFile.text 225 | } 226 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #Gradle setting 2 | org.gradle.jvmargs=-Xmx3G 3 | org.gradle.parallel=true 4 | #Minecraft 5 | minecraft_version=1.21.4 6 | support_versions=1.21.4 7 | #Mod 8 | archives_base_name=special-model-loader 9 | mod_display_name=SpecialModelLoader 10 | mod_version=1.4.0 11 | #Dependencies 12 | loader_version=0.16.9 13 | fabric_version=0.111.0+1.21.4 14 | #Maven 15 | maven_group=dev.felnull 16 | maven_put_url=https://maven.felnull.dev/ 17 | maven_put_pass= 18 | #Upload 19 | curesforge_id=782421 20 | modrinth_id=ajFw7VkX 21 | release_type=release 22 | #Other 23 | repository_url=https://github.com/TeamFelnull/SpecialModelLoader 24 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s 90 | ' "$PWD" ) || exit 91 | 92 | # Use the maximum available, or set MAX_FD != -1 to use that value. 93 | MAX_FD=maximum 94 | 95 | warn () { 96 | echo "$*" 97 | } >&2 98 | 99 | die () { 100 | echo 101 | echo "$*" 102 | echo 103 | exit 1 104 | } >&2 105 | 106 | # OS specific support (must be 'true' or 'false'). 107 | cygwin=false 108 | msys=false 109 | darwin=false 110 | nonstop=false 111 | case "$( uname )" in #( 112 | CYGWIN* ) cygwin=true ;; #( 113 | Darwin* ) darwin=true ;; #( 114 | MSYS* | MINGW* ) msys=true ;; #( 115 | NONSTOP* ) nonstop=true ;; 116 | esac 117 | 118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 119 | 120 | 121 | # Determine the Java command to use to start the JVM. 122 | if [ -n "$JAVA_HOME" ] ; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD=$JAVA_HOME/jre/sh/java 126 | else 127 | JAVACMD=$JAVA_HOME/bin/java 128 | fi 129 | if [ ! -x "$JAVACMD" ] ; then 130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 131 | 132 | Please set the JAVA_HOME variable in your environment to match the 133 | location of your Java installation." 134 | fi 135 | else 136 | JAVACMD=java 137 | if ! command -v java >/dev/null 2>&1 138 | then 139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 140 | 141 | Please set the JAVA_HOME variable in your environment to match the 142 | location of your Java installation." 143 | fi 144 | fi 145 | 146 | # Increase the maximum file descriptors if we can. 147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 148 | case $MAX_FD in #( 149 | max*) 150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 151 | # shellcheck disable=SC2039,SC3045 152 | MAX_FD=$( ulimit -H -n ) || 153 | warn "Could not query maximum file descriptor limit" 154 | esac 155 | case $MAX_FD in #( 156 | '' | soft) :;; #( 157 | *) 158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 159 | # shellcheck disable=SC2039,SC3045 160 | ulimit -n "$MAX_FD" || 161 | warn "Could not set maximum file descriptor limit to $MAX_FD" 162 | esac 163 | fi 164 | 165 | # Collect all arguments for the java command, stacking in reverse order: 166 | # * args from the command line 167 | # * the main class name 168 | # * -classpath 169 | # * -D...appname settings 170 | # * --module-path (only if needed) 171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 172 | 173 | # For Cygwin or MSYS, switch paths to Windows format before running java 174 | if "$cygwin" || "$msys" ; then 175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 177 | 178 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 179 | 180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 181 | for arg do 182 | if 183 | case $arg in #( 184 | -*) false ;; # don't mess with options #( 185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 186 | [ -e "$t" ] ;; #( 187 | *) false ;; 188 | esac 189 | then 190 | arg=$( cygpath --path --ignore --mixed "$arg" ) 191 | fi 192 | # Roll the args list around exactly as many times as the number of 193 | # args, so each arg winds up back in the position where it started, but 194 | # possibly modified. 195 | # 196 | # NB: a `for` loop captures its iteration list before it begins, so 197 | # changing the positional parameters here affects neither the number of 198 | # iterations, nor the values presented in `arg`. 199 | shift # remove old arg 200 | set -- "$@" "$arg" # push replacement arg 201 | done 202 | fi 203 | 204 | 205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 207 | 208 | # Collect all arguments for the java command: 209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 210 | # and any embedded shellness will be escaped. 211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 212 | # treated as '${Hostname}' itself on the command line. 213 | 214 | set -- \ 215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 216 | -classpath "$CLASSPATH" \ 217 | org.gradle.wrapper.GradleWrapperMain \ 218 | "$@" 219 | 220 | # Stop when "xargs" is not available. 221 | if ! command -v xargs >/dev/null 2>&1 222 | then 223 | die "xargs is not available" 224 | fi 225 | 226 | # Use "xargs" to parse quoted args. 227 | # 228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 229 | # 230 | # In Bash we could simply go: 231 | # 232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 233 | # set -- "${ARGS[@]}" "$@" 234 | # 235 | # but POSIX shell has neither arrays nor command substitution, so instead we 236 | # post-process each arg (as a line of input to sed) to backslash-escape any 237 | # character that might be a shell metacharacter, then use eval to reverse 238 | # that process (while maintaining the separation between arguments), and wrap 239 | # the whole thing up as a single "set" statement. 240 | # 241 | # This will of course break if any of these variables contains a newline or 242 | # an unmatched quote. 243 | # 244 | 245 | eval "set -- $( 246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 247 | xargs -n1 | 248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 249 | tr '\n' ' ' 250 | )" '"$@"' 251 | 252 | exec "$JAVACMD" "$@" 253 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/icon/icon.png -------------------------------------------------------------------------------- /icon/icon_min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/icon/icon_min.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | mavenCentral() 8 | gradlePluginPortal() 9 | } 10 | } -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/SpecialModelLoaderAPI.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api; 2 | 3 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 4 | import dev.felnull.specialmodelloader.api.model.ModelLoader; 5 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelLoader; 6 | import dev.felnull.specialmodelloader.impl.SpecialModelLoaderAPIImpl; 7 | import net.minecraft.client.resources.model.UnbakedModel; 8 | import net.minecraft.resources.ResourceLocation; 9 | import net.minecraft.server.packs.resources.ResourceManager; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | import org.jetbrains.annotations.Unmodifiable; 13 | 14 | import java.util.List; 15 | 16 | public interface SpecialModelLoaderAPI { 17 | 18 | static SpecialModelLoaderAPI getInstance() { 19 | return SpecialModelLoaderAPIImpl.INSTANCE; 20 | } 21 | 22 | /** 23 | * A complete list of model loaders supported by this mod.
24 | * Currently, there is only an OBJ loader 25 | * 26 | * @return ModelLoader list 27 | */ 28 | @Unmodifiable 29 | @NotNull List getLoaders(); 30 | 31 | /** 32 | * A loader for reading OBJ files 33 | * 34 | * @return OBJModel Loader 35 | */ 36 | @NotNull ObjModelLoader getObjLoader(); 37 | 38 | /** 39 | * Loads a model at a specified location using the resource manager and returns the loaded resource. 40 | * 41 | * @param resourceManager ResourceManager 42 | * @param modelLocation The location of the JsonModel (e.g. minecraft:item/apple) 43 | * @return The loaded resource instances required to make the model. Null if unable to load. 44 | */ 45 | @Nullable 46 | LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull ResourceLocation modelLocation); 47 | 48 | /** 49 | * Made a model from the loaded resources. 50 | * 51 | * @param resource Resources loaded using{@link #loadResource(ResourceManager, ResourceLocation)} 52 | * @return Made model 53 | */ 54 | @NotNull 55 | UnbakedModel makeModel(@NotNull LoadedResource resource); 56 | } 57 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/data/SpecialModelDataGenHelper.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.data; 2 | 3 | import com.google.gson.JsonObject; 4 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 5 | import net.minecraft.client.data.models.model.ModelInstance; 6 | import net.minecraft.client.data.models.model.ModelLocationUtils; 7 | import net.minecraft.resources.ResourceLocation; 8 | import net.minecraft.world.item.Item; 9 | import net.minecraft.world.level.block.Block; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | import org.jetbrains.annotations.Unmodifiable; 13 | 14 | import java.util.Map; 15 | import java.util.function.BiConsumer; 16 | 17 | public final class SpecialModelDataGenHelper { 18 | private static final ResourceLocation OBJ_LOADER = ResourceLocation.fromNamespaceAndPath(SpecialModelLoader.MODID, "builtin/obj"); 19 | 20 | public static void generateObjModel(@NotNull ResourceLocation location, @NotNull ResourceLocation objLocation, 21 | boolean flipV, boolean useAmbientOcclusion, @Nullable String mtlOverride, @Unmodifiable @NotNull Map textures, 22 | @Nullable ResourceLocation particle, @NotNull BiConsumer output) { 23 | 24 | output.accept(location, () -> { 25 | var jo = new JsonObject(); 26 | jo.addProperty("parent", OBJ_LOADER.toString()); 27 | jo.addProperty("model", objLocation.toString()); 28 | jo.addProperty("flip_v", flipV); 29 | jo.addProperty("ambientocclusion", useAmbientOcclusion); 30 | 31 | if (mtlOverride != null) { 32 | jo.addProperty("mtl_override", mtlOverride); 33 | } 34 | 35 | if (!textures.isEmpty()) { 36 | JsonObject texturesJo = new JsonObject(); 37 | textures.forEach((name, loc) -> { 38 | texturesJo.addProperty(name, loc.toString()); 39 | }); 40 | jo.add("textures", texturesJo); 41 | } 42 | 43 | if (particle != null) { 44 | jo.addProperty("particle", particle.toString()); 45 | } 46 | 47 | return jo; 48 | }); 49 | } 50 | 51 | public static void generateObjModel(@NotNull Item item, @NotNull ResourceLocation objLocation, 52 | boolean flipV, boolean useAmbientOcclusion, @Nullable String mtlOverride, @Unmodifiable @NotNull Map textures, 53 | @Nullable ResourceLocation particle, @NotNull BiConsumer output) { 54 | generateObjModel(ModelLocationUtils.getModelLocation(item), objLocation, flipV, useAmbientOcclusion, mtlOverride, textures, particle, output); 55 | } 56 | 57 | public static void generateObjModel(@NotNull Block block, @NotNull ResourceLocation objLocation, 58 | boolean flipV, boolean useAmbientOcclusion, @Nullable String mtlOverride, @Unmodifiable @NotNull Map textures, 59 | @Nullable ResourceLocation particle, @NotNull BiConsumer output) { 60 | generateObjModel(ModelLocationUtils.getModelLocation(block), objLocation, flipV, useAmbientOcclusion, mtlOverride, textures, particle, output); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/event/SpecialModelLoaderEvents.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.event; 2 | 3 | import net.fabricmc.fabric.api.event.Event; 4 | import net.fabricmc.fabric.api.event.EventFactory; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.server.packs.resources.ResourceManager; 7 | 8 | import java.util.Arrays; 9 | import java.util.concurrent.CompletableFuture; 10 | import java.util.concurrent.Executor; 11 | import java.util.function.BiPredicate; 12 | import java.util.function.Predicate; 13 | 14 | public final class SpecialModelLoaderEvents { 15 | 16 | public static final Event LOAD_SCOPE = EventFactory.createArrayBacked(LoadScope.class, loadScopes -> { 17 | BiPredicate predicate = Arrays.stream(loadScopes) 18 | .map(LoadScope::provideLoadScopePredicate) 19 | .reduce(BiPredicate::or) 20 | .orElseGet(() -> (res, loc) -> false); 21 | return () -> predicate; 22 | }); 23 | 24 | public static final Event LOAD_SCOPE_ASYNC = EventFactory.createArrayBacked(AsyncLoadScope.class, loadScopes -> (resourceManager, executor) -> 25 | Arrays.stream(loadScopes) 26 | .map(it -> it.provideAsyncLoadScopePredicate(resourceManager, executor)) 27 | .reduce((cf1, cf2) -> cf1.thenCombineAsync(cf2, Predicate::or, executor)) 28 | .orElseGet(() -> CompletableFuture.completedFuture(loc -> false))); 29 | 30 | public interface LoadScope { 31 | 32 | /** 33 | * It must return a Predicate to check if the given resource location is Load Scope.
34 | * This method is called from the rendering thread, but the Predicate test is called asynchronously, so be careful not to have side effects. 35 | * 36 | * @return A predicate to check if the location is a Load Scope. 37 | */ 38 | BiPredicate provideLoadScopePredicate(); 39 | 40 | } 41 | 42 | public interface AsyncLoadScope { 43 | 44 | /** 45 | * Must return a CompletableFuture that obtains a Predicate to check if the given resource location is Load Scope.
46 | * his method is called from the rendering thread, but the Predicate test is called asynchronously, so be careful not to have side effects. 47 | * 48 | * @param resourceManager Resource Manager 49 | * @param executor Executor 50 | * @return A CompletableFuture that takes a predicate to check if the location is a load scope. 51 | */ 52 | CompletableFuture> provideAsyncLoadScopePredicate(ResourceManager resourceManager, Executor executor); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/model/LoadedResource.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.model; 2 | 3 | public interface LoadedResource { 4 | ModelLoader getLoader(); 5 | } 6 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/model/ModelLoader.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.model; 2 | 3 | import com.google.gson.JsonObject; 4 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 5 | import net.minecraft.client.resources.model.UnbakedModel; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.server.packs.resources.ResourceManager; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public interface ModelLoader { 12 | 13 | /** 14 | * Load the resource needed to create the model from the Resource Manager and Model Json. 15 | * 16 | * @param resourceManager Resource Manager 17 | * @param modelJson Model json 18 | * @return Loaded Model, null if not loaded. 19 | */ 20 | @Nullable LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull JsonObject modelJson); 21 | 22 | /** 23 | * Make model from loaded resources. 24 | * 25 | * @param loadedResource Loaded resource 26 | * @return UnbakedModel 27 | */ 28 | @NotNull UnbakedModel makeModel(@NotNull LoadedResource loadedResource); 29 | 30 | /** 31 | * Load model from Resource Manager and Model Json. 32 | * 33 | * @param resourceManager Resource Manager 34 | * @param modelJson Model json 35 | * @return UnbakedModel 36 | */ 37 | default @Nullable UnbakedModel loadModel(@NotNull ResourceManager resourceManager, @NotNull JsonObject modelJson) { 38 | LoadedResource res = loadResource(resourceManager, modelJson); 39 | 40 | if (res == null) { 41 | return null; 42 | } 43 | 44 | return makeModel(res); 45 | } 46 | 47 | /** 48 | * ID of this model loader 49 | * 50 | * @return ID 51 | */ 52 | @Nullable String getId(); 53 | 54 | /** 55 | * Whether the model uses this model loader or not. 56 | * 57 | * @param modelLocation Model Location 58 | * @return true if this loader is used, false if not. 59 | */ 60 | default boolean isLoaderLocation(@NotNull ResourceLocation modelLocation) { 61 | if (SpecialModelLoader.MODID.equals(modelLocation.getNamespace()) || "sml".equals(modelLocation.getNamespace())) 62 | return modelLocation.getPath().equals("builtin/" + getId()); 63 | return false; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/model/ModelOption.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.model; 2 | 3 | import com.google.gson.JsonObject; 4 | import dev.felnull.specialmodelloader.impl.model.ModelOptionImpl; 5 | import net.minecraft.client.renderer.block.model.BlockModel; 6 | import net.minecraft.client.renderer.block.model.ItemTransforms; 7 | import net.minecraft.resources.ResourceLocation; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public interface ModelOption { 12 | 13 | @NotNull 14 | static ModelOption of(boolean useAmbientOcclusion, @Nullable BlockModel.GuiLight guiLight, @Nullable ResourceLocation particle, @NotNull ItemTransforms transforms) { 15 | return new ModelOptionImpl(useAmbientOcclusion, guiLight, particle, transforms); 16 | } 17 | 18 | @NotNull 19 | static ModelOption parse(@NotNull JsonObject modelJson) { 20 | return ModelOptionImpl.parse(modelJson); 21 | } 22 | 23 | boolean isUseAmbientOcclusion(); 24 | 25 | @Nullable 26 | BlockModel.GuiLight getGuiLight(); 27 | 28 | @Nullable 29 | ResourceLocation getParticle(); 30 | 31 | @NotNull 32 | ItemTransforms getTransforms(); 33 | } 34 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/model/obj/ObjModelLoader.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.model.obj; 2 | 3 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 4 | import dev.felnull.specialmodelloader.api.model.ModelLoader; 5 | import net.minecraft.client.resources.model.UnbakedModel; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.server.packs.resources.ResourceManager; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public interface ObjModelLoader extends ModelLoader { 12 | 13 | /** 14 | * Load resource from OBJ file location and options. 15 | * 16 | * @param resourceManager ResourceManager 17 | * @param location OBJ Location 18 | * @param option Model Option 19 | * @return Loaded Model, null if not loaded. 20 | */ 21 | @Nullable 22 | LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull ResourceLocation location, @NotNull ObjModelOption option); 23 | 24 | /** 25 | * Load model from OBJ file location and options. 26 | * 27 | * @param resourceManager ResourceManager 28 | * @param location OBJ Location 29 | * @param option Model Option 30 | * @return UnbakedModel 31 | */ 32 | default @Nullable UnbakedModel loadModel(@NotNull ResourceManager resourceManager, @NotNull ResourceLocation location, @NotNull ObjModelOption option) { 33 | LoadedResource res = loadResource(resourceManager, location, option); 34 | 35 | if (res == null) { 36 | return null; 37 | } 38 | 39 | return makeModel(res); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/api/model/obj/ObjModelOption.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.api.model.obj; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import com.google.gson.JsonObject; 5 | import dev.felnull.specialmodelloader.api.model.ModelOption; 6 | import dev.felnull.specialmodelloader.impl.model.obj.ObjModelOptionImpl; 7 | import net.minecraft.resources.ResourceLocation; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.jetbrains.annotations.Unmodifiable; 11 | 12 | import java.util.Map; 13 | 14 | public interface ObjModelOption extends ModelOption { 15 | 16 | @NotNull 17 | static ObjModelOption of(@NotNull ModelOption modelOption, boolean flipV, 18 | String mtlOverride, Map textures) { 19 | return new ObjModelOptionImpl(modelOption, flipV, mtlOverride, ImmutableMap.copyOf(textures)); 20 | } 21 | 22 | @NotNull 23 | static ObjModelOption parse(@NotNull JsonObject modelJson) { 24 | return ObjModelOptionImpl.parse(modelJson); 25 | } 26 | 27 | boolean isFlipV(); 28 | 29 | @Nullable 30 | String getMtlOverride(); 31 | 32 | @Unmodifiable 33 | @NotNull 34 | Map getTextures(); 35 | } 36 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/SpecialModelLoaderAPIImpl.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.gson.JsonObject; 5 | import dev.felnull.specialmodelloader.api.SpecialModelLoaderAPI; 6 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 7 | import dev.felnull.specialmodelloader.api.model.ModelLoader; 8 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelLoader; 9 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 10 | import dev.felnull.specialmodelloader.impl.model.NeoForgeCompat; 11 | import dev.felnull.specialmodelloader.impl.model.obj.ObjModelLoaderImp; 12 | import dev.felnull.specialmodelloader.impl.util.JsonUtils; 13 | import net.minecraft.client.resources.model.UnbakedModel; 14 | import net.minecraft.resources.ResourceLocation; 15 | import net.minecraft.server.packs.resources.ResourceManager; 16 | import net.minecraft.util.GsonHelper; 17 | import org.apache.commons.lang3.tuple.Pair; 18 | import org.jetbrains.annotations.NotNull; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.jetbrains.annotations.Unmodifiable; 21 | 22 | import java.io.IOException; 23 | import java.util.*; 24 | 25 | public class SpecialModelLoaderAPIImpl implements SpecialModelLoaderAPI { 26 | public static final SpecialModelLoaderAPIImpl INSTANCE = new SpecialModelLoaderAPIImpl(); 27 | private final List loaders = ImmutableList.of(ObjModelLoaderImp.INSTANCE); 28 | 29 | @Override 30 | public @NotNull ObjModelLoader getObjLoader() { 31 | return ObjModelLoaderImp.INSTANCE; 32 | } 33 | 34 | @Override 35 | public @Nullable LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull ResourceLocation modelLocation) { 36 | List models = new ArrayList<>(); 37 | JsonObject jo = readJson(resourceManager, modelLocation); 38 | 39 | if (NeoForgeCompat.isEnable()) { 40 | Pair forgeModel = NeoForgeCompat.getObjModelData(jo); 41 | if (forgeModel != null) { 42 | return getObjLoader().loadResource(resourceManager, forgeModel.getLeft(), forgeModel.getRight()); 43 | } 44 | } 45 | 46 | ResourceLocation location = JsonUtils.getParentLocation(jo); 47 | Set parents = new HashSet<>(); 48 | 49 | while (location != null) { 50 | models.add(jo); 51 | 52 | if (parents.contains(location)) { 53 | SpecialModelLoader.LOGGER.warn("Model parent specification is looping: '{}', '{}'", modelLocation, location); 54 | return null; 55 | } 56 | 57 | parents.add(location); 58 | 59 | ModelLoader loader = getLoader(location); 60 | if (loader != null) { 61 | JsonObject ret = new JsonObject(); 62 | Collections.reverse(models); 63 | models.forEach(r -> r.asMap().forEach((name, rlm) -> ret.add(name, rlm.deepCopy()))); 64 | return loader.loadResource(resourceManager, ret); 65 | } 66 | 67 | jo = readJson(resourceManager, location); 68 | location = JsonUtils.getParentLocation(jo); 69 | } 70 | 71 | return null; 72 | } 73 | 74 | @Override 75 | public @NotNull UnbakedModel makeModel(@NotNull LoadedResource resource) { 76 | return resource.getLoader().makeModel(resource); 77 | } 78 | 79 | @Override 80 | public @Unmodifiable @NotNull List getLoaders() { 81 | return loaders; 82 | } 83 | 84 | private ModelLoader getLoader(ResourceLocation location) { 85 | return getLoaders().stream() 86 | .filter(r -> r.isLoaderLocation(location)) 87 | .limit(1) 88 | .findFirst() 89 | .orElse(null); 90 | } 91 | 92 | private JsonObject readJson(ResourceManager resourceManager, ResourceLocation modelLocation) { 93 | ResourceLocation modelPath = ResourceLocation.fromNamespaceAndPath(modelLocation.getNamespace(), "models/" + modelLocation.getPath() + ".json"); 94 | var res = resourceManager.getResource(modelPath); 95 | if (res.isEmpty()) return null; 96 | JsonObject jo; 97 | try (var reader = res.get().openAsReader()) { 98 | jo = GsonHelper.parse(reader); 99 | } catch (IOException ex) { 100 | throw new IllegalStateException("Failed to load json: " + modelLocation, ex); 101 | } 102 | return jo; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/SpecialModelLoaderClient.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl; 2 | 3 | import dev.felnull.specialmodelloader.impl.handler.SMLClientHandler; 4 | import dev.felnull.specialmodelloader.impl.handler.SMLModelLoadingHandler; 5 | import dev.felnull.specialmodelloader.impl.model.NeoForgeCompat; 6 | import net.fabricmc.api.ClientModInitializer; 7 | 8 | public class SpecialModelLoaderClient implements ClientModInitializer { 9 | 10 | @Override 11 | public void onInitializeClient() { 12 | SMLClientHandler.init(); 13 | SMLModelLoadingHandler.init(); 14 | NeoForgeCompat.init(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/handler/SMLClientHandler.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.handler; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonObject; 8 | import dev.felnull.specialmodelloader.api.event.SpecialModelLoaderEvents; 9 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 10 | import net.minecraft.resources.ResourceLocation; 11 | import net.minecraft.server.packs.resources.ResourceManager; 12 | 13 | import java.io.Reader; 14 | import java.util.concurrent.CompletableFuture; 15 | import java.util.concurrent.Executor; 16 | import java.util.function.BiPredicate; 17 | import java.util.function.Predicate; 18 | import java.util.regex.Pattern; 19 | 20 | public class SMLClientHandler { 21 | private static final Gson GSON = new Gson(); 22 | private static final String MANUAL_LOAD_SCOPE_RESOURCE_NAME = "sml_load_scopes"; 23 | 24 | public static void init() { 25 | SpecialModelLoaderEvents.LOAD_SCOPE_ASYNC.register(SMLClientHandler::provideSimpleLoadScopePredicate); 26 | SpecialModelLoaderEvents.LOAD_SCOPE_ASYNC.register(SMLClientHandler::provideManualLoadScopePredicate); 27 | } 28 | 29 | private static CompletableFuture> provideSimpleLoadScopePredicate(ResourceManager resourceManager, Executor executor) { 30 | BiPredicate predicate = SpecialModelLoaderEvents.LOAD_SCOPE.invoker().provideLoadScopePredicate(); 31 | return CompletableFuture.supplyAsync(() -> loc -> predicate.test(resourceManager, loc), executor); 32 | } 33 | 34 | private static CompletableFuture> provideManualLoadScopePredicate(ResourceManager resourceManager, Executor executor) { 35 | return CompletableFuture.supplyAsync(() -> { 36 | 37 | ImmutableSet.Builder patternsBuilder = new ImmutableSet.Builder<>(); 38 | 39 | resourceManager.listResources(MANUAL_LOAD_SCOPE_RESOURCE_NAME, loc -> loc.getPath().endsWith(".json")).forEach((location, resource) -> { 40 | try (Reader reader = resource.openAsReader()) { 41 | JsonObject jo = GSON.fromJson(reader, JsonObject.class); 42 | loadManualLoadScope(patternsBuilder, jo); 43 | } catch (Exception e) { 44 | SpecialModelLoader.LOGGER.error("Error occurred while loading model load scope resource json {}", location, e); 45 | } 46 | }); 47 | 48 | final ImmutableSet patterns = patternsBuilder.build(); 49 | int size = patterns.size(); 50 | if (size >= 1) { 51 | SpecialModelLoader.LOGGER.info("Loaded {} manual model load scope", size); 52 | } 53 | 54 | return loc -> patterns.stream() 55 | .anyMatch(pattern -> pattern.matcher(loc.toString()).matches()); 56 | }, executor); 57 | } 58 | 59 | private static void loadManualLoadScope(ImmutableSet.Builder builder, JsonObject jsonObject) { 60 | 61 | if (!jsonObject.has("version") || !jsonObject.get("version").isJsonPrimitive() || !jsonObject.getAsJsonPrimitive("version").isNumber()) { 62 | throw new IllegalStateException("Unknown version"); 63 | } 64 | 65 | int version = jsonObject.getAsJsonPrimitive("version").getAsInt(); 66 | 67 | if (version != 1) { 68 | throw new IllegalStateException("Unsupported version"); 69 | } 70 | 71 | if (!jsonObject.has("entry") || !jsonObject.get("entry").isJsonArray()) { 72 | return; 73 | } 74 | 75 | JsonArray entries = jsonObject.getAsJsonArray("entry"); 76 | for (JsonElement entry : entries) { 77 | if (entry.isJsonPrimitive() && entry.getAsJsonPrimitive().isString()) { 78 | builder.add(Pattern.compile(entry.getAsString())); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/handler/SMLModelLoadingHandler.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.handler; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import dev.felnull.specialmodelloader.api.SpecialModelLoaderAPI; 5 | import dev.felnull.specialmodelloader.api.event.SpecialModelLoaderEvents; 6 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 7 | import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; 8 | import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; 9 | import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; 10 | import net.minecraft.client.resources.model.UnbakedModel; 11 | import net.minecraft.resources.ResourceLocation; 12 | import net.minecraft.server.packs.resources.ResourceManager; 13 | 14 | import java.util.Map; 15 | import java.util.concurrent.CompletableFuture; 16 | import java.util.concurrent.Executor; 17 | import java.util.function.Predicate; 18 | 19 | public final class SMLModelLoadingHandler { 20 | 21 | public static void init() { 22 | PreparableModelLoadingPlugin.register(SMLModelLoadingHandler::loadPrepareData, new MyModelLoadingPlugin()); 23 | } 24 | 25 | private static UnbakedModel modifyModelOnLoad(PreparationData data, UnbakedModel original, ModelModifier.OnLoad.Context context) { 26 | 27 | ResourceLocation resId = context.id(); 28 | if (resId != null) { 29 | LoadedResource loadedResource = data.resources().get(resId); 30 | if (loadedResource != null) { 31 | return SpecialModelLoaderAPI.getInstance().makeModel(loadedResource); 32 | } 33 | } 34 | 35 | return original; 36 | } 37 | 38 | private static CompletableFuture loadPrepareData(ResourceManager resourceManager, Executor executor) { 39 | CompletableFuture> loadScopePredicates = SpecialModelLoaderEvents.LOAD_SCOPE_ASYNC.invoker().provideAsyncLoadScopePredicate(resourceManager, executor); 40 | return loadScopePredicates.thenApplyAsync((lpPre) -> { 41 | ImmutableMap.Builder resBuilder = ImmutableMap.builder(); 42 | 43 | resourceManager.listResources("models", loc -> loc.getPath().endsWith(".json")).forEach((location, resource) -> { 44 | String path = location.getPath().substring("models/".length()); 45 | path = path.substring(0, path.length() - ".json".length()); 46 | ResourceLocation modelLoc = ResourceLocation.fromNamespaceAndPath(location.getNamespace(), path); 47 | 48 | if (!lpPre.test(modelLoc)) { 49 | return; 50 | } 51 | 52 | LoadedResource res = SpecialModelLoaderAPI.getInstance().loadResource(resourceManager, modelLoc); 53 | if (res != null) { 54 | resBuilder.put(modelLoc, res); 55 | } 56 | }); 57 | 58 | return new PreparationData(resBuilder.build()); 59 | }, executor); 60 | } 61 | 62 | private static class MyModelLoadingPlugin implements PreparableModelLoadingPlugin { 63 | @Override 64 | public void initialize(PreparationData data, ModelLoadingPlugin.Context pluginContext) { 65 | pluginContext.modifyModelOnLoad().register((model, context) -> modifyModelOnLoad(data, model, context)); 66 | } 67 | } 68 | 69 | private record PreparationData(Map resources) { 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/handler/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl.handler; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/mixin/BlockModelAccessor.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.mixin; 2 | 3 | import com.google.gson.Gson; 4 | import net.minecraft.client.renderer.block.model.BlockModel; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(BlockModel.class) 9 | public interface BlockModelAccessor { 10 | @Accessor("GSON") 11 | static Gson getGson() { 12 | throw new AssertionError(); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/mixin/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl.mixin; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/ModelOptionImpl.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model; 2 | 3 | import com.google.gson.JsonObject; 4 | import dev.felnull.specialmodelloader.api.model.ModelOption; 5 | import dev.felnull.specialmodelloader.impl.mixin.BlockModelAccessor; 6 | import net.minecraft.client.renderer.block.model.BlockModel; 7 | import net.minecraft.client.renderer.block.model.ItemTransforms; 8 | import net.minecraft.resources.ResourceLocation; 9 | import net.minecraft.util.GsonHelper; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | public record ModelOptionImpl(boolean useAmbientOcclusion, BlockModel.GuiLight guiLight, ResourceLocation particle, 14 | ItemTransforms transforms) implements ModelOption { 15 | 16 | public static ModelOptionImpl parse(JsonObject modelJson) { 17 | ItemTransforms transform = ItemTransforms.NO_TRANSFORMS; 18 | 19 | if (modelJson.has("display")) { 20 | var jo = GsonHelper.getAsJsonObject(modelJson, "display"); 21 | transform = BlockModelAccessor.getGson().fromJson(jo, ItemTransforms.class); 22 | } 23 | 24 | BlockModel.GuiLight guiLight = null; 25 | if (modelJson.has("gui_light")) 26 | guiLight = BlockModel.GuiLight.getByName(GsonHelper.getAsString(modelJson, "gui_light")); 27 | 28 | ResourceLocation particle = null; 29 | if (modelJson.has("particle")) 30 | particle = ResourceLocation.parse(GsonHelper.getAsString(modelJson, "particle")); 31 | 32 | return new ModelOptionImpl(GsonHelper.getAsBoolean(modelJson, "ambientocclusion", true), guiLight, particle, transform); 33 | } 34 | 35 | @Override 36 | public boolean isUseAmbientOcclusion() { 37 | return useAmbientOcclusion; 38 | } 39 | 40 | @Override 41 | public @Nullable BlockModel.GuiLight getGuiLight() { 42 | return guiLight; 43 | } 44 | 45 | @Override 46 | public @Nullable ResourceLocation getParticle() { 47 | return particle; 48 | } 49 | 50 | @Override 51 | public @NotNull ItemTransforms getTransforms() { 52 | return transforms; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/NeoForgeCompat.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model; 2 | 3 | import com.google.gson.JsonObject; 4 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 5 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 6 | import dev.felnull.specialmodelloader.impl.util.JsonUtils; 7 | import net.fabricmc.loader.api.FabricLoader; 8 | import net.minecraft.resources.ResourceLocation; 9 | import org.apache.commons.lang3.tuple.Pair; 10 | 11 | /** 12 | * Compatibility to load models in formats supported by NeoForge 13 | */ 14 | public final class NeoForgeCompat { 15 | private static final ResourceLocation NEO_FORGE_OBJ = ResourceLocation.fromNamespaceAndPath("neoforge", "obj"); 16 | 17 | public static void init() { 18 | if (FabricLoader.getInstance().isModLoaded("connector")) { 19 | SpecialModelLoader.LOGGER.info("Sinytra Connector detected."); 20 | SpecialModelLoader.LOGGER.info("Disable NeoForge compatibility for OBJ loader."); 21 | } 22 | } 23 | 24 | public static boolean isEnable() { 25 | // If the Sinytra Connector is present, disable compatibility as it was launched in NeoForge 26 | // https://sinytra.org/docs/connector/developers 27 | return !FabricLoader.getInstance().isModLoaded("connector"); 28 | } 29 | 30 | public static Pair getObjModelData(JsonObject modelJson) { 31 | if (modelJson == null) { 32 | return null; 33 | } 34 | 35 | // https://docs.neoforged.net/docs/resources/client/models/modelloaders/#obj-model 36 | 37 | ResourceLocation loaderLoc = JsonUtils.getResourceLocation(modelJson, "loader"); 38 | if (!NEO_FORGE_OBJ.equals(loaderLoc)) { 39 | return null; 40 | } 41 | 42 | ResourceLocation model = JsonUtils.getResourceLocation(modelJson, "model"); 43 | if (model == null) { 44 | return null; 45 | } 46 | 47 | return Pair.of(model, ObjModelOption.parse(modelJson)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/SimpleMeshModel.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model; 2 | 3 | import com.google.common.base.Suppliers; 4 | import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; 5 | import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; 6 | import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; 7 | import net.minecraft.client.renderer.block.model.BakedQuad; 8 | import net.minecraft.client.renderer.block.model.ItemTransforms; 9 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 10 | import net.minecraft.core.BlockPos; 11 | import net.minecraft.core.Direction; 12 | import net.minecraft.util.RandomSource; 13 | import net.minecraft.world.level.BlockAndTintGetter; 14 | import net.minecraft.world.level.block.state.BlockState; 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | import java.util.List; 19 | import java.util.function.Predicate; 20 | import java.util.function.Supplier; 21 | 22 | public class SimpleMeshModel extends SpecialBaseModel { 23 | private final Mesh mesh; 24 | private final Supplier[]> quadCache; 25 | 26 | public SimpleMeshModel(boolean useAmbientOcclusion, boolean usesBlockLight, TextureAtlasSprite particleIcon, ItemTransforms transforms, Mesh mesh) { 27 | super(useAmbientOcclusion, usesBlockLight, particleIcon, transforms); 28 | this.mesh = mesh; 29 | this.quadCache = Suppliers.memoize(() -> ModelHelper.toQuadLists(mesh)); 30 | } 31 | 32 | @Override 33 | public void emitBlockQuads(QuadEmitter emitter, BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, Predicate<@Nullable Direction> cullTest) { 34 | mesh.outputTo(emitter); 35 | } 36 | 37 | @Override 38 | public void emitItemQuads(QuadEmitter emitter, Supplier randomSupplier) { 39 | mesh.outputTo(emitter); 40 | } 41 | 42 | @Override 43 | public @NotNull List getQuads(@Nullable BlockState blockState, @Nullable Direction direction, RandomSource randomSource) { 44 | return this.quadCache.get()[ModelHelper.toFaceIndex(direction)]; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/SpecialBaseModel.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model; 2 | 3 | import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; 4 | import net.minecraft.client.renderer.block.model.ItemTransforms; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import net.minecraft.client.resources.model.BakedModel; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public abstract class SpecialBaseModel implements BakedModel, FabricBakedModel { 10 | private final boolean useAmbientOcclusion; 11 | private final boolean usesBlockLight; 12 | private final TextureAtlasSprite particleIcon; 13 | private final ItemTransforms transforms; 14 | 15 | protected SpecialBaseModel(boolean useAmbientOcclusion, boolean usesBlockLight, TextureAtlasSprite particleIcon, ItemTransforms transforms) { 16 | this.useAmbientOcclusion = useAmbientOcclusion; 17 | this.usesBlockLight = usesBlockLight; 18 | this.particleIcon = particleIcon; 19 | this.transforms = transforms; 20 | } 21 | 22 | @Override 23 | public boolean isVanillaAdapter() { 24 | return false; 25 | } 26 | 27 | @Override 28 | public boolean useAmbientOcclusion() { 29 | return useAmbientOcclusion; 30 | } 31 | 32 | @Override 33 | public boolean isGui3d() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public boolean usesBlockLight() { 39 | return usesBlockLight; 40 | } 41 | 42 | @Override 43 | public @NotNull TextureAtlasSprite getParticleIcon() { 44 | return particleIcon; 45 | } 46 | 47 | @Override 48 | public @NotNull ItemTransforms getTransforms() { 49 | return transforms; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/SpecialBaseUnbakedModel.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model; 2 | 3 | import dev.felnull.specialmodelloader.api.model.ModelOption; 4 | import net.minecraft.client.renderer.block.model.BlockModel; 5 | import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; 6 | import net.minecraft.client.renderer.texture.TextureAtlas; 7 | import net.minecraft.client.resources.model.Material; 8 | import net.minecraft.client.resources.model.UnbakedModel; 9 | 10 | public abstract class SpecialBaseUnbakedModel implements UnbakedModel { 11 | protected static final Material MISSING = new Material(TextureAtlas.LOCATION_BLOCKS, MissingTextureAtlasSprite.getLocation()); 12 | private final ModelOption modelOption; 13 | 14 | protected SpecialBaseUnbakedModel(ModelOption modelOption) { 15 | this.modelOption = modelOption; 16 | } 17 | 18 | public ModelOption getModelOption() { 19 | return modelOption; 20 | } 21 | 22 | public Material getParticleLocation() { 23 | if (modelOption.getParticle() != null) 24 | return new Material(TextureAtlas.LOCATION_BLOCKS, modelOption.getParticle()); 25 | return MISSING; 26 | } 27 | 28 | public BlockModel.GuiLight getGuiLight() { 29 | if (modelOption.getGuiLight() == null) 30 | return BlockModel.GuiLight.SIDE; 31 | return modelOption.getGuiLight(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/obj/ObjModelLoadedResource.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model.obj; 2 | 3 | import de.javagl.obj.Mtl; 4 | import de.javagl.obj.Obj; 5 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 6 | import dev.felnull.specialmodelloader.api.model.ModelLoader; 7 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 8 | import net.minecraft.resources.ResourceLocation; 9 | 10 | import java.util.Map; 11 | 12 | record ObjModelLoadedResource(ResourceLocation location, 13 | Obj obj, 14 | Map mtl, 15 | ObjModelOption option) implements LoadedResource { 16 | @Override 17 | public ModelLoader getLoader() { 18 | return ObjModelLoaderImp.INSTANCE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/obj/ObjModelLoaderImp.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model.obj; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.collect.ImmutableMap; 5 | import com.google.gson.JsonObject; 6 | import de.javagl.obj.*; 7 | import dev.felnull.specialmodelloader.api.model.LoadedResource; 8 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelLoader; 9 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 10 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 11 | import net.minecraft.client.resources.model.UnbakedModel; 12 | import net.minecraft.resources.ResourceLocation; 13 | import net.minecraft.server.packs.resources.Resource; 14 | import net.minecraft.server.packs.resources.ResourceManager; 15 | import org.apache.commons.lang3.ArrayUtils; 16 | import org.jetbrains.annotations.NotNull; 17 | import org.jetbrains.annotations.Nullable; 18 | 19 | import java.io.IOException; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.Optional; 24 | import java.util.stream.Collectors; 25 | 26 | public class ObjModelLoaderImp implements ObjModelLoader { 27 | public static final ObjModelLoaderImp INSTANCE = new ObjModelLoaderImp(); 28 | 29 | @Override 30 | public @Nullable LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull JsonObject modelJson) { 31 | if (!modelJson.has("model") || !modelJson.get("model").isJsonPrimitive() || !modelJson.getAsJsonPrimitive("model").isString()) { 32 | return null; 33 | } 34 | 35 | ResourceLocation modelLocation = ResourceLocation.parse(modelJson.get("model").getAsString()); 36 | 37 | return loadResource(resourceManager, modelLocation, ObjModelOption.parse(modelJson)); 38 | } 39 | 40 | @Override 41 | public @Nullable LoadedResource loadResource(@NotNull ResourceManager resourceManager, @NotNull ResourceLocation modelLocation, @NotNull ObjModelOption option) { 42 | Optional res = resourceManager.getResource(modelLocation); 43 | 44 | if (res.isEmpty()) { 45 | return null; 46 | } 47 | 48 | try (var reader = res.get().openAsReader()) { 49 | Obj obj = ObjUtils.convertToRenderable(ObjReader.read(reader)); 50 | 51 | ResourceLocation mtlDirLoc; 52 | List mtlFileNames; 53 | 54 | String mtlOverride; 55 | if ((mtlOverride = option.getMtlOverride()) != null) { 56 | String[] overrideSplit = mtlOverride.split("/"); 57 | 58 | mtlDirLoc = ResourceLocation.parse(String.join("/", ArrayUtils.remove(overrideSplit, overrideSplit.length - 1))); 59 | mtlFileNames = ImmutableList.of(overrideSplit[overrideSplit.length - 1]); 60 | } else { 61 | String[] mtlDirPaths = modelLocation.getPath().split("/"); 62 | mtlDirPaths = ArrayUtils.remove(mtlDirPaths, mtlDirPaths.length - 1); 63 | 64 | mtlDirLoc = ResourceLocation.fromNamespaceAndPath(modelLocation.getNamespace(), String.join("/", mtlDirPaths)); 65 | mtlFileNames = obj.getMtlFileNames(); 66 | } 67 | 68 | return new ObjModelLoadedResource(modelLocation, obj, 69 | ImmutableMap.copyOf(loadMtl(resourceManager, mtlDirLoc, mtlFileNames)), option); 70 | } catch (IOException e) { 71 | throw new IllegalStateException("Failed to load obj file.", e); 72 | } 73 | } 74 | 75 | @Override 76 | public @NotNull UnbakedModel makeModel(@NotNull LoadedResource loadedResource) { 77 | if (loadedResource instanceof ObjModelLoadedResource objRes) { 78 | return new ObjUnbakedModelModel(objRes.location(), objRes.obj(), objRes.mtl(), objRes.option()); 79 | } else { 80 | throw new IllegalArgumentException("A loaded resource that is not an OBJ model was received as an argument."); 81 | } 82 | } 83 | 84 | private Map loadMtl(ResourceManager resourceManager, ResourceLocation location, List mtlNames) { 85 | return mtlNames.stream() 86 | .flatMap(r -> loadMtl(resourceManager, location, r).stream()) 87 | .collect(Collectors.toMap(Mtl::getName, r -> r)); 88 | } 89 | 90 | private List loadMtl(ResourceManager resourceManager, ResourceLocation location, String mtlName) { 91 | var loc = ResourceLocation.fromNamespaceAndPath(location.getNamespace(), location.getPath() + "/" + mtlName); 92 | return resourceManager.getResource(loc).map(res -> { 93 | try (var reader = res.openAsReader()) { 94 | return MtlReader.read(reader); 95 | } catch (IOException e) { 96 | SpecialModelLoader.LOGGER.error("Failed to read mtl file.", e); 97 | return new ArrayList(); 98 | } 99 | }).orElseGet(List::of); 100 | } 101 | 102 | @Override 103 | public String getId() { 104 | return "obj"; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/obj/ObjModelOptionImpl.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model.obj; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import com.google.gson.JsonObject; 5 | import dev.felnull.specialmodelloader.api.model.ModelOption; 6 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 7 | import dev.felnull.specialmodelloader.impl.util.JsonUtils; 8 | import net.minecraft.client.renderer.block.model.BlockModel; 9 | import net.minecraft.client.renderer.block.model.ItemTransforms; 10 | import net.minecraft.resources.ResourceLocation; 11 | import net.minecraft.util.GsonHelper; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | import org.jetbrains.annotations.Unmodifiable; 15 | 16 | import java.util.Map; 17 | 18 | public record ObjModelOptionImpl(ModelOption modelOption, boolean flipV, String mtlOverride, 19 | Map textures) implements ObjModelOption { 20 | 21 | public static ObjModelOptionImpl parse(JsonObject modelJson) { 22 | boolean flipV = GsonHelper.getAsBoolean(modelJson, "flip_v", false); 23 | String mtlOverride = GsonHelper.getAsString(modelJson, "mtl_override", null); 24 | 25 | ImmutableMap.Builder textures = ImmutableMap.builder(); 26 | if (modelJson.has("textures") && modelJson.get("textures").isJsonObject()) { 27 | JsonObject texturesJo = modelJson.getAsJsonObject("textures"); 28 | texturesJo.keySet().forEach(key -> { 29 | ResourceLocation tex = JsonUtils.getResourceLocation(texturesJo, key); 30 | if (tex != null) { 31 | textures.put(key, tex); 32 | } 33 | }); 34 | } 35 | 36 | return new ObjModelOptionImpl(ModelOption.parse(modelJson), flipV, mtlOverride, textures.build()); 37 | } 38 | 39 | @Override 40 | public boolean isFlipV() { 41 | return flipV; 42 | } 43 | 44 | @Nullable 45 | @Override 46 | public String getMtlOverride() { 47 | return mtlOverride; 48 | } 49 | 50 | @Override 51 | public @Unmodifiable @NotNull Map getTextures() { 52 | return textures; 53 | } 54 | 55 | @Override 56 | public boolean isUseAmbientOcclusion() { 57 | return modelOption.isUseAmbientOcclusion(); 58 | } 59 | 60 | @Override 61 | public @Nullable BlockModel.GuiLight getGuiLight() { 62 | return modelOption.getGuiLight(); 63 | } 64 | 65 | @Override 66 | public @Nullable ResourceLocation getParticle() { 67 | return modelOption.getParticle(); 68 | } 69 | 70 | @Override 71 | public @NotNull ItemTransforms getTransforms() { 72 | return modelOption.getTransforms(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/obj/ObjUnbakedModelModel.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.model.obj; 2 | 3 | import de.javagl.obj.Mtl; 4 | import de.javagl.obj.Obj; 5 | import de.javagl.obj.ObjFace; 6 | import de.javagl.obj.ObjSplitting; 7 | import dev.felnull.specialmodelloader.api.model.obj.ObjModelOption; 8 | import dev.felnull.specialmodelloader.impl.SpecialModelLoader; 9 | import dev.felnull.specialmodelloader.impl.model.SimpleMeshModel; 10 | import dev.felnull.specialmodelloader.impl.model.SpecialBaseUnbakedModel; 11 | import net.fabricmc.fabric.api.renderer.v1.Renderer; 12 | import net.fabricmc.fabric.api.renderer.v1.mesh.MutableMesh; 13 | import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; 14 | import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; 15 | import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer; 16 | import net.minecraft.client.renderer.block.model.ItemTransforms; 17 | import net.minecraft.client.renderer.block.model.TextureSlots; 18 | import net.minecraft.client.renderer.texture.TextureAtlas; 19 | import net.minecraft.client.resources.model.*; 20 | import net.minecraft.resources.ResourceLocation; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.joml.Vector3f; 23 | 24 | import java.util.Map; 25 | 26 | public class ObjUnbakedModelModel extends SpecialBaseUnbakedModel { 27 | private final ResourceLocation location; 28 | private final Obj obj; 29 | private final Map mtl; 30 | private final ObjModelOption option; 31 | 32 | public ObjUnbakedModelModel(ResourceLocation location, Obj obj, Map mtl, ObjModelOption option) { 33 | super(option); 34 | this.location = location; 35 | this.obj = obj; 36 | this.mtl = mtl; 37 | this.option = option; 38 | } 39 | 40 | @Override 41 | public void resolveDependencies(Resolver resolver) { 42 | } 43 | 44 | @Override 45 | public @NotNull BakedModel bake(TextureSlots textureSlots, ModelBaker baker, ModelState modelState, boolean hasAmbientOcclusion, boolean useBlockLight, ItemTransforms transforms) { 46 | Renderer renderer = Renderer.get(); 47 | 48 | if (renderer == null) { 49 | SpecialModelLoader.LOGGER.warn("IndigoRenderer is used since the Renderer cannot be obtained. ({})", location); 50 | renderer = IndigoRenderer.INSTANCE; 51 | } 52 | 53 | MutableMesh builder = renderer.mutableMesh(); 54 | QuadEmitter emitter = builder.emitter(); 55 | SpriteGetter spriteGetter = baker.sprites(); 56 | Map materialGroups = ObjSplitting.splitByMaterialGroups(obj); 57 | 58 | materialGroups.forEach((name, model) -> { 59 | for (int i = 0; i < model.getNumFaces(); i++) { 60 | emitFace(emitter, modelState, spriteGetter, name, model, model.getFace(i)); 61 | } 62 | }); 63 | 64 | return new SimpleMeshModel( 65 | getModelOption().isUseAmbientOcclusion(), 66 | getGuiLight().lightLikeBlock(), 67 | spriteGetter.get(getParticleLocation()), 68 | getModelOption().getTransforms(), 69 | builder.immutableCopy() 70 | ); 71 | } 72 | 73 | private void emitFace(QuadEmitter emitter, ModelState modelState, SpriteGetter spriteGetter, String materialName, Obj fObj, ObjFace face) { 74 | for (int i = 0; i < face.getNumVertices(); i++) { 75 | emitVertex(i, i, emitter, modelState, fObj, face); 76 | } 77 | 78 | if (face.getNumVertices() == 3) 79 | emitVertex(3, 2, emitter, modelState, fObj, face); 80 | 81 | var smtl = mtl.get(materialName); 82 | 83 | int flg = MutableQuadView.BAKE_NORMALIZED; 84 | 85 | if (option.isFlipV()) 86 | flg |= MutableQuadView.BAKE_FLIP_V; 87 | 88 | if (modelState.isUvLocked()) 89 | flg |= MutableQuadView.BAKE_LOCK_UV; 90 | 91 | ResourceLocation texLoc = null; 92 | String tex; 93 | if (smtl != null && (tex = smtl.getMapKd()) != null) { 94 | if (tex.startsWith("#")) { 95 | texLoc = option.getTextures().get(tex.substring(1)); 96 | } else { 97 | texLoc = ResourceLocation.parse(tex); 98 | } 99 | } 100 | 101 | if (texLoc != null) { 102 | emitter.spriteBake(spriteGetter.get(new Material(TextureAtlas.LOCATION_BLOCKS, texLoc)), flg); 103 | } else { 104 | emitter.spriteBake(spriteGetter.get(MISSING), flg); 105 | } 106 | 107 | emitter.color(-1, -1, -1, -1); 108 | 109 | emitter.emit(); 110 | } 111 | 112 | private void emitVertex(int index, int vertexNum, QuadEmitter emitter, ModelState modelState, Obj fObj, ObjFace face) { 113 | var vt = fObj.getVertex(face.getVertexIndex(vertexNum)); 114 | var vertex = new Vector3f(vt.getX(), vt.getY(), vt.getZ()); 115 | 116 | vertex.add(-0.5f, -0.5f, -0.5f); 117 | vertex.rotate(modelState.getRotation().getLeftRotation()); 118 | vertex.add(0.5f, 0.5f, 0.5f); 119 | 120 | var normal = fObj.getNormal(face.getNormalIndex(vertexNum)); 121 | var tex = fObj.getTexCoord(face.getTexCoordIndex(vertexNum)); 122 | 123 | emitter.pos(index, vertex.x(), vertex.y(), vertex.z()) 124 | .normal(index, normal.getX(), normal.getY(), normal.getZ()) 125 | .uv(index, tex.getX(), tex.getY()); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/obj/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl.model.obj; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/model/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl.model; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/util/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl.util; 2 | 3 | import com.google.gson.JsonObject; 4 | import net.minecraft.resources.ResourceLocation; 5 | import net.minecraft.util.GsonHelper; 6 | 7 | public class JsonUtils { 8 | public static ResourceLocation getParentLocation(JsonObject modelJson) { 9 | if (modelJson == null) 10 | return null; 11 | 12 | if (modelJson.has("parent")) 13 | return ResourceLocation.parse(GsonHelper.getAsString(modelJson, "parent")); 14 | return null; 15 | } 16 | 17 | public static ResourceLocation getResourceLocation(JsonObject jsonObject, String name) { 18 | if (jsonObject.has(name) && jsonObject.get(name).isJsonPrimitive() && jsonObject.getAsJsonPrimitive(name).isString()) { 19 | return ResourceLocation.parse(jsonObject.get(name).getAsString()); 20 | } 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/client/java/dev/felnull/specialmodelloader/impl/util/package-info.java: -------------------------------------------------------------------------------- 1 | @ApiStatus.Internal 2 | package dev.felnull.specialmodelloader.impl.util; 3 | 4 | import org.jetbrains.annotations.ApiStatus; -------------------------------------------------------------------------------- /src/client/resources/special-model-loader.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "dev.felnull.specialmodelloader.impl.mixin", 4 | "compatibilityLevel": "JAVA_21", 5 | "client": [ 6 | "BlockModelAccessor" 7 | ], 8 | "injectors": { 9 | "defaultRequire": 1 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/dev/felnull/specialmodelloader/impl/SpecialModelLoader.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.specialmodelloader.impl; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | public class SpecialModelLoader { 7 | public static final Logger LOGGER = LogManager.getLogger(SpecialModelLoader.class); 8 | public static final String MODID = "special-model-loader"; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/assets/special-model-loader/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/main/resources/assets/special-model-loader/icon.png -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "special-model-loader", 4 | "version": "${version}", 5 | "name": "Special Model Loader", 6 | "description": "Support for loading special models.\nThe ikisugi model loader mod...", 7 | "authors": [ 8 | "MORIMORI0317", 9 | "FelNull Developers" 10 | ], 11 | "contributors": [ 12 | "StarBoyCeleste", 13 | "MerlinDaWizard" 14 | ], 15 | "contact": { 16 | "email": "teamfelnull@felnull.dev", 17 | "homepage": "https://modrinth.com/mod/special-model-loader", 18 | "sources": "https://github.com/TeamFelnull/SpecialModelLoader", 19 | "issues": "https://github.com/TeamFelnull/SpecialModelLoader/issues" 20 | }, 21 | "license": "MIT License", 22 | "icon": "assets/special-model-loader/icon.png", 23 | "environment": "client", 24 | "entrypoints": { 25 | "client": [ 26 | "dev.felnull.specialmodelloader.impl.SpecialModelLoaderClient" 27 | ] 28 | }, 29 | "mixins": [ 30 | { 31 | "config": "special-model-loader.mixins.json", 32 | "environment": "client" 33 | } 34 | ], 35 | "depends": { 36 | "fabricloader": ">=0.16.9", 37 | "minecraft": ">=1.21.4", 38 | "java": ">=21", 39 | "fabric-api": "*" 40 | }, 41 | "custom": { 42 | "modmenu": { 43 | "badges": [ 44 | "library" 45 | ] 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/generated/.cache/d26dbd274f1ce9df6c32c695a40e10fe4203dafa: -------------------------------------------------------------------------------- 1 | // 1.21.4 -999999999-01-01T00:00:00 Special Model Loader Test/Model Definitions 2 | 2fe12a7b7f26a1434370749403837d2301d330c4 assets/special-model-loader-test/blockstates/facing_model_block.json 3 | 2026021089f1eb67bb59680a39566b65319b9c1d assets/special-model-loader-test/blockstates/facing_obj_model_block.json 4 | 09d86e9b817b52a30a7afdc219645cb7f67cd5c8 assets/special-model-loader-test/blockstates/normal_model_block.json 5 | 2a6689e3962f0c56716ee7a2840038d8e1c6f65d assets/special-model-loader-test/items/facing_model_block.json 6 | db12e0af083675fa1ab711028e4f2d7fe81d7644 assets/special-model-loader-test/items/facing_obj_model_block.json 7 | 5da9262165426aa448e0b149c06cb5baf1f2d119 assets/special-model-loader-test/items/mtloverride_obj_model_item.json 8 | e9bb5e2f398bccd6253053b120344d1b7b0b7385 assets/special-model-loader-test/items/normal_model_block.json 9 | 1fd027e47bb05c0928fc934bcf6c3cfb85ad90b8 assets/special-model-loader-test/items/normal_model_item.json 10 | 0ca9dcce673b914bf2c74024d4b2b7ef7303d268 assets/special-model-loader-test/items/obj_model_block.json 11 | 08d17fdf5d40bca50f52581e517c952a837994a5 assets/special-model-loader-test/items/obj_model_item.json 12 | b744e088d55e2ea5a1d9ea27b93c720a3356e8ec assets/special-model-loader-test/items/textures_obj_model_item.json 13 | e61360716d4882fb639d854551e14f9a9130c6ac assets/special-model-loader-test/models/block/facing_model_block.json 14 | d8c8c782516cf0bc564998dcaed70a1592d59fb7 assets/special-model-loader-test/models/block/normal_model_block.json 15 | 900ce8dcc85cb9354e94b586092cb1fb2c2bc204 assets/special-model-loader-test/models/item/mtloverride_obj_model_item.json 16 | 29b5a4f3bf537fd7d26d638c82162277ceed8152 assets/special-model-loader-test/models/item/normal_model_item.json 17 | 92aa0969bc41ff465724c5cce1982fc91c53a428 assets/special-model-loader-test/models/item/obj_model_item.json 18 | b86b8a89c6b8c2cd5f75410589c716570e9c4b7d assets/special-model-loader-test/models/item/textures_obj_model_item.json 19 | -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/blockstates/facing_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "facing=east": { 4 | "model": "special-model-loader-test:block/facing_model_block", 5 | "y": 90 6 | }, 7 | "facing=north": { 8 | "model": "special-model-loader-test:block/facing_model_block" 9 | }, 10 | "facing=south": { 11 | "model": "special-model-loader-test:block/facing_model_block", 12 | "y": 180 13 | }, 14 | "facing=west": { 15 | "model": "special-model-loader-test:block/facing_model_block", 16 | "y": 270 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/blockstates/facing_obj_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "facing=east": { 4 | "model": "special-model-loader-test:block/obj_model_block", 5 | "y": 90 6 | }, 7 | "facing=north": { 8 | "model": "special-model-loader-test:block/obj_model_block" 9 | }, 10 | "facing=south": { 11 | "model": "special-model-loader-test:block/obj_model_block", 12 | "y": 180 13 | }, 14 | "facing=west": { 15 | "model": "special-model-loader-test:block/obj_model_block", 16 | "y": 270 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/blockstates/normal_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { 4 | "model": "special-model-loader-test:block/normal_model_block" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/block/facing_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "minecraft:block/orientable", 3 | "textures": { 4 | "front": "special-model-loader-test:block/facing_model_block_front", 5 | "side": "special-model-loader-test:block/facing_model_block_side", 6 | "top": "special-model-loader-test:block/facing_model_block_top" 7 | } 8 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/block/normal_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "minecraft:block/cube_all", 3 | "textures": { 4 | "all": "special-model-loader-test:block/normal_model_block" 5 | } 6 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/item/mtloverride_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "ambientocclusion": false, 4 | "flip_v": true, 5 | "model": "special-model-loader-test:models/item/ring/ring.obj", 6 | "mtl_override": "special-model-loader-test:models/item/ring/ring_2.mtl" 7 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/item/normal_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "minecraft:item/generated", 3 | "textures": { 4 | "layer0": "special-model-loader-test:item/normal_model_item" 5 | } 6 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/item/obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "ambientocclusion": false, 4 | "flip_v": true, 5 | "model": "special-model-loader-test:models/item/sea_cheken_pack/sea_chicken.obj" 6 | } -------------------------------------------------------------------------------- /src/test/generated/assets/special-model-loader-test/models/item/textures_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "ambientocclusion": false, 4 | "flip_v": true, 5 | "model": "special-model-loader-test:models/item/ring/ring.obj", 6 | "textures": { 7 | "texture0": "minecraft:block/cobblestone" 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/SMLTest.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest; 2 | 3 | import dev.felnull.smltest.block.SMLTestBlocks; 4 | import dev.felnull.smltest.item.SMLTestItems; 5 | import net.fabricmc.api.ModInitializer; 6 | 7 | public class SMLTest implements ModInitializer { 8 | public static final String MODID = "special-model-loader-test"; 9 | 10 | @Override 11 | public void onInitialize() { 12 | SMLTestItems.init(); 13 | SMLTestBlocks.init(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/block/FacingBlock.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.block; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.context.BlockPlaceContext; 5 | import net.minecraft.world.level.block.Block; 6 | import net.minecraft.world.level.block.HorizontalDirectionalBlock; 7 | import net.minecraft.world.level.block.Mirror; 8 | import net.minecraft.world.level.block.Rotation; 9 | import net.minecraft.world.level.block.state.BlockState; 10 | import net.minecraft.world.level.block.state.StateDefinition; 11 | import net.minecraft.world.level.block.state.properties.EnumProperty; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | public class FacingBlock extends Block { 15 | public static final EnumProperty FACING = HorizontalDirectionalBlock.FACING; 16 | 17 | public FacingBlock(Properties properties) { 18 | super(properties); 19 | this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH)); 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public BlockState getStateForPlacement(BlockPlaceContext blockPlaceContext) { 25 | return this.defaultBlockState().setValue(FACING, blockPlaceContext.getHorizontalDirection().getOpposite()); 26 | } 27 | 28 | @Override 29 | public BlockState rotate(BlockState blockState, Rotation rotation) { 30 | return blockState.setValue(FACING, rotation.rotate(blockState.getValue(FACING))); 31 | } 32 | 33 | @Override 34 | public BlockState mirror(BlockState blockState, Mirror mirror) { 35 | return blockState.rotate(mirror.getRotation(blockState.getValue(FACING))); 36 | } 37 | 38 | @Override 39 | protected void createBlockStateDefinition(StateDefinition.Builder builder) { 40 | builder.add(FACING); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/block/SMLTestBlocks.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.block; 2 | 3 | import dev.felnull.smltest.SMLTest; 4 | import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; 5 | import net.minecraft.core.registries.Registries; 6 | import net.minecraft.resources.ResourceKey; 7 | import net.minecraft.resources.ResourceLocation; 8 | import net.minecraft.world.item.CreativeModeTabs; 9 | import net.minecraft.world.item.Items; 10 | import net.minecraft.world.level.block.Block; 11 | import net.minecraft.world.level.block.Blocks; 12 | import net.minecraft.world.level.block.SoundType; 13 | import net.minecraft.world.level.block.state.BlockBehaviour; 14 | import net.minecraft.world.level.material.MapColor; 15 | 16 | import java.util.function.Function; 17 | 18 | public class SMLTestBlocks { 19 | public static final Block NORMAL_MODEL_BLOCK = register("normal_model_block", Block::new, BlockBehaviour.Properties.of().sound(SoundType.AMETHYST).mapColor(MapColor.DEEPSLATE)); 20 | public static final Block OBJ_MODEL_BLOCK = register("obj_model_block", Block::new, BlockBehaviour.Properties.of().sound(SoundType.AMETHYST).mapColor(MapColor.DEEPSLATE)); 21 | public static final Block FACING_MODEL_BLOCK = register("facing_model_block", FacingBlock::new, BlockBehaviour.Properties.of().sound(SoundType.AMETHYST).mapColor(MapColor.DEEPSLATE)); 22 | public static final Block FACING_OBJ_MODEL_BLOCK = register("facing_obj_model_block", FacingBlock::new, BlockBehaviour.Properties.of().sound(SoundType.AMETHYST).mapColor(MapColor.DEEPSLATE)); 23 | 24 | public static void init() { 25 | ItemGroupEvents.modifyEntriesEvent(CreativeModeTabs.BUILDING_BLOCKS).register(ct -> { 26 | ct.accept(NORMAL_MODEL_BLOCK); 27 | ct.accept(OBJ_MODEL_BLOCK); 28 | ct.accept(FACING_MODEL_BLOCK); 29 | ct.accept(FACING_OBJ_MODEL_BLOCK); 30 | }); 31 | } 32 | 33 | public static Block register(String name, Function factory, BlockBehaviour.Properties properties) { 34 | ResourceKey resKey = ResourceKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, name)); 35 | Block block = Blocks.register(resKey, factory, properties); 36 | Items.registerBlock(block); 37 | return block; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/client/DynamicObjModelItemSpecialRenderer.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.client; 2 | 3 | import com.mojang.blaze3d.vertex.PoseStack; 4 | import com.mojang.blaze3d.vertex.VertexConsumer; 5 | import com.mojang.math.Axis; 6 | import com.mojang.serialization.MapCodec; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.model.geom.EntityModelSet; 9 | import net.minecraft.client.renderer.MultiBufferSource; 10 | import net.minecraft.client.renderer.Sheets; 11 | import net.minecraft.client.renderer.special.NoDataSpecialModelRenderer; 12 | import net.minecraft.client.renderer.special.SpecialModelRenderer; 13 | import net.minecraft.client.resources.model.BakedModel; 14 | import net.minecraft.world.item.ItemDisplayContext; 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | import java.util.Objects; 18 | import java.util.function.Consumer; 19 | 20 | public class DynamicObjModelItemSpecialRenderer implements NoDataSpecialModelRenderer { 21 | 22 | @Override 23 | public void render(ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, boolean hasFoilType) { 24 | poseStack.pushPose(); 25 | 26 | poseCenterConsumer(poseStack, 0.5f, 0.5f, 0.5f, pose -> { 27 | poseRotateX(poseStack, 360f * (float) (System.currentTimeMillis() % 10000) / 10000f); 28 | poseRotateY(poseStack, 360f * (float) (System.currentTimeMillis() % 20000) / 20000f); 29 | poseRotateZ(poseStack, 360f * (float) (System.currentTimeMillis() % 30000) / 30000f); 30 | }); 31 | 32 | var model = Minecraft.getInstance().getModelManager().getModel(SMLTestClient.TEST_OBJ_MODEL); 33 | var vc = bufferSource.getBuffer(Sheets.solidBlockSheet()); 34 | renderModel(poseStack, vc, model, packedLight, packedOverlay); 35 | 36 | poseStack.popPose(); 37 | } 38 | 39 | public static void poseCenterConsumer(@NotNull PoseStack poseStack, float centerX, float centerY, float centerZ, @NotNull Consumer poseStackConsumer) { 40 | poseStack.translate(centerX, centerY, centerZ); 41 | poseStackConsumer.accept(poseStack); 42 | poseStack.translate(-centerX, -centerY, -centerZ); 43 | } 44 | 45 | public static void renderModel(PoseStack poseStack, VertexConsumer vertexConsumer, @NotNull BakedModel bakedModel, int combinedLight, int combinedOverlay) { 46 | Objects.requireNonNull(bakedModel); 47 | var bmr = Minecraft.getInstance().getBlockRenderer().getModelRenderer(); 48 | bmr.renderModel(poseStack.last(), vertexConsumer, null, bakedModel, 1.0F, 1.0F, 1.0F, combinedLight, combinedOverlay); 49 | } 50 | 51 | public static void poseRotateX(@NotNull PoseStack poseStack, float angle) { 52 | poseStack.mulPose(Axis.XP.rotationDegrees(angle)); 53 | } 54 | 55 | public static void poseRotateY(@NotNull PoseStack poseStack, float angle) { 56 | poseStack.mulPose(Axis.YP.rotationDegrees(angle)); 57 | } 58 | 59 | public static void poseRotateZ(@NotNull PoseStack poseStack, float angle) { 60 | poseStack.mulPose(Axis.ZP.rotationDegrees(angle)); 61 | } 62 | 63 | public record Unbaked() implements SpecialModelRenderer.Unbaked { 64 | public static final MapCodec MAP_CODEC = MapCodec.unit(new Unbaked()); 65 | 66 | @Override 67 | public @NotNull SpecialModelRenderer bake(EntityModelSet modelSet) { 68 | return new DynamicObjModelItemSpecialRenderer(); 69 | } 70 | 71 | @Override 72 | public @NotNull MapCodec type() { 73 | return MAP_CODEC; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/client/SMLTestClient.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.client; 2 | 3 | import dev.felnull.smltest.SMLTest; 4 | import dev.felnull.specialmodelloader.api.event.SpecialModelLoaderEvents; 5 | import net.fabricmc.api.ClientModInitializer; 6 | import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; 7 | import net.minecraft.client.renderer.special.SpecialModelRenderers; 8 | import net.minecraft.resources.ResourceLocation; 9 | 10 | public class SMLTestClient implements ClientModInitializer { 11 | public static final ResourceLocation TEST_OBJ_MODEL = ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, "item/obj_model_item_dynamic"); 12 | 13 | @Override 14 | public void onInitializeClient() { 15 | SpecialModelLoaderEvents.LOAD_SCOPE.register(() -> (resManager, location) -> SMLTest.MODID.equals(location.getNamespace())); 16 | ModelLoadingPlugin.register(pluginContext -> pluginContext.addModels(TEST_OBJ_MODEL)); 17 | 18 | SpecialModelRenderers.ID_MAPPER.put( 19 | ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, "dynamic_obj_model_item"), 20 | DynamicObjModelItemSpecialRenderer.Unbaked.MAP_CODEC 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/data/SMLTestDataGenerator.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.data; 2 | 3 | import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; 4 | import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; 5 | 6 | public class SMLTestDataGenerator implements DataGeneratorEntrypoint { 7 | @Override 8 | public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { 9 | var pack = fabricDataGenerator.createPack(); 10 | pack.addProvider(SMLTestModelProvider::new); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/data/SMLTestModelProvider.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.data; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import dev.felnull.smltest.SMLTest; 5 | import dev.felnull.smltest.block.SMLTestBlocks; 6 | import dev.felnull.smltest.item.SMLTestItems; 7 | import dev.felnull.specialmodelloader.api.data.SpecialModelDataGenHelper; 8 | import net.fabricmc.fabric.api.client.datagen.v1.provider.FabricModelProvider; 9 | import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; 10 | import net.minecraft.client.data.models.BlockModelGenerators; 11 | import net.minecraft.client.data.models.ItemModelGenerators; 12 | import net.minecraft.client.data.models.blockstates.MultiVariantGenerator; 13 | import net.minecraft.client.data.models.blockstates.Variant; 14 | import net.minecraft.client.data.models.blockstates.VariantProperties; 15 | import net.minecraft.client.data.models.model.ItemModelUtils; 16 | import net.minecraft.client.data.models.model.ModelLocationUtils; 17 | import net.minecraft.client.data.models.model.ModelTemplates; 18 | import net.minecraft.client.data.models.model.TexturedModel; 19 | import net.minecraft.resources.ResourceLocation; 20 | import net.minecraft.world.level.block.Block; 21 | 22 | public class SMLTestModelProvider extends FabricModelProvider { 23 | 24 | public SMLTestModelProvider(FabricDataOutput output) { 25 | super(output); 26 | } 27 | 28 | @Override 29 | public void generateBlockStateModels(BlockModelGenerators blockStateModelGenerator) { 30 | blockStateModelGenerator.createTrivialCube(SMLTestBlocks.NORMAL_MODEL_BLOCK); 31 | 32 | createFacing(blockStateModelGenerator, SMLTestBlocks.FACING_MODEL_BLOCK); 33 | 34 | blockStateModelGenerator.blockStateOutput.accept(MultiVariantGenerator.multiVariant(SMLTestBlocks.FACING_OBJ_MODEL_BLOCK, Variant.variant().with(VariantProperties.MODEL, ModelLocationUtils.getModelLocation(SMLTestBlocks.OBJ_MODEL_BLOCK, ""))) 35 | .with(BlockModelGenerators.createHorizontalFacingDispatch())); 36 | } 37 | 38 | private void createFacing(BlockModelGenerators blockStateModelGenerator, Block block) { 39 | var r = TexturedModel.ORIENTABLE_ONLY_TOP.create(SMLTestBlocks.FACING_MODEL_BLOCK, blockStateModelGenerator.modelOutput); 40 | 41 | blockStateModelGenerator.blockStateOutput.accept(MultiVariantGenerator.multiVariant(block, Variant.variant().with(VariantProperties.MODEL, r)) 42 | .with(BlockModelGenerators.createHorizontalFacingDispatch())); 43 | } 44 | 45 | @Override 46 | public void generateItemModels(ItemModelGenerators itemModelGenerator) { 47 | itemModelGenerator.generateFlatItem(SMLTestItems.NORMAL_MODEL_ITEM, ModelTemplates.FLAT_ITEM); 48 | 49 | SpecialModelDataGenHelper.generateObjModel(SMLTestItems.OBJ_MODEL_ITEM, ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, "models/item/sea_cheken_pack/sea_chicken.obj"), 50 | true, false, null, ImmutableMap.of(), 51 | null, itemModelGenerator.modelOutput); 52 | itemModelGenerator.itemModelOutput.accept(SMLTestItems.OBJ_MODEL_ITEM, 53 | ItemModelUtils.plainModel(ModelLocationUtils.getModelLocation(SMLTestItems.OBJ_MODEL_ITEM))); 54 | 55 | SpecialModelDataGenHelper.generateObjModel(SMLTestItems.MTLOVERRIDE_OBJ_MODEL_ITEM, 56 | ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, "models/item/ring/ring.obj"), 57 | true, false, SMLTest.MODID + ":models/item/ring/ring_2.mtl", ImmutableMap.of(), 58 | null, itemModelGenerator.modelOutput); 59 | itemModelGenerator.itemModelOutput.accept(SMLTestItems.MTLOVERRIDE_OBJ_MODEL_ITEM, 60 | ItemModelUtils.plainModel(ModelLocationUtils.getModelLocation(SMLTestItems.MTLOVERRIDE_OBJ_MODEL_ITEM))); 61 | 62 | SpecialModelDataGenHelper.generateObjModel(SMLTestItems.TEXTURES_OBJ_MODEL_ITEM, 63 | ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, "models/item/ring/ring.obj"), 64 | true, false, null, ImmutableMap.of("texture0", ResourceLocation.withDefaultNamespace("block/cobblestone")), 65 | null, itemModelGenerator.modelOutput); 66 | itemModelGenerator.itemModelOutput.accept(SMLTestItems.TEXTURES_OBJ_MODEL_ITEM, 67 | ItemModelUtils.plainModel(ModelLocationUtils.getModelLocation(SMLTestItems.TEXTURES_OBJ_MODEL_ITEM))); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/dev/felnull/smltest/item/SMLTestItems.java: -------------------------------------------------------------------------------- 1 | package dev.felnull.smltest.item; 2 | 3 | import dev.felnull.smltest.SMLTest; 4 | import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; 5 | import net.minecraft.core.registries.Registries; 6 | import net.minecraft.resources.ResourceKey; 7 | import net.minecraft.resources.ResourceLocation; 8 | import net.minecraft.world.item.CreativeModeTabs; 9 | import net.minecraft.world.item.Item; 10 | import net.minecraft.world.item.Items; 11 | 12 | import java.util.function.Function; 13 | 14 | public class SMLTestItems { 15 | public static final Item NORMAL_MODEL_ITEM = register("normal_model_item", Item::new, new Item.Properties()); 16 | public static final Item OBJ_MODEL_ITEM = register("obj_model_item", Item::new, new Item.Properties()); 17 | public static final Item OBJ2_MODEL_ITEM = register("obj2_model_item", Item::new, new Item.Properties()); 18 | public static final Item FORGE_OBJ_MODEL_ITEM = register("forge_obj_model_item", Item::new, new Item.Properties()); 19 | public static final Item DYNAMIC_OBJ_MODEL_ITEM = register("dynamic_obj_model_item", Item::new, new Item.Properties()); 20 | public static final Item MTLOVERRIDE_OBJ_MODEL_ITEM = register("mtloverride_obj_model_item", Item::new, new Item.Properties()); 21 | public static final Item TEXTURES_OBJ_MODEL_ITEM = register("textures_obj_model_item", Item::new, new Item.Properties()); 22 | 23 | public static void init() { 24 | ItemGroupEvents.modifyEntriesEvent(CreativeModeTabs.BUILDING_BLOCKS).register(ct -> { 25 | ct.accept(NORMAL_MODEL_ITEM); 26 | ct.accept(OBJ_MODEL_ITEM); 27 | ct.accept(OBJ2_MODEL_ITEM); 28 | ct.accept(FORGE_OBJ_MODEL_ITEM); 29 | ct.accept(DYNAMIC_OBJ_MODEL_ITEM); 30 | ct.accept(MTLOVERRIDE_OBJ_MODEL_ITEM); 31 | ct.accept(TEXTURES_OBJ_MODEL_ITEM); 32 | }); 33 | } 34 | 35 | public static Item register(String name, Function factory, Item.Properties properties) { 36 | ResourceKey resKey = ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(SMLTest.MODID, name)); 37 | return Items.registerItem(resKey, factory, properties); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/blockstates/obj_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { 4 | "model": "special-model-loader-test:block/obj_model_block" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/items/dynamic_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "type": "minecraft:special", 4 | "base": "special-model-loader-test:item/dynamic_obj_model_item", 5 | "model": { 6 | "type": "special-model-loader-test:dynamic_obj_model_item" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/items/forge_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "type": "minecraft:model", 4 | "model": "special-model-loader-test:item/forge_obj_model_item" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/items/obj2_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "type": "minecraft:model", 4 | "model": "special-model-loader-test:item/obj2_model_item" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/block/apple/apple.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 6 3 | 4 | newmtl body 5 | Ns 225.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd special-model-loader-test:block/body 14 | 15 | newmtl eda 16 | Ns 225.000000 17 | Ka 1.000000 1.000000 1.000000 18 | Kd 0.310813 0.122194 0.018597 19 | Ks 0.500000 0.500000 0.500000 20 | Ke 0.000000 0.000000 0.000000 21 | Ni 1.450000 22 | d 1.000000 23 | illum 2 24 | 25 | newmtl ha 26 | Ns 225.000000 27 | Ka 1.000000 1.000000 1.000000 28 | Kd 0.005605 0.318547 0.005605 29 | Ks 0.500000 0.500000 0.500000 30 | Ke 0.000000 0.000000 0.000000 31 | Ni 1.450000 32 | d 1.000000 33 | illum 2 34 | 35 | newmtl ikisugi 36 | Ns 225.000000 37 | Ka 1.000000 1.000000 1.000000 38 | Kd 0.800000 0.800000 0.800000 39 | Ks 0.500000 0.500000 0.500000 40 | Ke 0.000000 0.000000 0.000000 41 | Ni 1.450000 42 | d 1.000000 43 | illum 2 44 | map_Kd special-model-loader-test:block/eay 45 | 46 | newmtl ikisugi.002 47 | Ns 225.000000 48 | Ka 1.000000 1.000000 1.000000 49 | Kd 0.800000 0.800000 0.800000 50 | Ks 0.500000 0.500000 0.500000 51 | Ke 0.000000 0.000000 0.000000 52 | Ni 1.450000 53 | d 1.000000 54 | illum 2 55 | map_Kd special-model-loader-test:block/eay 56 | 57 | newmtl te 58 | Ns 225.000000 59 | Ka 1.000000 1.000000 1.000000 60 | Kd 0.000000 0.000000 0.000000 61 | Ks 0.500000 0.500000 0.500000 62 | Ke 0.000000 0.000000 0.000000 63 | Ni 1.450000 64 | d 1.000000 65 | illum 2 66 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/block/obj_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "model": "special-model-loader-test:models/block/apple/apple.obj", 4 | "gui_light": "side", 5 | "particle": "block/sand", 6 | "display": { 7 | "gui": { 8 | "rotation": [ 9 | 30, 10 | 225, 11 | 0 12 | ], 13 | "translation": [ 14 | 0, 15 | 0, 16 | 0 17 | ], 18 | "scale": [ 19 | 0.625, 20 | 0.625, 21 | 0.625 22 | ] 23 | }, 24 | "ground": { 25 | "rotation": [ 26 | 0, 27 | 0, 28 | 0 29 | ], 30 | "translation": [ 31 | 0, 32 | 3, 33 | 0 34 | ], 35 | "scale": [ 36 | 0.25, 37 | 0.25, 38 | 0.25 39 | ] 40 | }, 41 | "fixed": { 42 | "rotation": [ 43 | 0, 44 | 0, 45 | 0 46 | ], 47 | "translation": [ 48 | 0, 49 | 0, 50 | 0 51 | ], 52 | "scale": [ 53 | 0.5, 54 | 0.5, 55 | 0.5 56 | ] 57 | }, 58 | "thirdperson_righthand": { 59 | "rotation": [ 60 | 75, 61 | 45, 62 | 0 63 | ], 64 | "translation": [ 65 | 0, 66 | 2.5, 67 | 0 68 | ], 69 | "scale": [ 70 | 0.375, 71 | 0.375, 72 | 0.375 73 | ] 74 | }, 75 | "firstperson_righthand": { 76 | "rotation": [ 77 | 0, 78 | 45, 79 | 0 80 | ], 81 | "translation": [ 82 | 0, 83 | 0, 84 | 0 85 | ], 86 | "scale": [ 87 | 0.40, 88 | 0.40, 89 | 0.40 90 | ] 91 | }, 92 | "firstperson_lefthand": { 93 | "rotation": [ 94 | 0, 95 | 225, 96 | 0 97 | ], 98 | "translation": [ 99 | 0, 100 | 0, 101 | 0 102 | ], 103 | "scale": [ 104 | 0.40, 105 | 0.40, 106 | 0.40 107 | ] 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/cylinder/cylinder.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/models/item/cylinder/cylinder.blend -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/cylinder/cylinder.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'cylinder.blend' 2 | # Material Count: 1 3 | 4 | newmtl マテリアル 5 | Ns 250.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd block/ancient_debris_side 14 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/cylinder/cylinder.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.2.2 OBJ File: 'cylinder.blend' 2 | # www.blender.org 3 | mtllib cylinder.mtl 4 | o 円柱 5 | v 0.000000 -1.845595 -0.365594 6 | v 0.000000 1.845595 -0.365594 7 | v 0.071324 -1.845595 -0.358569 8 | v 0.071324 1.845595 -0.358569 9 | v 0.139907 -1.845595 -0.337765 10 | v 0.139907 1.845595 -0.337765 11 | v 0.203113 -1.845595 -0.303980 12 | v 0.203113 1.845595 -0.303980 13 | v 0.258514 -1.845595 -0.258514 14 | v 0.258514 1.845595 -0.258514 15 | v 0.303980 -1.845595 -0.203113 16 | v 0.303980 1.845595 -0.203113 17 | v 0.337765 -1.845595 -0.139907 18 | v 0.337765 1.845595 -0.139907 19 | v 0.358569 -1.845595 -0.071324 20 | v 0.358569 1.845595 -0.071324 21 | v 0.365594 -1.845595 0.000000 22 | v 0.365594 1.845595 0.000000 23 | v 0.358569 -1.845595 0.071324 24 | v 0.358569 1.845595 0.071324 25 | v 0.337765 -1.845595 0.139907 26 | v 0.337765 1.845595 0.139907 27 | v 0.303980 -1.845595 0.203113 28 | v 0.303980 1.845595 0.203113 29 | v 0.258514 -1.845595 0.258514 30 | v 0.258514 1.845595 0.258514 31 | v 0.203113 -1.845595 0.303980 32 | v 0.203113 1.845595 0.303980 33 | v 0.139907 -1.845595 0.337765 34 | v 0.139907 1.845595 0.337765 35 | v 0.071324 -1.845595 0.358569 36 | v 0.071324 1.845595 0.358569 37 | v -0.000000 -1.845595 0.365594 38 | v -0.000000 1.845595 0.365594 39 | v -0.071324 -1.845595 0.358569 40 | v -0.071324 1.845595 0.358569 41 | v -0.139907 -1.845595 0.337765 42 | v -0.139907 1.845595 0.337765 43 | v -0.203113 -1.845595 0.303980 44 | v -0.203113 1.845595 0.303980 45 | v -0.258514 -1.845595 0.258514 46 | v -0.258514 1.845595 0.258514 47 | v -0.303980 -1.845595 0.203113 48 | v -0.303980 1.845595 0.203113 49 | v -0.337765 -1.845595 0.139907 50 | v -0.337765 1.845595 0.139907 51 | v -0.358569 -1.845595 0.071324 52 | v -0.358569 1.845595 0.071324 53 | v -0.365594 -1.845595 -0.000000 54 | v -0.365594 1.845595 -0.000000 55 | v -0.358569 -1.845595 -0.071324 56 | v -0.358569 1.845595 -0.071324 57 | v -0.337765 -1.845595 -0.139907 58 | v -0.337765 1.845595 -0.139907 59 | v -0.303980 -1.845595 -0.203113 60 | v -0.303980 1.845595 -0.203113 61 | v -0.258514 -1.845595 -0.258514 62 | v -0.258514 1.845595 -0.258514 63 | v -0.203113 -1.845595 -0.303980 64 | v -0.203113 1.845595 -0.303980 65 | v -0.139907 -1.845595 -0.337765 66 | v -0.139907 1.845595 -0.337765 67 | v -0.071324 -1.845595 -0.358569 68 | v -0.071324 1.845595 -0.358569 69 | vt 1.000000 0.500000 70 | vt 1.000000 1.000000 71 | vt 0.968750 1.000000 72 | vt 0.968750 0.500000 73 | vt 0.937500 1.000000 74 | vt 0.937500 0.500000 75 | vt 0.906250 1.000000 76 | vt 0.906250 0.500000 77 | vt 0.875000 1.000000 78 | vt 0.875000 0.500000 79 | vt 0.843750 1.000000 80 | vt 0.843750 0.500000 81 | vt 0.812500 1.000000 82 | vt 0.812500 0.500000 83 | vt 0.781250 1.000000 84 | vt 0.781250 0.500000 85 | vt 0.750000 1.000000 86 | vt 0.750000 0.500000 87 | vt 0.718750 1.000000 88 | vt 0.718750 0.500000 89 | vt 0.687500 1.000000 90 | vt 0.687500 0.500000 91 | vt 0.656250 1.000000 92 | vt 0.656250 0.500000 93 | vt 0.625000 1.000000 94 | vt 0.625000 0.500000 95 | vt 0.593750 1.000000 96 | vt 0.593750 0.500000 97 | vt 0.562500 1.000000 98 | vt 0.562500 0.500000 99 | vt 0.531250 1.000000 100 | vt 0.531250 0.500000 101 | vt 0.500000 1.000000 102 | vt 0.500000 0.500000 103 | vt 0.468750 1.000000 104 | vt 0.468750 0.500000 105 | vt 0.437500 1.000000 106 | vt 0.437500 0.500000 107 | vt 0.406250 1.000000 108 | vt 0.406250 0.500000 109 | vt 0.375000 1.000000 110 | vt 0.375000 0.500000 111 | vt 0.343750 1.000000 112 | vt 0.343750 0.500000 113 | vt 0.312500 1.000000 114 | vt 0.312500 0.500000 115 | vt 0.281250 1.000000 116 | vt 0.281250 0.500000 117 | vt 0.250000 1.000000 118 | vt 0.250000 0.500000 119 | vt 0.218750 1.000000 120 | vt 0.218750 0.500000 121 | vt 0.187500 1.000000 122 | vt 0.187500 0.500000 123 | vt 0.156250 1.000000 124 | vt 0.156250 0.500000 125 | vt 0.125000 1.000000 126 | vt 0.125000 0.500000 127 | vt 0.093750 1.000000 128 | vt 0.093750 0.500000 129 | vt 0.062500 1.000000 130 | vt 0.062500 0.500000 131 | vt 0.296822 0.485388 132 | vt 0.250000 0.490000 133 | vt 0.203178 0.485388 134 | vt 0.158156 0.471731 135 | vt 0.116663 0.449553 136 | vt 0.080294 0.419706 137 | vt 0.050447 0.383337 138 | vt 0.028269 0.341844 139 | vt 0.014612 0.296822 140 | vt 0.010000 0.250000 141 | vt 0.014612 0.203178 142 | vt 0.028269 0.158156 143 | vt 0.050447 0.116663 144 | vt 0.080294 0.080294 145 | vt 0.116663 0.050447 146 | vt 0.158156 0.028269 147 | vt 0.203178 0.014612 148 | vt 0.250000 0.010000 149 | vt 0.296822 0.014612 150 | vt 0.341844 0.028269 151 | vt 0.383337 0.050447 152 | vt 0.419706 0.080294 153 | vt 0.449553 0.116663 154 | vt 0.471731 0.158156 155 | vt 0.485388 0.203178 156 | vt 0.490000 0.250000 157 | vt 0.485388 0.296822 158 | vt 0.471731 0.341844 159 | vt 0.449553 0.383337 160 | vt 0.419706 0.419706 161 | vt 0.383337 0.449553 162 | vt 0.341844 0.471731 163 | vt 0.031250 1.000000 164 | vt 0.031250 0.500000 165 | vt 0.000000 1.000000 166 | vt 0.000000 0.500000 167 | vt 0.750000 0.490000 168 | vt 0.796822 0.485388 169 | vt 0.841844 0.471731 170 | vt 0.883337 0.449553 171 | vt 0.919706 0.419706 172 | vt 0.949553 0.383337 173 | vt 0.971731 0.341844 174 | vt 0.985388 0.296822 175 | vt 0.990000 0.250000 176 | vt 0.985388 0.203178 177 | vt 0.971731 0.158156 178 | vt 0.949553 0.116663 179 | vt 0.919706 0.080294 180 | vt 0.883337 0.050447 181 | vt 0.841844 0.028269 182 | vt 0.796822 0.014612 183 | vt 0.750000 0.010000 184 | vt 0.703178 0.014612 185 | vt 0.658156 0.028269 186 | vt 0.616663 0.050447 187 | vt 0.580294 0.080294 188 | vt 0.550447 0.116663 189 | vt 0.528269 0.158156 190 | vt 0.514612 0.203178 191 | vt 0.510000 0.250000 192 | vt 0.514612 0.296822 193 | vt 0.528269 0.341844 194 | vt 0.550447 0.383337 195 | vt 0.580294 0.419706 196 | vt 0.616663 0.449553 197 | vt 0.658156 0.471731 198 | vt 0.703178 0.485388 199 | vn 0.0980 0.0000 -0.9952 200 | vn 0.2903 0.0000 -0.9569 201 | vn 0.4714 0.0000 -0.8819 202 | vn 0.6344 0.0000 -0.7730 203 | vn 0.7730 0.0000 -0.6344 204 | vn 0.8819 0.0000 -0.4714 205 | vn 0.9569 0.0000 -0.2903 206 | vn 0.9952 0.0000 -0.0980 207 | vn 0.9952 0.0000 0.0980 208 | vn 0.9569 0.0000 0.2903 209 | vn 0.8819 0.0000 0.4714 210 | vn 0.7730 0.0000 0.6344 211 | vn 0.6344 0.0000 0.7730 212 | vn 0.4714 0.0000 0.8819 213 | vn 0.2903 0.0000 0.9569 214 | vn 0.0980 0.0000 0.9952 215 | vn -0.0980 0.0000 0.9952 216 | vn -0.2903 0.0000 0.9569 217 | vn -0.4714 0.0000 0.8819 218 | vn -0.6344 0.0000 0.7730 219 | vn -0.7730 0.0000 0.6344 220 | vn -0.8819 0.0000 0.4714 221 | vn -0.9569 0.0000 0.2903 222 | vn -0.9952 0.0000 0.0980 223 | vn -0.9952 0.0000 -0.0980 224 | vn -0.9569 0.0000 -0.2903 225 | vn -0.8819 0.0000 -0.4714 226 | vn -0.7730 0.0000 -0.6344 227 | vn -0.6344 0.0000 -0.7730 228 | vn -0.4714 0.0000 -0.8819 229 | vn 0.0000 1.0000 0.0000 230 | vn -0.2903 0.0000 -0.9569 231 | vn -0.0980 0.0000 -0.9952 232 | vn 0.0000 -1.0000 0.0000 233 | usemtl マテリアル 234 | s off 235 | f 1/1/1 2/2/1 4/3/1 3/4/1 236 | f 3/4/2 4/3/2 6/5/2 5/6/2 237 | f 5/6/3 6/5/3 8/7/3 7/8/3 238 | f 7/8/4 8/7/4 10/9/4 9/10/4 239 | f 9/10/5 10/9/5 12/11/5 11/12/5 240 | f 11/12/6 12/11/6 14/13/6 13/14/6 241 | f 13/14/7 14/13/7 16/15/7 15/16/7 242 | f 15/16/8 16/15/8 18/17/8 17/18/8 243 | f 17/18/9 18/17/9 20/19/9 19/20/9 244 | f 19/20/10 20/19/10 22/21/10 21/22/10 245 | f 21/22/11 22/21/11 24/23/11 23/24/11 246 | f 23/24/12 24/23/12 26/25/12 25/26/12 247 | f 25/26/13 26/25/13 28/27/13 27/28/13 248 | f 27/28/14 28/27/14 30/29/14 29/30/14 249 | f 29/30/15 30/29/15 32/31/15 31/32/15 250 | f 31/32/16 32/31/16 34/33/16 33/34/16 251 | f 33/34/17 34/33/17 36/35/17 35/36/17 252 | f 35/36/18 36/35/18 38/37/18 37/38/18 253 | f 37/38/19 38/37/19 40/39/19 39/40/19 254 | f 39/40/20 40/39/20 42/41/20 41/42/20 255 | f 41/42/21 42/41/21 44/43/21 43/44/21 256 | f 43/44/22 44/43/22 46/45/22 45/46/22 257 | f 45/46/23 46/45/23 48/47/23 47/48/23 258 | f 47/48/24 48/47/24 50/49/24 49/50/24 259 | f 49/50/25 50/49/25 52/51/25 51/52/25 260 | f 51/52/26 52/51/26 54/53/26 53/54/26 261 | f 53/54/27 54/53/27 56/55/27 55/56/27 262 | f 55/56/28 56/55/28 58/57/28 57/58/28 263 | f 57/58/29 58/57/29 60/59/29 59/60/29 264 | f 59/60/30 60/59/30 62/61/30 61/62/30 265 | f 4/63/31 2/64/31 64/65/31 62/66/31 60/67/31 58/68/31 56/69/31 54/70/31 52/71/31 50/72/31 48/73/31 46/74/31 44/75/31 42/76/31 40/77/31 38/78/31 36/79/31 34/80/31 32/81/31 30/82/31 28/83/31 26/84/31 24/85/31 22/86/31 20/87/31 18/88/31 16/89/31 14/90/31 12/91/31 10/92/31 8/93/31 6/94/31 266 | f 61/62/32 62/61/32 64/95/32 63/96/32 267 | f 63/96/33 64/95/33 2/97/33 1/98/33 268 | f 1/99/34 3/100/34 5/101/34 7/102/34 9/103/34 11/104/34 13/105/34 15/106/34 17/107/34 19/108/34 21/109/34 23/110/34 25/111/34 27/112/34 29/113/34 31/114/34 33/115/34 35/116/34 37/117/34 39/118/34 41/119/34 43/120/34 45/121/34 47/122/34 49/123/34 51/124/34 53/125/34 55/126/34 57/127/34 59/128/34 61/129/34 63/130/34 269 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/dynamic_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "gui_light": "side", 3 | "display": { 4 | "gui": { 5 | "rotation": [ 6 | 30, 7 | 225, 8 | 0 9 | ], 10 | "translation": [ 11 | 0, 12 | 0, 13 | 0 14 | ], 15 | "scale": [ 16 | 0.625, 17 | 0.625, 18 | 0.625 19 | ] 20 | }, 21 | "ground": { 22 | "rotation": [ 23 | 0, 24 | 0, 25 | 0 26 | ], 27 | "translation": [ 28 | 0, 29 | 3, 30 | 0 31 | ], 32 | "scale": [ 33 | 0.25, 34 | 0.25, 35 | 0.25 36 | ] 37 | }, 38 | "fixed": { 39 | "rotation": [ 40 | 0, 41 | 0, 42 | 0 43 | ], 44 | "translation": [ 45 | 0, 46 | 0, 47 | 0 48 | ], 49 | "scale": [ 50 | 0.5, 51 | 0.5, 52 | 0.5 53 | ] 54 | }, 55 | "thirdperson_righthand": { 56 | "rotation": [ 57 | 75, 58 | 45, 59 | 0 60 | ], 61 | "translation": [ 62 | 0, 63 | 2.5, 64 | 0 65 | ], 66 | "scale": [ 67 | 0.375, 68 | 0.375, 69 | 0.375 70 | ] 71 | }, 72 | "firstperson_righthand": { 73 | "rotation": [ 74 | 0, 75 | 45, 76 | 0 77 | ], 78 | "translation": [ 79 | 0, 80 | 0, 81 | 0 82 | ], 83 | "scale": [ 84 | 0.40, 85 | 0.40, 86 | 0.40 87 | ] 88 | }, 89 | "firstperson_lefthand": { 90 | "rotation": [ 91 | 0, 92 | 225, 93 | 0 94 | ], 95 | "translation": [ 96 | 0, 97 | 0, 98 | 0 99 | ], 100 | "scale": [ 101 | 0.40, 102 | 0.40, 103 | 0.40 104 | ] 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/forge_obj_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "loader": "neoforge:obj", 3 | "model": "special-model-loader-test:models/item/parabolic_antenna/parabolic_antenna.obj", 4 | "flip_v": true, 5 | "display": { 6 | "ground": { 7 | "rotation": [ 8 | 0, 9 | 0, 10 | 0 11 | ], 12 | "translation": [ 13 | 0.8, 14 | 7, 15 | 0.8 16 | ], 17 | "scale": [ 18 | 0.1, 19 | 0.1, 20 | 0.1 21 | ] 22 | }, 23 | "head": { 24 | "rotation": [ 25 | 0, 26 | 180, 27 | 0 28 | ], 29 | "translation": [ 30 | -0.9, 31 | 11.5, 32 | 0 33 | ], 34 | "scale": [ 35 | 0.1, 36 | 0.1, 37 | 0.1 38 | ] 39 | }, 40 | "thirdperson_righthand": { 41 | "rotation": [ 42 | 0, 43 | 0, 44 | 0 45 | ], 46 | "translation": [ 47 | 1, 48 | 5.25, 49 | 2 50 | ], 51 | "scale": [ 52 | 0.1, 53 | 0.1, 54 | 0.1 55 | ] 56 | }, 57 | "thirdperson_lefthand": { 58 | "rotation": [ 59 | 0, 60 | 0, 61 | 0 62 | ], 63 | "translation": [ 64 | -1, 65 | 5.25, 66 | 2 67 | ], 68 | "scale": [ 69 | 0.1, 70 | 0.1, 71 | 0.1 72 | ] 73 | }, 74 | "firstperson_righthand": { 75 | "rotation": [ 76 | 0, 77 | 0, 78 | 25 79 | ], 80 | "translation": [ 81 | 0, 82 | 5, 83 | 0 84 | ], 85 | "scale": [ 86 | 0.1, 87 | 0.1, 88 | 0.1 89 | ] 90 | }, 91 | "fixed": { 92 | "rotation": [ 93 | 45, 94 | 180, 95 | 0 96 | ], 97 | "translation": [ 98 | -1, 99 | 4, 100 | 0.65 101 | ], 102 | "scale": [ 103 | 0.1, 104 | 0.1, 105 | 0.1 106 | ] 107 | }, 108 | "gui": { 109 | "rotation": [ 110 | 15, 111 | 0, 112 | 45 113 | ], 114 | "translation": [ 115 | -5, 116 | 7, 117 | 0 118 | ], 119 | "scale": [ 120 | 0.25, 121 | 0.25, 122 | 0.25 123 | ] 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/obj2_model_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "model": "special-model-loader-test:models/item/cylinder/cylinder.obj", 4 | "display": { 5 | "gui": { 6 | "rotation": [ 7 | 30, 8 | 225, 9 | 0 10 | ], 11 | "translation": [ 12 | 0, 13 | 0, 14 | 0 15 | ], 16 | "scale": [ 17 | 0.625, 18 | 0.625, 19 | 0.625 20 | ] 21 | }, 22 | "ground": { 23 | "rotation": [ 24 | 0, 25 | 0, 26 | 0 27 | ], 28 | "translation": [ 29 | 0, 30 | 3, 31 | 0 32 | ], 33 | "scale": [ 34 | 0.25, 35 | 0.25, 36 | 0.25 37 | ] 38 | }, 39 | "fixed": { 40 | "rotation": [ 41 | 0, 42 | 0, 43 | 0 44 | ], 45 | "translation": [ 46 | 0, 47 | 0, 48 | 0 49 | ], 50 | "scale": [ 51 | 0.5, 52 | 0.5, 53 | 0.5 54 | ] 55 | }, 56 | "thirdperson_righthand": { 57 | "rotation": [ 58 | 75, 59 | 45, 60 | 0 61 | ], 62 | "translation": [ 63 | 0, 64 | 2.5, 65 | 0 66 | ], 67 | "scale": [ 68 | 0.375, 69 | 0.375, 70 | 0.375 71 | ] 72 | }, 73 | "firstperson_righthand": { 74 | "rotation": [ 75 | 0, 76 | 45, 77 | 0 78 | ], 79 | "translation": [ 80 | 0, 81 | 0, 82 | 0 83 | ], 84 | "scale": [ 85 | 0.40, 86 | 0.40, 87 | 0.40 88 | ] 89 | }, 90 | "firstperson_lefthand": { 91 | "rotation": [ 92 | 0, 93 | 225, 94 | 0 95 | ], 96 | "translation": [ 97 | 0, 98 | 0, 99 | 0 100 | ], 101 | "scale": [ 102 | 0.40, 103 | 0.40, 104 | 0.40 105 | ] 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/obj_model_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader-test:block/obj_model_block" 3 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/obj_model_item_dynamic.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "ambientocclusion": true, 4 | "flip_v": true, 5 | "model": "special-model-loader-test:models/item/test/test.obj" 6 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/parabolic_antenna/parabolic_antenna.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'parabolic_antenna.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material.001 5 | Ns 224.999983 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd special-model-loader-test:item/parabolic_antenna 14 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/parabolic_antenna/parabolic_antenna.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.2.2 OBJ File: 'parabolic_antenna.blend' 2 | # www.blender.org 3 | mtllib parabolic_antenna.mtl 4 | o Cylinder.001 5 | v 0.000000 -2.492532 -1.000000 6 | v 0.500000 -2.492532 -0.866025 7 | v 0.874318 -1.959199 -1.514364 8 | v 0.000000 -1.959199 -1.748637 9 | v 0.866025 -2.492532 -0.500000 10 | v 1.514364 -1.959199 -0.874318 11 | v 1.000000 -2.492532 -0.000000 12 | v 1.748637 -1.959199 -0.000000 13 | v 0.866025 -2.492532 0.500000 14 | v 1.514364 -1.959199 0.874318 15 | v 0.500000 -2.492532 0.866025 16 | v 0.874318 -1.959199 1.514364 17 | v 0.000000 -2.492532 1.000000 18 | v 0.000000 -1.959199 1.748637 19 | v -0.500000 -2.492532 0.866026 20 | v -0.874318 -1.959199 1.514364 21 | v -0.866025 -2.492532 0.500000 22 | v -1.514364 -1.959199 0.874319 23 | v -1.000000 -2.492532 -0.000000 24 | v -1.748637 -1.959199 0.000001 25 | v -0.866026 -2.492532 -0.499999 26 | v -1.514364 -1.959199 -0.874318 27 | v -1.655755 -1.638039 -0.955949 28 | v -1.911900 -1.638039 0.000001 29 | v -0.500001 -2.492532 -0.866025 30 | v -0.874319 -1.959199 -1.514363 31 | v -1.655754 -1.638039 0.955951 32 | v -0.955950 -1.638039 1.655754 33 | v 0.000000 -1.638039 1.911900 34 | v 0.955950 -1.638039 1.655754 35 | v 1.655754 -1.638039 0.955950 36 | v 1.911900 -1.638039 -0.000000 37 | v 0.000000 -1.638039 -1.911901 38 | v -0.955951 -1.638039 -1.655754 39 | v 0.955950 -1.638039 -1.655754 40 | v 1.655754 -1.638039 -0.955950 41 | v 1.655754 -1.638039 -0.955950 42 | v 1.911900 -1.638039 -0.000000 43 | v 1.801995 -1.604232 -0.000000 44 | v 1.560573 -1.604232 -0.900997 45 | v 0.955950 -1.638039 1.655754 46 | v 0.000000 -1.638039 1.911900 47 | v 0.000000 -1.604232 1.801995 48 | v 0.900997 -1.604232 1.560573 49 | v -1.655754 -1.638039 0.955951 50 | v -1.911900 -1.638039 0.000001 51 | v -1.801995 -1.604232 0.000001 52 | v -1.560573 -1.604232 0.900998 53 | v 0.955950 -1.638039 -1.655754 54 | v 0.900997 -1.604232 -1.560573 55 | v -0.955951 -1.638039 -1.655754 56 | v 0.000000 -1.638039 -1.911901 57 | v 0.000000 -1.604232 -1.801995 58 | v -0.900998 -1.604232 -1.560573 59 | v 1.655754 -1.638039 0.955950 60 | v 1.560573 -1.604232 0.900997 61 | v -0.955950 -1.638039 1.655754 62 | v -0.900997 -1.604232 1.560573 63 | v -1.655755 -1.638039 -0.955949 64 | v -1.560574 -1.604232 -0.900997 65 | v 0.000000 -2.409605 -0.942515 66 | v 0.000000 -1.906930 -1.648116 67 | v 0.824058 -1.906930 -1.427311 68 | v 0.471257 -2.409605 -0.816242 69 | v 1.427311 -1.906930 -0.824058 70 | v 0.816242 -2.409605 -0.471257 71 | v 1.648116 -1.906930 -0.000000 72 | v 0.942515 -2.409605 -0.000000 73 | v 1.427311 -1.906930 0.824058 74 | v 0.816242 -2.409605 0.471258 75 | v 0.824058 -1.906930 1.427311 76 | v 0.471258 -2.409605 0.816242 77 | v 0.000000 -1.906930 1.648116 78 | v 0.000000 -2.409605 0.942515 79 | v -0.824058 -1.906930 1.427311 80 | v -0.471257 -2.409605 0.816242 81 | v -1.427310 -1.906930 0.824059 82 | v -0.816242 -2.409605 0.471258 83 | v -1.648116 -1.906930 0.000001 84 | v -0.942515 -2.409605 -0.000000 85 | v -1.427311 -1.906930 -0.824057 86 | v -0.816242 -2.409605 -0.471257 87 | v -0.824059 -1.906930 -1.427310 88 | v -0.471258 -2.409605 -0.816242 89 | vt 0.491267 0.294338 90 | vt 0.692385 0.148190 91 | vt 0.594496 0.317777 92 | vt 0.672272 0.389832 93 | vt 0.842011 0.291974 94 | vt 0.703053 0.491760 95 | vt 0.850665 0.692965 96 | vt 0.680616 0.595629 97 | vt 0.707299 0.843021 98 | vt 0.608906 0.673696 99 | vt 0.507918 0.705377 100 | vt 0.508074 0.901085 101 | vt 0.404586 0.681571 102 | vt 0.156762 0.707835 103 | vt 0.326429 0.609722 104 | vt 0.098834 0.508512 105 | vt 0.295292 0.508046 106 | vt 0.318129 0.404313 107 | vt 0.067867 0.265076 108 | vt 0.148170 0.306705 109 | vt 0.390305 0.326364 110 | vt 0.291684 0.156761 111 | vt 0.008466 0.512544 112 | vt 0.264926 0.931798 113 | vt 0.080525 0.756487 114 | vt 0.306652 0.851573 115 | vt 0.512120 0.991402 116 | vt 0.756036 0.919189 117 | vt 0.990102 0.487123 118 | vt 0.930982 0.734514 119 | vt 0.490963 0.098652 120 | vt 0.242982 0.080556 121 | vt 0.486923 0.008328 122 | vt 0.734129 0.068011 123 | vt 0.899795 0.491155 124 | vt 0.918220 0.243416 125 | vt 0.918220 0.243416 126 | vt 0.990102 0.487123 127 | vt 0.918220 0.243416 128 | vt 0.756036 0.919189 129 | vt 0.512120 0.991402 130 | vt 0.756036 0.919189 131 | vt 0.080525 0.756487 132 | vt 0.008466 0.512544 133 | vt 0.080525 0.756487 134 | vt 0.734129 0.068011 135 | vt 0.734129 0.068011 136 | vt 0.242982 0.080556 137 | vt 0.486923 0.008328 138 | vt 0.242982 0.080556 139 | vt 0.930982 0.734514 140 | vt 0.930982 0.734514 141 | vt 0.264926 0.931798 142 | vt 0.264926 0.931798 143 | vt 0.486923 0.008328 144 | vt 0.067867 0.265076 145 | vt 0.067867 0.265076 146 | vt 0.008466 0.512544 147 | vt 0.594496 0.317777 148 | vt 0.490963 0.098652 149 | vt 0.491267 0.294338 150 | vt 0.842011 0.291974 151 | vt 0.692385 0.148190 152 | vt 0.672272 0.389832 153 | vt 0.899795 0.491155 154 | vt 0.680616 0.595629 155 | vt 0.703053 0.491760 156 | vt 0.608906 0.673696 157 | vt 0.850665 0.692965 158 | vt 0.507918 0.705377 159 | vt 0.707299 0.843021 160 | vt 0.404586 0.681571 161 | vt 0.508074 0.901085 162 | vt 0.326429 0.609722 163 | vt 0.306652 0.851573 164 | vt 0.098834 0.508512 165 | vt 0.156762 0.707835 166 | vt 0.295292 0.508046 167 | vt 0.148170 0.306705 168 | vt 0.390305 0.326364 169 | vt 0.318129 0.404313 170 | vt 0.291684 0.156761 171 | vt 0.512120 0.991402 172 | vt 0.990102 0.487123 173 | vn 0.1536 -0.8048 -0.5733 174 | vn 0.4197 -0.8048 -0.4197 175 | vn 0.5733 -0.8048 -0.1536 176 | vn 0.5733 -0.8048 0.1536 177 | vn 0.4197 -0.8048 0.4197 178 | vn 0.1536 -0.8048 0.5733 179 | vn -0.1536 -0.8048 0.5733 180 | vn -0.4197 -0.8048 0.4197 181 | vn -0.5733 -0.8048 0.1536 182 | vn -0.5733 -0.8048 -0.1536 183 | vn -0.8670 -0.4408 -0.2323 184 | vn -0.4197 -0.8048 -0.4197 185 | vn -0.1536 -0.8048 -0.5733 186 | vn -0.0000 -1.0000 -0.0000 187 | vn -0.8670 -0.4408 0.2323 188 | vn -0.6347 -0.4408 0.6347 189 | vn -0.2323 -0.4408 0.8670 190 | vn 0.2323 -0.4408 0.8670 191 | vn 0.6347 -0.4408 0.6347 192 | vn 0.8670 -0.4408 0.2323 193 | vn -0.2323 -0.4408 -0.8670 194 | vn 0.2323 -0.4408 -0.8670 195 | vn 0.8670 -0.4408 -0.2323 196 | vn -0.6347 -0.4408 -0.6347 197 | vn 0.6347 -0.4408 -0.6347 198 | vn 0.2931 0.9529 -0.0785 199 | vn 0.0785 0.9529 0.2931 200 | vn -0.2931 0.9529 0.0785 201 | vn 0.2146 0.9529 -0.2146 202 | vn -0.0785 0.9529 -0.2931 203 | vn 0.2146 0.9529 0.2146 204 | vn -0.2146 0.9529 0.2146 205 | vn 0.0785 0.9529 -0.2931 206 | vn -0.2146 0.9529 -0.2146 207 | vn 0.2931 0.9529 0.0785 208 | vn -0.0785 0.9529 0.2931 209 | vn -0.2931 0.9529 -0.0785 210 | vn 0.0000 0.0000 1.0000 211 | vn -0.1536 0.8048 0.5733 212 | vn -0.4197 0.8048 0.4197 213 | vn -0.5733 0.8048 0.1536 214 | vn -0.5733 0.8048 -0.1536 215 | vn -0.4197 0.8048 -0.4197 216 | vn -0.1536 0.8048 -0.5733 217 | vn 0.1536 0.8048 -0.5733 218 | vn 0.4197 0.8048 -0.4197 219 | vn 0.5733 0.8048 -0.1536 220 | vn 0.5733 0.8048 0.1536 221 | vn 0.8670 0.4408 0.2323 222 | vn 0.4197 0.8048 0.4197 223 | vn 0.1536 0.8048 0.5733 224 | vn -0.0000 1.0000 0.0000 225 | vn 0.8670 0.4408 -0.2323 226 | vn 0.6347 0.4408 -0.6347 227 | vn 0.2323 0.4408 -0.8670 228 | vn -0.2323 0.4408 -0.8670 229 | vn -0.6347 0.4408 -0.6347 230 | vn -0.8670 0.4408 -0.2323 231 | vn 0.2323 0.4408 0.8670 232 | vn -0.2323 0.4408 0.8670 233 | vn -0.8670 0.4408 0.2323 234 | vn 0.6347 0.4408 0.6347 235 | vn -0.6347 0.4408 0.6347 236 | usemtl Material.001 237 | s 1 238 | f 1/1/1 3/2/1 2/3/1 239 | f 3/2/2 5/4/2 2/3/2 240 | f 6/5/3 7/6/3 5/4/3 241 | f 7/6/4 10/7/4 9/8/4 242 | f 9/8/5 12/9/5 11/10/5 243 | f 12/9/6 13/11/6 11/10/6 244 | f 14/12/7 15/13/7 13/11/7 245 | f 15/13/8 18/14/8 17/15/8 246 | f 17/15/9 20/16/9 19/17/9 247 | f 20/16/10 21/18/10 19/17/10 248 | f 20/16/11 23/19/11 22/20/11 249 | f 22/20/12 25/21/12 21/18/12 250 | f 26/22/13 1/1/13 25/21/13 251 | f 7/6/14 15/13/14 25/21/14 252 | f 18/14/15 24/23/15 20/16/15 253 | f 18/14/16 28/24/16 27/25/16 254 | f 16/26/17 29/27/17 28/24/17 255 | f 12/9/18 29/27/18 14/12/18 256 | f 10/7/19 30/28/19 12/9/19 257 | f 10/7/20 32/29/20 31/30/20 258 | f 4/31/21 34/32/21 33/33/21 259 | f 3/2/22 33/33/22 35/34/22 260 | f 6/5/23 32/29/23 8/35/23 261 | f 22/20/24 34/32/24 26/22/24 262 | f 3/2/25 36/36/25 6/5/25 263 | f 25/21/14 1/1/14 2/3/14 264 | f 2/3/14 5/4/14 7/6/14 265 | f 7/6/14 9/8/14 11/10/14 266 | f 11/10/14 13/11/14 15/13/14 267 | f 15/13/14 17/15/14 19/17/14 268 | f 19/17/14 21/18/14 25/21/14 269 | f 25/21/14 2/3/14 7/6/14 270 | f 7/6/14 11/10/14 15/13/14 271 | f 15/13/14 19/17/14 25/21/14 272 | f 40/37/26 38/38/26 37/39/26 273 | f 44/40/27 42/41/27 41/42/27 274 | f 48/43/28 46/44/28 45/45/28 275 | f 50/46/29 37/39/29 49/47/29 276 | f 54/48/30 52/49/30 51/50/30 277 | f 56/51/31 41/42/31 55/52/31 278 | f 58/53/32 45/45/32 57/54/32 279 | f 53/55/33 49/47/33 52/49/33 280 | f 60/56/34 51/50/34 59/57/34 281 | f 38/38/35 56/51/35 55/52/35 282 | f 42/41/36 58/53/36 57/54/36 283 | f 47/58/37 59/57/37 46/44/37 284 | f 36/36/38 38/38/38 32/29/38 285 | f 24/23/38 59/57/38 23/19/38 286 | f 29/27/38 57/54/38 28/24/38 287 | f 32/29/38 55/52/38 31/30/38 288 | f 23/19/38 51/50/38 34/32/38 289 | f 33/33/38 49/47/38 35/34/38 290 | f 28/24/38 45/45/38 27/25/38 291 | f 31/30/38 41/42/38 30/28/38 292 | f 34/32/38 52/49/38 33/33/38 293 | f 35/34/38 37/39/38 36/36/38 294 | f 27/25/38 46/44/38 24/23/38 295 | f 30/28/38 42/41/38 29/27/38 296 | f 64/59/39 62/60/39 61/61/39 297 | f 64/59/40 65/62/40 63/63/40 298 | f 66/64/41 67/65/41 65/62/41 299 | f 70/66/42 67/65/42 68/67/42 300 | f 72/68/43 69/69/43 70/66/43 301 | f 74/70/44 71/71/44 72/68/44 302 | f 76/72/45 73/73/45 74/70/45 303 | f 78/74/46 75/75/46 76/72/46 304 | f 78/74/47 79/76/47 77/77/47 305 | f 80/78/48 81/79/48 79/76/48 306 | f 81/79/49 47/58/49 79/76/49 307 | f 84/80/50 81/79/50 82/81/50 308 | f 84/80/51 62/60/51 83/82/51 309 | f 68/67/52 84/80/52 76/72/52 310 | f 79/76/53 48/43/53 77/77/53 311 | f 77/77/54 58/53/54 75/75/54 312 | f 58/53/55 73/73/55 75/75/55 313 | f 43/83/56 71/71/56 73/73/56 314 | f 44/40/57 69/69/57 71/71/57 315 | f 56/51/58 67/65/58 69/69/58 316 | f 62/60/59 54/48/59 83/82/59 317 | f 50/46/60 62/60/60 63/63/60 318 | f 67/65/61 40/37/61 65/62/61 319 | f 83/82/62 60/56/62 81/79/62 320 | f 40/37/63 63/63/63 65/62/63 321 | f 84/80/52 64/59/52 61/61/52 322 | f 64/59/52 68/67/52 66/64/52 323 | f 68/67/52 72/68/52 70/66/52 324 | f 72/68/52 76/72/52 74/70/52 325 | f 76/72/52 80/78/52 78/74/52 326 | f 80/78/52 84/80/52 82/81/52 327 | f 84/80/52 68/67/52 64/59/52 328 | f 68/67/52 76/72/52 72/68/52 329 | f 76/72/52 84/80/52 80/78/52 330 | f 1/1/1 4/31/1 3/2/1 331 | f 3/2/2 6/5/2 5/4/2 332 | f 6/5/3 8/35/3 7/6/3 333 | f 7/6/4 8/35/4 10/7/4 334 | f 9/8/5 10/7/5 12/9/5 335 | f 12/9/6 14/12/6 13/11/6 336 | f 14/12/7 16/26/7 15/13/7 337 | f 15/13/8 16/26/8 18/14/8 338 | f 17/15/9 18/14/9 20/16/9 339 | f 20/16/10 22/20/10 21/18/10 340 | f 20/16/11 24/23/11 23/19/11 341 | f 22/20/12 26/22/12 25/21/12 342 | f 26/22/13 4/31/13 1/1/13 343 | f 18/14/15 27/25/15 24/23/15 344 | f 18/14/16 16/26/16 28/24/16 345 | f 16/26/17 14/12/17 29/27/17 346 | f 12/9/18 30/28/18 29/27/18 347 | f 10/7/19 31/30/19 30/28/19 348 | f 10/7/20 8/35/20 32/29/20 349 | f 4/31/21 26/22/21 34/32/21 350 | f 3/2/22 4/31/22 33/33/22 351 | f 6/5/23 36/36/23 32/29/23 352 | f 22/20/24 23/19/24 34/32/24 353 | f 3/2/25 35/34/25 36/36/25 354 | f 40/37/26 39/84/26 38/38/26 355 | f 44/40/27 43/83/27 42/41/27 356 | f 48/43/28 47/58/28 46/44/28 357 | f 50/46/29 40/37/29 37/39/29 358 | f 54/48/30 53/55/30 52/49/30 359 | f 56/51/31 44/40/31 41/42/31 360 | f 58/53/32 48/43/32 45/45/32 361 | f 53/55/33 50/46/33 49/47/33 362 | f 60/56/34 54/48/34 51/50/34 363 | f 38/38/35 39/84/35 56/51/35 364 | f 42/41/36 43/83/36 58/53/36 365 | f 47/58/37 60/56/37 59/57/37 366 | f 36/36/38 37/39/38 38/38/38 367 | f 24/23/38 46/44/38 59/57/38 368 | f 29/27/38 42/41/38 57/54/38 369 | f 32/29/38 38/38/38 55/52/38 370 | f 23/19/38 59/57/38 51/50/38 371 | f 33/33/38 52/49/38 49/47/38 372 | f 28/24/38 57/54/38 45/45/38 373 | f 31/30/38 55/52/38 41/42/38 374 | f 34/32/38 51/50/38 52/49/38 375 | f 35/34/38 49/47/38 37/39/38 376 | f 27/25/38 45/45/38 46/44/38 377 | f 30/28/38 41/42/38 42/41/38 378 | f 64/59/39 63/63/39 62/60/39 379 | f 64/59/40 66/64/40 65/62/40 380 | f 66/64/41 68/67/41 67/65/41 381 | f 70/66/42 69/69/42 67/65/42 382 | f 72/68/43 71/71/43 69/69/43 383 | f 74/70/44 73/73/44 71/71/44 384 | f 76/72/45 75/75/45 73/73/45 385 | f 78/74/46 77/77/46 75/75/46 386 | f 78/74/47 80/78/47 79/76/47 387 | f 80/78/48 82/81/48 81/79/48 388 | f 81/79/49 60/56/49 47/58/49 389 | f 84/80/50 83/82/50 81/79/50 390 | f 84/80/51 61/61/51 62/60/51 391 | f 79/76/53 47/58/53 48/43/53 392 | f 77/77/54 48/43/54 58/53/54 393 | f 58/53/55 43/83/55 73/73/55 394 | f 43/83/56 44/40/56 71/71/56 395 | f 44/40/57 56/51/57 69/69/57 396 | f 56/51/58 39/84/58 67/65/58 397 | f 62/60/59 53/55/59 54/48/59 398 | f 50/46/60 53/55/60 62/60/60 399 | f 67/65/61 39/84/61 40/37/61 400 | f 83/82/62 54/48/62 60/56/62 401 | f 40/37/63 50/46/63 63/63/63 402 | o Cylinder.004 403 | v -1.757394 -1.895375 -0.060000 404 | v -0.007336 -0.229707 -0.060000 405 | v 0.034029 -0.273169 -0.000000 406 | v -1.716029 -1.938837 -0.000000 407 | v -0.007336 -0.229707 0.060000 408 | v -1.757394 -1.895375 0.060000 409 | v -0.048702 -0.186246 -0.000000 410 | v -1.798760 -1.851914 -0.000000 411 | vt 0.171147 0.001058 412 | vt 0.150027 0.998942 413 | vt 0.150027 0.001058 414 | vt 0.128906 0.001058 415 | vt 0.751953 0.980234 416 | vt 0.751953 0.500234 417 | vt 0.991953 0.740234 418 | vt 0.107786 0.998942 419 | vt 0.107786 0.001058 420 | vt 0.086665 0.001058 421 | vt 0.750000 0.490000 422 | vt 0.750000 0.010000 423 | vt 0.510000 0.250000 424 | vt 0.171147 0.998942 425 | vt 0.128906 0.998942 426 | vt 0.511953 0.740234 427 | vt 0.086665 0.998942 428 | vt 0.990000 0.250000 429 | vn 0.4875 -0.5122 -0.7071 430 | vn 0.4875 -0.5122 0.7071 431 | vn 0.7244 0.6894 0.0000 432 | vn -0.4875 0.5122 0.7071 433 | vn -0.4875 0.5122 -0.7071 434 | vn -0.7244 -0.6894 0.0000 435 | vn -0.7243 -0.6894 0.0000 436 | vn 0.7243 0.6894 0.0000 437 | usemtl Material.001 438 | s 1 439 | f 85/85/64 87/86/64 88/87/64 440 | f 87/86/65 90/88/65 88/87/65 441 | f 86/89/66 89/90/66 87/91/66 442 | f 90/88/67 91/92/67 92/93/67 443 | f 91/92/68 85/94/68 92/93/68 444 | f 85/95/69 90/96/69 92/97/70 445 | f 85/85/64 86/98/64 87/86/64 446 | f 87/86/65 89/99/65 90/88/65 447 | f 86/89/66 91/100/71 89/90/66 448 | f 90/88/67 89/99/67 91/92/67 449 | f 91/92/68 86/101/68 85/94/68 450 | f 85/95/69 88/102/69 90/96/69 451 | o Cylinder.003 452 | v 0.000000 -2.811414 -0.130000 453 | v 0.000000 -1.788067 -0.130000 454 | v 0.130000 -1.788067 -0.000000 455 | v 0.130000 -2.811414 -0.000000 456 | v 0.000000 -1.788067 0.130000 457 | v 0.000000 -2.811414 0.130000 458 | v 0.000000 -1.415264 -0.000000 459 | v -0.130000 -1.788067 -0.000000 460 | v -0.130000 -2.811414 -0.000000 461 | vt 0.210623 0.829295 462 | vt 0.169652 0.563570 463 | vt 0.210623 0.563570 464 | vt 0.169652 0.829295 465 | vt 0.128682 0.563570 466 | vt 0.178994 0.018632 467 | vt 0.241359 0.018450 468 | vt 0.210557 0.148792 469 | vt 0.128682 0.829295 470 | vt 0.087711 0.563570 471 | vt 0.087711 0.829295 472 | vt 0.046740 0.563570 473 | vt 0.851829 0.092661 474 | vt 0.972761 0.092661 475 | vt 0.912295 0.032195 476 | vt 0.033710 0.022537 477 | vt 0.096075 0.022355 478 | vt 0.065273 0.152697 479 | vt 0.109356 0.022918 480 | vt 0.171722 0.022736 481 | vt 0.140919 0.153078 482 | vt 0.250584 0.019448 483 | vt 0.312950 0.019266 484 | vt 0.282147 0.149608 485 | vt 0.046740 0.829295 486 | vt 0.912295 0.153128 487 | vn 0.7071 0.0000 -0.7071 488 | vn 0.7071 -0.0000 0.7071 489 | vn 0.6865 0.2394 -0.6865 490 | vn -0.7071 -0.0000 0.7071 491 | vn -0.7071 0.0000 -0.7071 492 | vn 0.0000 -1.0000 0.0000 493 | vn -0.6865 0.2394 0.6865 494 | vn -0.6865 0.2394 -0.6865 495 | vn 0.6865 0.2394 0.6865 496 | usemtl Material.001 497 | s 1 498 | f 94/103/72 96/104/72 93/105/72 499 | f 95/106/73 98/107/73 96/104/73 500 | f 95/108/74 94/109/74 99/110/74 501 | f 97/111/75 101/112/75 98/107/75 502 | f 100/113/76 93/114/76 101/112/76 503 | f 96/115/77 101/116/77 93/117/77 504 | f 100/118/78 97/119/78 99/120/78 505 | f 94/121/79 100/122/79 99/123/79 506 | f 97/124/80 95/125/80 99/126/80 507 | f 94/103/72 95/106/72 96/104/72 508 | f 95/106/73 97/111/73 98/107/73 509 | f 97/111/75 100/113/75 101/112/75 510 | f 100/113/76 94/127/76 93/114/76 511 | f 96/115/77 98/128/77 101/116/77 512 | o Cylinder.005_Cylinder.004 513 | v -0.060000 -1.895375 1.757394 514 | v -0.060000 -0.229707 0.007336 515 | v 0.000000 -0.273169 -0.034029 516 | v 0.000000 -1.938837 1.716029 517 | v 0.060000 -0.229707 0.007336 518 | v 0.060000 -1.895375 1.757394 519 | v 0.000000 -0.186246 0.048702 520 | v 0.000000 -1.851914 1.798760 521 | vt 0.171147 0.998942 522 | vt 0.150027 0.001058 523 | vt 0.171147 0.001058 524 | vt 0.150027 0.998942 525 | vt 0.128906 0.001058 526 | vt 0.751953 0.980234 527 | vt 0.751953 0.500234 528 | vt 0.991953 0.740234 529 | vt 0.107786 0.998942 530 | vt 0.107786 0.001058 531 | vt 0.086665 0.998942 532 | vt 0.086665 0.001058 533 | vt 0.990000 0.250000 534 | vt 0.510000 0.250000 535 | vt 0.750000 0.490000 536 | vt 0.128906 0.998942 537 | vt 0.511953 0.740234 538 | vt 0.750000 0.010000 539 | vn -0.7071 -0.5122 -0.4875 540 | vn 0.7071 -0.5122 -0.4875 541 | vn 0.0000 0.6894 -0.7244 542 | vn 0.7071 0.5122 0.4875 543 | vn -0.7071 0.5122 0.4875 544 | vn 0.0000 -0.6894 0.7244 545 | vn 0.0000 0.6894 -0.7243 546 | usemtl Material.001 547 | s 1 548 | f 103/129/81 105/130/81 102/131/81 549 | f 104/132/82 107/133/82 105/130/82 550 | f 103/134/83 106/135/83 104/136/83 551 | f 107/133/84 108/137/84 109/138/84 552 | f 109/138/85 103/139/85 102/140/85 553 | f 105/141/86 109/142/86 102/143/86 554 | f 103/129/81 104/132/81 105/130/81 555 | f 104/132/82 106/144/82 107/133/82 556 | f 103/134/83 108/145/87 106/135/83 557 | f 107/133/84 106/144/84 108/137/84 558 | f 109/138/85 108/137/85 103/139/85 559 | f 105/141/86 107/146/86 109/142/86 560 | o Cylinder.006_Cylinder.004 561 | v 1.757394 -1.895375 0.060000 562 | v 0.007336 -0.229707 0.060000 563 | v -0.034029 -0.273169 -0.000000 564 | v 1.716029 -1.938837 -0.000000 565 | v 0.007336 -0.229707 -0.060000 566 | v 1.757394 -1.895375 -0.060000 567 | v 0.048702 -0.186246 -0.000000 568 | v 1.798760 -1.851914 -0.000000 569 | vt 0.171147 0.001058 570 | vt 0.150027 0.998942 571 | vt 0.150027 0.001058 572 | vt 0.128906 0.001058 573 | vt 0.751953 0.980234 574 | vt 0.751953 0.500234 575 | vt 0.991953 0.740234 576 | vt 0.107786 0.998942 577 | vt 0.107786 0.001058 578 | vt 0.086665 0.001058 579 | vt 0.750000 0.490000 580 | vt 0.750000 0.010000 581 | vt 0.510000 0.250000 582 | vt 0.171147 0.998942 583 | vt 0.128906 0.998942 584 | vt 0.511953 0.740234 585 | vt 0.086665 0.998942 586 | vt 0.990000 0.250000 587 | vn -0.4875 -0.5122 0.7071 588 | vn -0.4875 -0.5122 -0.7071 589 | vn -0.7244 0.6894 0.0000 590 | vn 0.4875 0.5122 -0.7071 591 | vn 0.4875 0.5122 0.7071 592 | vn 0.7244 -0.6894 0.0000 593 | vn 0.7243 -0.6894 0.0000 594 | vn -0.7243 0.6894 0.0000 595 | usemtl Material.001 596 | s 1 597 | f 110/147/88 112/148/88 113/149/88 598 | f 112/148/89 115/150/89 113/149/89 599 | f 111/151/90 114/152/90 112/153/90 600 | f 115/150/91 116/154/91 117/155/91 601 | f 116/154/92 110/156/92 117/155/92 602 | f 110/157/93 115/158/93 117/159/94 603 | f 110/147/88 111/160/88 112/148/88 604 | f 112/148/89 114/161/89 115/150/89 605 | f 111/151/90 116/162/95 114/152/90 606 | f 115/150/91 114/161/91 116/154/91 607 | f 116/154/92 111/163/92 110/156/92 608 | f 110/157/93 113/164/93 115/158/93 609 | o Cylinder.007_Cylinder.004 610 | v 0.060000 -1.895375 -1.757394 611 | v 0.060000 -0.229707 -0.007336 612 | v 0.000000 -0.273169 0.034029 613 | v 0.000000 -1.938837 -1.716029 614 | v -0.060000 -0.229707 -0.007336 615 | v -0.060000 -1.895375 -1.757394 616 | v 0.000000 -0.186246 -0.048702 617 | v 0.000000 -1.851914 -1.798760 618 | vt 0.171147 0.998942 619 | vt 0.150027 0.001058 620 | vt 0.171147 0.001058 621 | vt 0.150027 0.998942 622 | vt 0.128906 0.001058 623 | vt 0.751953 0.980234 624 | vt 0.751953 0.500234 625 | vt 0.991953 0.740234 626 | vt 0.107786 0.998942 627 | vt 0.107786 0.001058 628 | vt 0.086665 0.998942 629 | vt 0.086665 0.001058 630 | vt 0.990000 0.250000 631 | vt 0.510000 0.250000 632 | vt 0.750000 0.490000 633 | vt 0.128906 0.998942 634 | vt 0.511953 0.740234 635 | vt 0.750000 0.010000 636 | vn 0.7071 -0.5122 0.4875 637 | vn -0.7071 -0.5122 0.4875 638 | vn 0.0000 0.6894 0.7244 639 | vn -0.7071 0.5122 -0.4875 640 | vn 0.7071 0.5122 -0.4875 641 | vn 0.0000 -0.6894 -0.7244 642 | vn 0.0000 0.6894 0.7243 643 | usemtl Material.001 644 | s 1 645 | f 119/165/96 121/166/96 118/167/96 646 | f 120/168/97 123/169/97 121/166/97 647 | f 119/170/98 122/171/98 120/172/98 648 | f 123/169/99 124/173/99 125/174/99 649 | f 125/174/100 119/175/100 118/176/100 650 | f 121/177/101 125/178/101 118/179/101 651 | f 119/165/96 120/168/96 121/166/96 652 | f 120/168/97 122/180/97 123/169/97 653 | f 119/170/98 124/181/102 122/171/98 654 | f 123/169/99 122/180/99 124/173/99 655 | f 125/174/100 124/173/100 119/175/100 656 | f 121/177/101 123/182/101 125/178/101 657 | o Cylinder.008_Cylinder.005 658 | v 0.000000 -0.360062 -0.190000 659 | v 0.000000 0.069938 -0.190000 660 | v 0.134350 0.069938 -0.134350 661 | v 0.134350 -0.360062 -0.134350 662 | v 0.190000 0.069938 0.000000 663 | v 0.190000 -0.360062 -0.000000 664 | v 0.134350 0.069938 0.134350 665 | v 0.134350 -0.360062 0.134350 666 | v 0.000000 0.069938 0.190000 667 | v 0.000000 -0.360062 0.190000 668 | v -0.134350 0.069938 0.134350 669 | v -0.134350 -0.360062 0.134350 670 | v -0.190000 0.069938 0.000000 671 | v -0.190000 -0.360062 -0.000000 672 | v -0.134350 0.069938 -0.134350 673 | v -0.134350 -0.360062 -0.134350 674 | vt 0.749675 0.874838 675 | vt 0.687257 0.625162 676 | vt 0.749675 0.625162 677 | vt 0.687257 0.874838 678 | vt 0.624838 0.625162 679 | vt 0.624838 0.874838 680 | vt 0.562419 0.625162 681 | vt 0.562419 0.874838 682 | vt 0.500000 0.625162 683 | vt 0.500000 0.874838 684 | vt 0.437581 0.625162 685 | vt 0.437581 0.874838 686 | vt 0.375162 0.625162 687 | vt 0.721096 0.250000 688 | vt 0.612804 0.358292 689 | vt 0.504512 0.250000 690 | vt 0.375162 0.874838 691 | vt 0.312743 0.625162 692 | vt 0.312743 0.874838 693 | vt 0.250325 0.625162 694 | vt 0.310622 0.326574 695 | vt 0.463770 0.326574 696 | vt 0.463770 0.173426 697 | vt 0.536230 0.173426 698 | vt 0.612804 0.141708 699 | vt 0.689378 0.173426 700 | vt 0.689378 0.326574 701 | vt 0.536230 0.326574 702 | vt 0.387196 0.141708 703 | vt 0.310622 0.173426 704 | vt 0.278904 0.250000 705 | vt 0.387196 0.358292 706 | vt 0.495488 0.250000 707 | vt 0.250325 0.874838 708 | vn 0.3827 0.0000 -0.9239 709 | vn 0.9239 0.0000 -0.3827 710 | vn 0.9239 -0.0000 0.3827 711 | vn 0.3827 -0.0000 0.9239 712 | vn -0.3827 -0.0000 0.9239 713 | vn -0.9239 -0.0000 0.3827 714 | vn 0.0000 1.0000 0.0000 715 | vn -0.9239 0.0000 -0.3827 716 | vn -0.3827 0.0000 -0.9239 717 | vn 0.0000 -1.0000 -0.0000 718 | usemtl Material.001 719 | s 1 720 | f 127/183/103 129/184/103 126/185/103 721 | f 128/186/104 131/187/104 129/184/104 722 | f 130/188/105 133/189/105 131/187/105 723 | f 132/190/106 135/191/106 133/189/106 724 | f 134/192/107 137/193/107 135/191/107 725 | f 136/194/108 139/195/108 137/193/108 726 | f 138/196/109 134/197/109 130/198/109 727 | f 138/199/110 141/200/110 139/195/110 728 | f 140/201/111 126/202/111 141/200/111 729 | f 133/203/112 137/204/112 141/205/112 730 | f 130/198/109 128/206/109 127/207/109 731 | f 127/207/109 140/208/109 138/196/109 732 | f 138/196/109 136/209/109 134/197/109 733 | f 134/197/109 132/210/109 130/198/109 734 | f 130/198/109 127/207/109 138/196/109 735 | f 141/205/112 126/211/112 129/212/112 736 | f 129/212/112 131/213/112 133/203/112 737 | f 133/203/112 135/214/112 137/204/112 738 | f 137/204/112 139/215/112 141/205/112 739 | f 141/205/112 129/212/112 133/203/112 740 | f 127/183/103 128/186/103 129/184/103 741 | f 128/186/104 130/188/104 131/187/104 742 | f 130/188/105 132/190/105 133/189/105 743 | f 132/190/106 134/192/106 135/191/106 744 | f 134/192/107 136/194/107 137/193/107 745 | f 136/194/108 138/199/108 139/195/108 746 | f 138/199/110 140/201/110 141/200/110 747 | f 140/201/111 127/216/111 126/202/111 748 | o Cylinder.009_Cylinder.006 749 | v 0.000000 0.063290 -0.011143 750 | v 0.000000 0.288781 -0.011143 751 | v 0.011143 0.288781 0.000000 752 | v 0.011143 0.063290 0.000000 753 | v 0.000000 0.288781 0.011143 754 | v 0.000000 0.063290 0.011143 755 | v -0.011143 0.288781 0.000000 756 | v -0.011143 0.063290 0.000000 757 | vt 0.530396 0.854540 758 | vt 0.515198 0.645460 759 | vt 0.530396 0.645460 760 | vt 0.515198 0.854540 761 | vt 0.500000 0.645460 762 | vt 0.538416 0.213121 763 | vt 0.538416 0.286879 764 | vt 0.501537 0.250000 765 | vt 0.500000 0.854540 766 | vt 0.484802 0.645460 767 | vt 0.484802 0.854540 768 | vt 0.469604 0.645460 769 | vt 0.424705 0.250000 770 | vt 0.498463 0.250000 771 | vt 0.461584 0.213121 772 | vt 0.575295 0.250000 773 | vt 0.469604 0.854540 774 | vt 0.461584 0.286879 775 | vn 0.7071 0.0000 -0.7071 776 | vn 0.7071 -0.0000 0.7071 777 | vn 0.0000 1.0000 0.0000 778 | vn -0.7071 -0.0000 0.7071 779 | vn -0.7071 0.0000 -0.7071 780 | vn 0.0000 -1.0000 0.0000 781 | usemtl Material.001 782 | s 1 783 | f 143/217/113 145/218/113 142/219/113 784 | f 144/220/114 147/221/114 145/218/114 785 | f 143/222/115 146/223/115 144/224/115 786 | f 146/225/116 149/226/116 147/221/116 787 | f 148/227/117 142/228/117 149/226/117 788 | f 145/229/118 149/230/118 142/231/118 789 | f 143/217/113 144/220/113 145/218/113 790 | f 144/220/114 146/225/114 147/221/114 791 | f 143/222/115 148/232/115 146/223/115 792 | f 146/225/116 148/227/116 149/226/116 793 | f 148/227/117 143/233/117 142/228/117 794 | f 145/229/118 147/234/118 149/230/118 795 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/parabolic_antenna/parabolic_antenna_2.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'parabolic_antenna.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material.001 5 | Ns 224.999983 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd item/apple 14 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/ring/ring.mtl: -------------------------------------------------------------------------------- 1 | # Blender 4.2.1 LTS MTL File: 'None' 2 | # www.blender.org 3 | 4 | newmtl test_material 5 | Ns 250.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Ks 0.500000 0.500000 0.500000 8 | Ke 0.000000 0.000000 0.000000 9 | Ni 1.500000 10 | d 1.000000 11 | illum 2 12 | map_Kd #texture0 13 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/ring/ring.obj: -------------------------------------------------------------------------------- 1 | # Blender 4.2.1 LTS 2 | # www.blender.org 3 | mtllib ring.mtl 4 | o トーラス 5 | v 1.250000 0.000000 0.000000 6 | v 1.000000 0.250000 0.000000 7 | v 0.750000 0.000000 0.000000 8 | v 1.000000 -0.250000 0.000000 9 | v 0.957555 0.000000 -0.803485 10 | v 0.766044 0.250000 -0.642788 11 | v 0.574533 0.000000 -0.482091 12 | v 0.766044 -0.250000 -0.642788 13 | v 0.217060 0.000000 -1.231010 14 | v 0.173648 0.250000 -0.984808 15 | v 0.130236 0.000000 -0.738606 16 | v 0.173648 -0.250000 -0.984808 17 | v -0.625000 0.000000 -1.082532 18 | v -0.500000 0.250000 -0.866026 19 | v -0.375000 0.000000 -0.649519 20 | v -0.500000 -0.250000 -0.866026 21 | v -1.174616 0.000000 -0.427526 22 | v -0.939692 0.250000 -0.342020 23 | v -0.704769 0.000000 -0.256515 24 | v -0.939692 -0.250000 -0.342020 25 | v -1.174616 0.000000 0.427525 26 | v -0.939693 0.250000 0.342020 27 | v -0.704769 0.000000 0.256515 28 | v -0.939693 -0.250000 0.342020 29 | v -0.625000 0.000000 1.082532 30 | v -0.500000 0.250000 0.866026 31 | v -0.375000 0.000000 0.649519 32 | v -0.500000 -0.250000 0.866026 33 | v 0.217060 0.000000 1.231010 34 | v 0.173648 0.250000 0.984808 35 | v 0.130236 0.000000 0.738606 36 | v 0.173648 -0.250000 0.984808 37 | v 0.957555 0.000000 0.803485 38 | v 0.766044 0.250000 0.642788 39 | v 0.574533 0.000000 0.482091 40 | v 0.766044 -0.250000 0.642788 41 | vn 0.6848 0.6848 -0.2492 42 | vn -0.6848 0.6848 0.2492 43 | vn -0.6848 -0.6848 0.2492 44 | vn 0.6848 -0.6848 -0.2492 45 | vn 0.3644 0.6848 -0.6311 46 | vn -0.3644 0.6848 0.6311 47 | vn -0.3644 -0.6848 0.6311 48 | vn 0.3644 -0.6848 -0.6311 49 | vn -0.1265 0.6848 -0.7177 50 | vn 0.1265 0.6848 0.7177 51 | vn 0.1265 -0.6848 0.7177 52 | vn -0.1265 -0.6848 -0.7177 53 | vn -0.5582 0.6848 -0.4684 54 | vn 0.5582 0.6848 0.4684 55 | vn 0.5582 -0.6848 0.4684 56 | vn -0.5582 -0.6848 -0.4684 57 | vn -0.7287 0.6848 -0.0000 58 | vn 0.7287 0.6848 -0.0000 59 | vn 0.7287 -0.6848 -0.0000 60 | vn -0.7287 -0.6848 -0.0000 61 | vn -0.5582 0.6848 0.4684 62 | vn 0.5582 0.6848 -0.4684 63 | vn 0.5582 -0.6848 -0.4684 64 | vn -0.5582 -0.6848 0.4684 65 | vn -0.1265 0.6848 0.7177 66 | vn 0.1265 0.6848 -0.7177 67 | vn 0.1265 -0.6848 -0.7177 68 | vn -0.1265 -0.6848 0.7177 69 | vn 0.3644 0.6848 0.6311 70 | vn -0.3644 0.6848 -0.6311 71 | vn -0.3644 -0.6848 -0.6311 72 | vn 0.3644 -0.6848 0.6311 73 | vn 0.6848 0.6848 0.2492 74 | vn -0.6848 0.6848 -0.2492 75 | vn -0.6848 -0.6848 -0.2492 76 | vn 0.6848 -0.6848 0.2492 77 | vt 0.555556 0.500000 78 | vt 0.666667 0.500000 79 | vt 0.666667 0.750000 80 | vt 0.555556 0.750000 81 | vt 0.666667 1.000000 82 | vt 0.555556 1.000000 83 | vt 0.555556 0.000000 84 | vt 0.666667 0.000000 85 | vt 0.666667 0.250000 86 | vt 0.555556 0.250000 87 | vt 0.777778 0.500000 88 | vt 0.777778 0.750000 89 | vt 0.777778 1.000000 90 | vt 0.777778 0.000000 91 | vt 0.777778 0.250000 92 | vt 0.888889 0.500000 93 | vt 0.888889 0.750000 94 | vt 0.888889 1.000000 95 | vt 0.888889 0.000000 96 | vt 0.888889 0.250000 97 | vt 1.000000 0.500000 98 | vt 1.000000 0.750000 99 | vt 1.000000 1.000000 100 | vt 1.000000 0.000000 101 | vt 1.000000 0.250000 102 | vt 0.000000 0.500000 103 | vt 0.111111 0.500000 104 | vt 0.111111 0.750000 105 | vt 0.000000 0.750000 106 | vt 0.111111 1.000000 107 | vt 0.000000 1.000000 108 | vt 0.000000 0.000000 109 | vt 0.111111 0.000000 110 | vt 0.111111 0.250000 111 | vt 0.000000 0.250000 112 | vt 0.222222 0.500000 113 | vt 0.222222 0.750000 114 | vt 0.222222 1.000000 115 | vt 0.222222 0.000000 116 | vt 0.222222 0.250000 117 | vt 0.333333 0.500000 118 | vt 0.333333 0.750000 119 | vt 0.333333 1.000000 120 | vt 0.333333 0.000000 121 | vt 0.333333 0.250000 122 | vt 0.444444 0.500000 123 | vt 0.444444 0.750000 124 | vt 0.444444 1.000000 125 | vt 0.444444 0.000000 126 | vt 0.444444 0.250000 127 | s 0 128 | usemtl test_material 129 | f 1/1/1 5/2/1 6/3/1 2/4/1 130 | f 2/4/2 6/3/2 7/5/2 3/6/2 131 | f 3/7/3 7/8/3 8/9/3 4/10/3 132 | f 4/10/4 8/9/4 5/2/4 1/1/4 133 | f 5/2/5 9/11/5 10/12/5 6/3/5 134 | f 6/3/6 10/12/6 11/13/6 7/5/6 135 | f 7/8/7 11/14/7 12/15/7 8/9/7 136 | f 8/9/8 12/15/8 9/11/8 5/2/8 137 | f 9/11/9 13/16/9 14/17/9 10/12/9 138 | f 10/12/10 14/17/10 15/18/10 11/13/10 139 | f 11/14/11 15/19/11 16/20/11 12/15/11 140 | f 12/15/12 16/20/12 13/16/12 9/11/12 141 | f 13/16/13 17/21/13 18/22/13 14/17/13 142 | f 14/17/14 18/22/14 19/23/14 15/18/14 143 | f 15/19/15 19/24/15 20/25/15 16/20/15 144 | f 16/20/16 20/25/16 17/21/16 13/16/16 145 | f 17/26/17 21/27/17 22/28/17 18/29/17 146 | f 18/29/18 22/28/18 23/30/18 19/31/18 147 | f 19/32/19 23/33/19 24/34/19 20/35/19 148 | f 20/35/20 24/34/20 21/27/20 17/26/20 149 | f 21/27/21 25/36/21 26/37/21 22/28/21 150 | f 22/28/22 26/37/22 27/38/22 23/30/22 151 | f 23/33/23 27/39/23 28/40/23 24/34/23 152 | f 24/34/24 28/40/24 25/36/24 21/27/24 153 | f 25/36/25 29/41/25 30/42/25 26/37/25 154 | f 26/37/26 30/42/26 31/43/26 27/38/26 155 | f 27/39/27 31/44/27 32/45/27 28/40/27 156 | f 28/40/28 32/45/28 29/41/28 25/36/28 157 | f 29/41/29 33/46/29 34/47/29 30/42/29 158 | f 30/42/30 34/47/30 35/48/30 31/43/30 159 | f 31/44/31 35/49/31 36/50/31 32/45/31 160 | f 32/45/32 36/50/32 33/46/32 29/41/32 161 | f 33/46/33 1/1/33 2/4/33 34/47/33 162 | f 34/47/34 2/4/34 3/6/34 35/48/34 163 | f 35/49/35 3/7/35 4/10/35 36/50/35 164 | f 36/50/36 4/10/36 1/1/36 33/46/36 165 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/ring/ring_2.mtl: -------------------------------------------------------------------------------- 1 | # Blender 4.2.1 LTS MTL File: 'None' 2 | # www.blender.org 3 | 4 | newmtl test_material 5 | Ns 250.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Ks 0.500000 0.500000 0.500000 8 | Ke 0.000000 0.000000 0.000000 9 | Ni 1.500000 10 | d 1.000000 11 | illum 2 12 | map_Kd item/apple 13 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/sea_cheken_pack/sea_chicken.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/models/item/sea_cheken_pack/sea_chicken.blend -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/sea_cheken_pack/sea_chicken.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'sea_chicken.blend' 2 | # Material Count: 2 3 | 4 | newmtl chken 5 | Ns 225.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd special-model-loader-test:item/cheken 14 | 15 | newmtl pack 16 | Ns 225.000000 17 | Ka 1.000000 1.000000 1.000000 18 | Kd 0.800000 0.800000 0.800000 19 | Ks 0.500000 0.500000 0.500000 20 | Ke 0.000000 0.000000 0.000000 21 | Ni 1.450000 22 | d 1.000000 23 | illum 2 24 | map_Kd special-model-loader-test:item/cheken_pack 25 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/sea_cheken_pack/sea_chicken.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.0.0 OBJ File: 'sea_chicken.blend' 2 | # www.blender.org 3 | mtllib sea_chicken.mtl 4 | o pack_立方体 5 | v -0.985420 -1.167350 0.005905 6 | v -0.985420 1.167350 0.005905 7 | v -0.985420 -1.167350 -0.005905 8 | v -0.985420 1.167350 -0.005905 9 | v 0.985420 -1.167350 0.005905 10 | v 0.985420 1.167350 0.005905 11 | v 0.985420 -1.167350 -0.005905 12 | v 0.985420 1.167350 -0.005905 13 | vt 0.375000 0.000000 14 | vt 0.625000 0.000000 15 | vt 0.625000 0.250000 16 | vt 0.375000 0.250000 17 | vt 0.625000 0.500000 18 | vt 0.375000 0.500000 19 | vt 0.625000 0.750000 20 | vt 0.375000 0.750000 21 | vt 0.625000 1.000000 22 | vt 0.375000 1.000000 23 | vt 0.125000 0.500000 24 | vt 0.125000 0.750000 25 | vt 0.875000 0.500000 26 | vt 0.875000 0.750000 27 | vn -1.0000 0.0000 0.0000 28 | vn 0.0000 0.0000 -1.0000 29 | vn 1.0000 0.0000 0.0000 30 | vn 0.0000 0.0000 1.0000 31 | vn 0.0000 -1.0000 0.0000 32 | vn 0.0000 1.0000 0.0000 33 | usemtl pack 34 | s off 35 | f 1/1/1 2/2/1 4/3/1 3/4/1 36 | f 3/4/2 4/3/2 8/5/2 7/6/2 37 | f 7/6/3 8/5/3 6/7/3 5/8/3 38 | f 5/8/4 6/7/4 2/9/4 1/10/4 39 | f 3/11/5 7/6/5 5/8/5 1/12/5 40 | f 8/5/6 4/13/6 2/14/6 6/7/6 41 | o chken_cheken 42 | v -0.695974 -0.976651 -0.004122 43 | v -0.319695 -0.852625 -0.257067 44 | v 0.187396 0.269045 -0.004122 45 | v 0.155231 0.046654 -0.173164 46 | v 0.187396 0.269045 -0.004122 47 | v -0.009971 -0.026913 -0.158743 48 | v 0.463203 -0.976651 -0.004122 49 | v 0.549722 -0.890132 -0.004122 50 | v 0.508870 -0.767122 -0.223969 51 | v 0.321090 -0.880648 -0.240693 52 | v -0.439289 -0.359904 -0.004122 53 | v -0.695974 -0.976651 -0.004122 54 | v -0.433613 -0.694016 -0.237826 55 | v -0.326702 -0.355187 -0.163503 56 | v 0.549722 -0.423916 -0.004122 57 | v 0.315927 0.140514 -0.004122 58 | v 0.282023 -0.090947 -0.180036 59 | v 0.441779 -0.511728 -0.208948 60 | vt 0.697716 0.500000 61 | vt 0.697716 0.500000 62 | vt 0.697716 0.750000 63 | vt 0.697716 0.750000 64 | vt 0.375000 0.250000 65 | vt 0.375000 0.250000 66 | vt 0.498776 0.301514 67 | vt 0.625000 0.427284 68 | vt 0.625000 0.427284 69 | vt 0.599205 0.453080 70 | vt 0.485929 0.500000 71 | vt 0.392364 0.500000 72 | vt 0.375000 0.482636 73 | vt 0.125000 0.500000 74 | vt 0.357636 0.500000 75 | vt 0.357636 0.750000 76 | vt 0.125000 0.750000 77 | vt 0.485929 0.750000 78 | vt 0.392364 0.750000 79 | vt 0.375000 0.000000 80 | vt 0.375000 0.000000 81 | vt 0.375000 0.767364 82 | vt 0.599205 0.796920 83 | vt 0.625000 0.822716 84 | vt 0.625000 0.822716 85 | vt 0.498776 0.948486 86 | vt 0.375000 1.000000 87 | vt 0.375000 1.000000 88 | vt 0.498776 0.000000 89 | vt 0.498776 0.250000 90 | vt 0.625000 0.000000 91 | vt 0.625000 0.250000 92 | vt 0.646125 0.500000 93 | vt 0.646125 0.750000 94 | vn -0.3311 0.6009 -0.7275 95 | vn -0.0143 0.1070 -0.9942 96 | vn -0.0104 -0.9102 -0.4141 97 | vn 0.9420 0.0943 -0.3222 98 | vn -0.4838 -0.2455 -0.8400 99 | vn 0.5206 -0.6695 -0.5299 100 | vn 0.0000 0.0000 1.0000 101 | vn -0.7921 0.3408 -0.5064 102 | vn -0.6460 0.6387 -0.4180 103 | vn 0.7662 0.3224 -0.5558 104 | vn 0.4844 0.4836 -0.7290 105 | usemtl chken 106 | s off 107 | f 12/15/7 14/16/7 13/17/7 11/18/7 108 | f 10/19/8 21/20/8 22/21/8 14/22/8 12/23/8 25/24/8 26/25/8 17/26/8 18/27/8 109 | f 10/28/9 18/29/9 15/30/9 9/31/9 110 | f 17/26/10 26/25/10 23/32/10 16/33/10 111 | f 9/34/11 20/35/11 21/20/11 10/19/11 112 | f 15/30/12 18/29/12 17/26/12 16/33/12 113 | f 15/36/13 16/33/13 23/32/13 24/37/13 11/38/13 13/39/13 19/40/13 20/41/13 9/42/13 114 | f 21/20/14 20/35/14 19/43/14 22/44/14 115 | f 13/45/15 14/46/15 22/44/15 19/43/15 116 | f 23/32/16 26/25/16 25/47/16 24/48/16 117 | f 12/15/17 11/18/17 24/48/17 25/47/17 118 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/test/test.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'test.blend' 2 | # Material Count: 1 3 | 4 | newmtl tex 5 | Ns 250.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd block/birch_planks 14 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/models/item/test/test.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.2.2 OBJ File: 'test.blend' 2 | # www.blender.org 3 | mtllib test.mtl 4 | o 立方体 5 | v -0.051783 0.264556 0.391743 6 | v -0.051783 0.730501 0.391743 7 | v -0.051783 0.264556 0.239970 8 | v -0.051783 0.730501 0.239970 9 | v 0.099990 0.264556 0.391743 10 | v 0.099990 0.730501 0.391743 11 | v 0.099990 0.264556 0.239970 12 | v 0.099990 0.730501 0.239970 13 | vt 0.375000 0.000000 14 | vt 0.625000 0.000000 15 | vt 0.625000 0.250000 16 | vt 0.375000 0.250000 17 | vt 0.625000 0.500000 18 | vt 0.375000 0.500000 19 | vt 0.625000 0.750000 20 | vt 0.375000 0.750000 21 | vt 0.625000 1.000000 22 | vt 0.375000 1.000000 23 | vt 0.125000 0.500000 24 | vt 0.125000 0.750000 25 | vt 0.875000 0.500000 26 | vt 0.875000 0.750000 27 | vn -1.0000 0.0000 0.0000 28 | vn 0.0000 0.0000 -1.0000 29 | vn 1.0000 0.0000 0.0000 30 | vn 0.0000 0.0000 1.0000 31 | vn 0.0000 -1.0000 0.0000 32 | vn 0.0000 1.0000 0.0000 33 | usemtl tex 34 | s off 35 | f 1/1/1 2/2/1 4/3/1 3/4/1 36 | f 3/4/2 4/3/2 8/5/2 7/6/2 37 | f 7/6/3 8/5/3 6/7/3 5/8/3 38 | f 5/8/4 6/7/4 2/9/4 1/10/4 39 | f 3/11/5 7/6/5 5/8/5 1/12/5 40 | f 8/5/6 4/13/6 2/14/6 6/7/6 41 | o 立方体.001 42 | v -0.265246 0.709407 0.393838 43 | v -0.265246 0.860616 0.393838 44 | v -0.265246 0.709407 0.237875 45 | v -0.265246 0.860616 0.237875 46 | v 0.313453 0.709407 0.393838 47 | v 0.313453 0.860616 0.393838 48 | v 0.313453 0.709407 0.237875 49 | v 0.313453 0.860616 0.237875 50 | vt 0.375000 0.000000 51 | vt 0.625000 0.000000 52 | vt 0.625000 0.250000 53 | vt 0.375000 0.250000 54 | vt 0.625000 0.500000 55 | vt 0.375000 0.500000 56 | vt 0.625000 0.750000 57 | vt 0.375000 0.750000 58 | vt 0.625000 1.000000 59 | vt 0.375000 1.000000 60 | vt 0.125000 0.500000 61 | vt 0.125000 0.750000 62 | vt 0.875000 0.500000 63 | vt 0.875000 0.750000 64 | vn -1.0000 0.0000 0.0000 65 | vn 0.0000 0.0000 -1.0000 66 | vn 1.0000 0.0000 0.0000 67 | vn 0.0000 0.0000 1.0000 68 | vn 0.0000 -1.0000 0.0000 69 | vn 0.0000 1.0000 0.0000 70 | usemtl tex 71 | s off 72 | f 9/15/7 10/16/7 12/17/7 11/18/7 73 | f 11/18/8 12/17/8 16/19/8 15/20/8 74 | f 15/20/9 16/19/9 14/21/9 13/22/9 75 | f 13/22/10 14/21/10 10/23/10 9/24/10 76 | f 11/25/11 15/20/11 13/22/11 9/26/11 77 | f 16/19/12 12/27/12 10/28/12 14/21/12 78 | o 立方体.002 79 | v 0.397554 0.709407 0.393838 80 | v 0.397554 0.860616 0.393838 81 | v 0.397554 0.709407 0.237875 82 | v 0.397554 0.860616 0.237875 83 | v 0.976252 0.709407 0.393838 84 | v 0.976252 0.860616 0.393838 85 | v 0.976252 0.709407 0.237875 86 | v 0.976252 0.860616 0.237875 87 | vt 0.375000 0.000000 88 | vt 0.625000 0.000000 89 | vt 0.625000 0.250000 90 | vt 0.375000 0.250000 91 | vt 0.625000 0.500000 92 | vt 0.375000 0.500000 93 | vt 0.625000 0.750000 94 | vt 0.375000 0.750000 95 | vt 0.625000 1.000000 96 | vt 0.375000 1.000000 97 | vt 0.125000 0.500000 98 | vt 0.125000 0.750000 99 | vt 0.875000 0.500000 100 | vt 0.875000 0.750000 101 | vn -1.0000 0.0000 0.0000 102 | vn 0.0000 0.0000 -1.0000 103 | vn 1.0000 0.0000 0.0000 104 | vn 0.0000 0.0000 1.0000 105 | vn 0.0000 -1.0000 0.0000 106 | vn 0.0000 1.0000 0.0000 107 | usemtl tex 108 | s off 109 | f 17/29/13 18/30/13 20/31/13 19/32/13 110 | f 19/32/14 20/31/14 24/33/14 23/34/14 111 | f 23/34/15 24/33/15 22/35/15 21/36/15 112 | f 21/36/16 22/35/16 18/37/16 17/38/16 113 | f 19/39/17 23/34/17 21/36/17 17/40/17 114 | f 24/33/18 20/41/18 18/42/18 22/35/18 115 | o 立方体.003 116 | v 0.398178 0.264556 0.391743 117 | v 0.398178 0.730501 0.391743 118 | v 0.398178 0.264556 0.239970 119 | v 0.398178 0.730501 0.239970 120 | v 0.549951 0.264556 0.391743 121 | v 0.549951 0.730501 0.391743 122 | v 0.549951 0.264556 0.239970 123 | v 0.549951 0.730501 0.239970 124 | vt 0.375000 0.000000 125 | vt 0.625000 0.000000 126 | vt 0.625000 0.250000 127 | vt 0.375000 0.250000 128 | vt 0.625000 0.500000 129 | vt 0.375000 0.500000 130 | vt 0.625000 0.750000 131 | vt 0.375000 0.750000 132 | vt 0.625000 1.000000 133 | vt 0.375000 1.000000 134 | vt 0.125000 0.500000 135 | vt 0.125000 0.750000 136 | vt 0.875000 0.500000 137 | vt 0.875000 0.750000 138 | vn -1.0000 0.0000 0.0000 139 | vn 0.0000 0.0000 -1.0000 140 | vn 1.0000 0.0000 0.0000 141 | vn 0.0000 0.0000 1.0000 142 | vn 0.0000 -1.0000 0.0000 143 | vn 0.0000 1.0000 0.0000 144 | usemtl tex 145 | s off 146 | f 25/43/19 26/44/19 28/45/19 27/46/19 147 | f 27/46/20 28/45/20 32/47/20 31/48/20 148 | f 31/48/21 32/47/21 30/49/21 29/50/21 149 | f 29/50/22 30/49/22 26/51/22 25/52/22 150 | f 27/53/23 31/48/23 29/50/23 25/54/23 151 | f 32/47/24 28/55/24 26/56/24 30/49/24 152 | o 立方体.004 153 | v 0.397554 0.240207 0.393838 154 | v 0.397554 0.391415 0.393838 155 | v 0.397554 0.240207 0.237875 156 | v 0.397554 0.391415 0.237875 157 | v 0.976252 0.240207 0.393838 158 | v 0.976252 0.391415 0.393838 159 | v 0.976252 0.240207 0.237875 160 | v 0.976252 0.391415 0.237875 161 | vt 0.375000 0.000000 162 | vt 0.625000 0.000000 163 | vt 0.625000 0.250000 164 | vt 0.375000 0.250000 165 | vt 0.625000 0.500000 166 | vt 0.375000 0.500000 167 | vt 0.625000 0.750000 168 | vt 0.375000 0.750000 169 | vt 0.625000 1.000000 170 | vt 0.375000 1.000000 171 | vt 0.125000 0.500000 172 | vt 0.125000 0.750000 173 | vt 0.875000 0.500000 174 | vt 0.875000 0.750000 175 | vn -1.0000 0.0000 0.0000 176 | vn 0.0000 0.0000 -1.0000 177 | vn 1.0000 0.0000 0.0000 178 | vn 0.0000 0.0000 1.0000 179 | vn 0.0000 -1.0000 0.0000 180 | vn 0.0000 1.0000 0.0000 181 | usemtl tex 182 | s off 183 | f 33/57/25 34/58/25 36/59/25 35/60/25 184 | f 35/60/26 36/59/26 40/61/26 39/62/26 185 | f 39/62/27 40/61/27 38/63/27 37/64/27 186 | f 37/64/28 38/63/28 34/65/28 33/66/28 187 | f 35/67/29 39/62/29 37/64/29 33/68/29 188 | f 40/61/30 36/69/30 34/70/30 38/63/30 189 | o 立方体.005 190 | v 0.397554 0.487739 0.393838 191 | v 0.397554 0.638948 0.393838 192 | v 0.397554 0.487739 0.237875 193 | v 0.397554 0.638948 0.237875 194 | v 0.976252 0.487739 0.393838 195 | v 0.976252 0.638948 0.393838 196 | v 0.976252 0.487739 0.237875 197 | v 0.976252 0.638948 0.237875 198 | vt 0.375000 0.000000 199 | vt 0.625000 0.000000 200 | vt 0.625000 0.250000 201 | vt 0.375000 0.250000 202 | vt 0.625000 0.500000 203 | vt 0.375000 0.500000 204 | vt 0.625000 0.750000 205 | vt 0.375000 0.750000 206 | vt 0.625000 1.000000 207 | vt 0.375000 1.000000 208 | vt 0.125000 0.500000 209 | vt 0.125000 0.750000 210 | vt 0.875000 0.500000 211 | vt 0.875000 0.750000 212 | vn -1.0000 0.0000 0.0000 213 | vn 0.0000 0.0000 -1.0000 214 | vn 1.0000 0.0000 0.0000 215 | vn 0.0000 0.0000 1.0000 216 | vn 0.0000 -1.0000 0.0000 217 | vn 0.0000 1.0000 0.0000 218 | usemtl tex 219 | s off 220 | f 41/71/31 42/72/31 44/73/31 43/74/31 221 | f 43/74/32 44/73/32 48/75/32 47/76/32 222 | f 47/76/33 48/75/33 46/77/33 45/78/33 223 | f 45/78/34 46/77/34 42/79/34 41/80/34 224 | f 43/81/35 47/76/35 45/78/35 41/82/35 225 | f 48/75/36 44/83/36 42/84/36 46/77/36 226 | o 立方体.006 227 | v 1.094479 0.709407 0.393838 228 | v 1.094479 0.860616 0.393838 229 | v 1.094479 0.709407 0.237875 230 | v 1.094479 0.860616 0.237875 231 | v 1.673178 0.709407 0.393838 232 | v 1.673178 0.860616 0.393838 233 | v 1.673178 0.709407 0.237875 234 | v 1.673178 0.860616 0.237875 235 | vt 0.375000 0.000000 236 | vt 0.625000 0.000000 237 | vt 0.625000 0.250000 238 | vt 0.375000 0.250000 239 | vt 0.625000 0.500000 240 | vt 0.375000 0.500000 241 | vt 0.625000 0.750000 242 | vt 0.375000 0.750000 243 | vt 0.625000 1.000000 244 | vt 0.375000 1.000000 245 | vt 0.125000 0.500000 246 | vt 0.125000 0.750000 247 | vt 0.875000 0.500000 248 | vt 0.875000 0.750000 249 | vn -1.0000 0.0000 0.0000 250 | vn 0.0000 0.0000 -1.0000 251 | vn 1.0000 0.0000 0.0000 252 | vn 0.0000 0.0000 1.0000 253 | vn 0.0000 -1.0000 0.0000 254 | vn 0.0000 1.0000 0.0000 255 | usemtl tex 256 | s off 257 | f 49/85/37 50/86/37 52/87/37 51/88/37 258 | f 51/88/38 52/87/38 56/89/38 55/90/38 259 | f 55/90/39 56/89/39 54/91/39 53/92/39 260 | f 53/92/40 54/91/40 50/93/40 49/94/40 261 | f 51/95/41 55/90/41 53/92/41 49/96/41 262 | f 56/89/42 52/97/42 50/98/42 54/91/42 263 | o 立方体.007 264 | v 1.099454 0.537770 0.391743 265 | v 1.099454 0.723567 0.391743 266 | v 1.099454 0.537770 0.239970 267 | v 1.099454 0.723567 0.239970 268 | v 1.251227 0.537770 0.391743 269 | v 1.251227 0.723567 0.391743 270 | v 1.251227 0.537770 0.239970 271 | v 1.251227 0.723567 0.239970 272 | vt 0.375000 0.000000 273 | vt 0.625000 0.000000 274 | vt 0.625000 0.250000 275 | vt 0.375000 0.250000 276 | vt 0.625000 0.500000 277 | vt 0.375000 0.500000 278 | vt 0.625000 0.750000 279 | vt 0.375000 0.750000 280 | vt 0.625000 1.000000 281 | vt 0.375000 1.000000 282 | vt 0.125000 0.500000 283 | vt 0.125000 0.750000 284 | vt 0.875000 0.500000 285 | vt 0.875000 0.750000 286 | vn -1.0000 0.0000 0.0000 287 | vn 0.0000 0.0000 -1.0000 288 | vn 1.0000 0.0000 0.0000 289 | vn 0.0000 0.0000 1.0000 290 | vn 0.0000 -1.0000 0.0000 291 | vn 0.0000 1.0000 0.0000 292 | usemtl tex 293 | s off 294 | f 57/99/43 58/100/43 60/101/43 59/102/43 295 | f 59/102/44 60/101/44 64/103/44 63/104/44 296 | f 63/104/45 64/103/45 62/105/45 61/106/45 297 | f 61/106/46 62/105/46 58/107/46 57/108/46 298 | f 59/109/47 63/104/47 61/106/47 57/110/47 299 | f 64/103/48 60/111/48 58/112/48 62/105/48 300 | o 立方体.008 301 | v 1.094479 0.447644 0.393838 302 | v 1.094479 0.598853 0.393838 303 | v 1.094479 0.447644 0.237875 304 | v 1.094479 0.598853 0.237875 305 | v 1.673178 0.447644 0.393838 306 | v 1.673178 0.598853 0.393838 307 | v 1.673178 0.447644 0.237875 308 | v 1.673178 0.598853 0.237875 309 | vt 0.375000 0.000000 310 | vt 0.625000 0.000000 311 | vt 0.625000 0.250000 312 | vt 0.375000 0.250000 313 | vt 0.625000 0.500000 314 | vt 0.375000 0.500000 315 | vt 0.625000 0.750000 316 | vt 0.375000 0.750000 317 | vt 0.625000 1.000000 318 | vt 0.375000 1.000000 319 | vt 0.125000 0.500000 320 | vt 0.125000 0.750000 321 | vt 0.875000 0.500000 322 | vt 0.875000 0.750000 323 | vn -1.0000 0.0000 0.0000 324 | vn 0.0000 0.0000 -1.0000 325 | vn 1.0000 0.0000 0.0000 326 | vn 0.0000 0.0000 1.0000 327 | vn 0.0000 -1.0000 0.0000 328 | vn 0.0000 1.0000 0.0000 329 | usemtl tex 330 | s off 331 | f 65/113/49 66/114/49 68/115/49 67/116/49 332 | f 67/116/50 68/115/50 72/117/50 71/118/50 333 | f 71/118/51 72/117/51 70/119/51 69/120/51 334 | f 69/120/52 70/119/52 66/121/52 65/122/52 335 | f 67/123/53 71/118/53 69/120/53 65/124/53 336 | f 72/117/54 68/125/54 66/126/54 70/119/54 337 | o 立方体.009 338 | v 1.517694 0.271846 0.391743 339 | v 1.517694 0.457643 0.391743 340 | v 1.517694 0.271846 0.239970 341 | v 1.517694 0.457643 0.239970 342 | v 1.669467 0.271846 0.391743 343 | v 1.669467 0.457643 0.391743 344 | v 1.669467 0.271846 0.239970 345 | v 1.669467 0.457643 0.239970 346 | vt 0.375000 0.000000 347 | vt 0.625000 0.000000 348 | vt 0.625000 0.250000 349 | vt 0.375000 0.250000 350 | vt 0.625000 0.500000 351 | vt 0.375000 0.500000 352 | vt 0.625000 0.750000 353 | vt 0.375000 0.750000 354 | vt 0.625000 1.000000 355 | vt 0.375000 1.000000 356 | vt 0.125000 0.500000 357 | vt 0.125000 0.750000 358 | vt 0.875000 0.500000 359 | vt 0.875000 0.750000 360 | vn -1.0000 0.0000 0.0000 361 | vn 0.0000 0.0000 -1.0000 362 | vn 1.0000 0.0000 0.0000 363 | vn 0.0000 0.0000 1.0000 364 | vn 0.0000 -1.0000 0.0000 365 | vn 0.0000 1.0000 0.0000 366 | usemtl tex 367 | s off 368 | f 73/127/55 74/128/55 76/129/55 75/130/55 369 | f 75/130/56 76/129/56 80/131/56 79/132/56 370 | f 79/132/57 80/131/57 78/133/57 77/134/57 371 | f 77/134/58 78/133/58 74/135/58 73/136/58 372 | f 75/137/59 79/132/59 77/134/59 73/138/59 373 | f 80/131/60 76/139/60 74/140/60 78/133/60 374 | o 立方体.010 375 | v 1.094479 0.236851 0.393838 376 | v 1.094479 0.388060 0.393838 377 | v 1.094479 0.236851 0.237875 378 | v 1.094479 0.388060 0.237875 379 | v 1.673178 0.236851 0.393838 380 | v 1.673178 0.388060 0.393838 381 | v 1.673178 0.236851 0.237875 382 | v 1.673178 0.388060 0.237875 383 | vt 0.375000 0.000000 384 | vt 0.625000 0.000000 385 | vt 0.625000 0.250000 386 | vt 0.375000 0.250000 387 | vt 0.625000 0.500000 388 | vt 0.375000 0.500000 389 | vt 0.625000 0.750000 390 | vt 0.375000 0.750000 391 | vt 0.625000 1.000000 392 | vt 0.375000 1.000000 393 | vt 0.125000 0.500000 394 | vt 0.125000 0.750000 395 | vt 0.875000 0.500000 396 | vt 0.875000 0.750000 397 | vn -1.0000 0.0000 0.0000 398 | vn 0.0000 0.0000 -1.0000 399 | vn 1.0000 0.0000 0.0000 400 | vn 0.0000 0.0000 1.0000 401 | vn 0.0000 -1.0000 0.0000 402 | vn 0.0000 1.0000 0.0000 403 | usemtl tex 404 | s off 405 | f 81/141/61 82/142/61 84/143/61 83/144/61 406 | f 83/144/62 84/143/62 88/145/62 87/146/62 407 | f 87/146/63 88/145/63 86/147/63 85/148/63 408 | f 85/148/64 86/147/64 82/149/64 81/150/64 409 | f 83/151/65 87/146/65 85/148/65 81/152/65 410 | f 88/145/66 84/153/66 82/154/66 86/147/66 411 | o 立方体.011 412 | v 1.730660 0.709407 0.393838 413 | v 1.730660 0.860616 0.393838 414 | v 1.730660 0.709407 0.237875 415 | v 1.730660 0.860616 0.237875 416 | v 2.309359 0.709407 0.393838 417 | v 2.309359 0.860616 0.393838 418 | v 2.309359 0.709407 0.237875 419 | v 2.309359 0.860616 0.237875 420 | vt 0.375000 0.000000 421 | vt 0.625000 0.000000 422 | vt 0.625000 0.250000 423 | vt 0.375000 0.250000 424 | vt 0.625000 0.500000 425 | vt 0.375000 0.500000 426 | vt 0.625000 0.750000 427 | vt 0.375000 0.750000 428 | vt 0.625000 1.000000 429 | vt 0.375000 1.000000 430 | vt 0.125000 0.500000 431 | vt 0.125000 0.750000 432 | vt 0.875000 0.500000 433 | vt 0.875000 0.750000 434 | vn -1.0000 0.0000 0.0000 435 | vn 0.0000 0.0000 -1.0000 436 | vn 1.0000 0.0000 0.0000 437 | vn 0.0000 0.0000 1.0000 438 | vn 0.0000 -1.0000 0.0000 439 | vn 0.0000 1.0000 0.0000 440 | usemtl tex 441 | s off 442 | f 89/155/67 90/156/67 92/157/67 91/158/67 443 | f 91/158/68 92/157/68 96/159/68 95/160/68 444 | f 95/160/69 96/159/69 94/161/69 93/162/69 445 | f 93/162/70 94/161/70 90/163/70 89/164/70 446 | f 91/165/71 95/160/71 93/162/71 89/166/71 447 | f 96/159/72 92/167/72 90/168/72 94/161/72 448 | o 立方体.012 449 | v 1.944123 0.264556 0.391743 450 | v 1.944123 0.730501 0.391743 451 | v 1.944123 0.264556 0.239970 452 | v 1.944123 0.730501 0.239970 453 | v 2.095896 0.264556 0.391743 454 | v 2.095896 0.730501 0.391743 455 | v 2.095896 0.264556 0.239970 456 | v 2.095896 0.730501 0.239970 457 | vt 0.375000 0.000000 458 | vt 0.625000 0.000000 459 | vt 0.625000 0.250000 460 | vt 0.375000 0.250000 461 | vt 0.625000 0.500000 462 | vt 0.375000 0.500000 463 | vt 0.625000 0.750000 464 | vt 0.375000 0.750000 465 | vt 0.625000 1.000000 466 | vt 0.375000 1.000000 467 | vt 0.125000 0.500000 468 | vt 0.125000 0.750000 469 | vt 0.875000 0.500000 470 | vt 0.875000 0.750000 471 | vn -1.0000 0.0000 0.0000 472 | vn 0.0000 0.0000 -1.0000 473 | vn 1.0000 0.0000 0.0000 474 | vn 0.0000 0.0000 1.0000 475 | vn 0.0000 -1.0000 0.0000 476 | vn 0.0000 1.0000 0.0000 477 | usemtl tex 478 | s off 479 | f 97/169/73 98/170/73 100/171/73 99/172/73 480 | f 99/172/74 100/171/74 104/173/74 103/174/74 481 | f 103/174/75 104/173/75 102/175/75 101/176/75 482 | f 101/176/76 102/175/76 98/177/76 97/178/76 483 | f 99/179/77 103/174/77 101/176/77 97/180/77 484 | f 104/173/78 100/181/78 98/182/78 102/175/78 485 | -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/sml_load_scopes/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "entry": [ 4 | "test:.*" 5 | ] 6 | } -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/body.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/eay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/eay.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_front.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_side.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/facing_model_block_top.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/block/normal_model_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/block/normal_model_block.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/item/cheken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/item/cheken.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/item/cheken_pack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/item/cheken_pack.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/item/normal_model_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/item/normal_model_item.png -------------------------------------------------------------------------------- /src/test/resources/assets/special-model-loader-test/textures/item/parabolic_antenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/src/test/resources/assets/special-model-loader-test/textures/item/parabolic_antenna.png -------------------------------------------------------------------------------- /src/test/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "special-model-loader-test", 4 | "version": "1.0.0", 5 | "name": "Special Model Loader Test", 6 | "description": "The ikisugi test mod...", 7 | "authors": [ 8 | "MORIMORI0317" 9 | ], 10 | "contact": { 11 | }, 12 | "license": "IKISUGI", 13 | "environment": "*", 14 | "entrypoints": { 15 | "main": [ 16 | "dev.felnull.smltest.SMLTest" 17 | ], 18 | "client": [ 19 | "dev.felnull.smltest.client.SMLTestClient" 20 | ], 21 | "fabric-datagen": [ 22 | "dev.felnull.smltest.data.SMLTestDataGenerator" 23 | ] 24 | }, 25 | "depends": { 26 | "fabricloader": ">=0.16.9", 27 | "java": ">=21", 28 | "fabric-api": "*" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/test-resourcepacks/SMLTestPack.zip -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/assets/minecraft/models/item/3d_apple.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: '3d_apple.blend' 2 | # Material Count: 1 3 | 4 | newmtl マテリアル 5 | Ns 250.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd item/3d_apple 14 | -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/assets/minecraft/models/item/3d_apple.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.2.2 OBJ File: '3d_apple.blend' 2 | # www.blender.org 3 | mtllib 3d_apple.mtl 4 | o 球 5 | v 0.500000 0.500000 0.000000 6 | v 0.500000 0.146447 0.146447 7 | v 0.853553 0.853553 0.500000 8 | v 1.000000 0.500000 0.500000 9 | v 0.853553 0.146447 0.500000 10 | v 0.500000 1.000000 0.500000 11 | v 0.500000 0.853553 0.853553 12 | v 0.500000 0.500000 1.000000 13 | v 0.500000 0.146447 0.853553 14 | v 0.500000 0.000000 0.500000 15 | v 0.146447 0.853553 0.500000 16 | v -0.000000 0.500000 0.500000 17 | v 0.146447 0.146447 0.500000 18 | v 0.500000 0.853553 0.146447 19 | v 0.505114 1.198274 0.499034 20 | v 0.505114 0.948205 0.499034 21 | v 0.517079 1.198274 0.507727 22 | v 0.517079 0.948205 0.507727 23 | v 0.512508 1.198274 0.521793 24 | v 0.512508 0.948205 0.521793 25 | v 0.497719 1.198274 0.521793 26 | v 0.497719 0.948205 0.521793 27 | v 0.493149 1.198274 0.507727 28 | v 0.493149 0.948205 0.507727 29 | v 0.501273 1.086047 0.424095 30 | v 0.522778 1.092430 0.503667 31 | v 0.492983 1.082099 0.548012 32 | v 0.477389 1.115799 0.431938 33 | v 0.497546 1.146957 0.315857 34 | v 0.525598 1.132514 0.360189 35 | v 0.512185 1.126127 0.560689 36 | v 0.484133 1.140570 0.516357 37 | v 0.486953 1.180654 0.372879 38 | v 0.516748 1.190984 0.328534 39 | v 0.532342 1.157285 0.444608 40 | v 0.508459 1.187037 0.452451 41 | vt 0.343535 0.280806 42 | vt 0.172382 0.328915 43 | vt 0.172382 0.000410 44 | vt 0.343535 0.048518 45 | vt 0.529655 0.659058 46 | vt 0.529655 0.836844 47 | vt 0.353786 0.810808 48 | vt 0.352967 0.836844 49 | vt 0.177098 0.810808 50 | vt 0.352967 0.659058 51 | vt 0.687479 0.328915 52 | vt 0.516326 0.280806 53 | vt 0.516326 0.048518 54 | vt 0.687479 0.000410 55 | vt 0.171563 0.280806 56 | vt 0.000410 0.328915 57 | vt 0.000410 0.000410 58 | vt 0.171563 0.048518 59 | vt 0.823721 0.026446 60 | vt 0.999590 0.000410 61 | vt 0.999590 0.178195 62 | vt 0.864167 0.507520 63 | vt 0.688298 0.481483 64 | vt 0.864167 0.329734 65 | vt 0.515507 0.328915 66 | vt 0.344354 0.280806 67 | vt 0.344354 0.048518 68 | vt 0.515507 0.000410 69 | vt 0.172382 0.377842 70 | vt 0.343535 0.329734 71 | vt 0.343535 0.658239 72 | vt 0.172382 0.610131 73 | vt 0.822902 0.232698 74 | vt 0.688298 0.116554 75 | vt 0.822902 0.000410 76 | vt 0.706343 0.659058 77 | vt 0.706343 0.836844 78 | vt 0.530474 0.685094 79 | vt 0.000410 0.329734 80 | vt 0.171563 0.377842 81 | vt 0.171563 0.610131 82 | vt 0.000410 0.658239 83 | vt 0.516326 0.377842 84 | vt 0.687479 0.329734 85 | vt 0.687479 0.658239 86 | vt 0.516326 0.610131 87 | vt 0.176279 0.659058 88 | vt 0.176279 0.836844 89 | vt 0.000410 0.810808 90 | vt 0.883031 0.659058 91 | vt 0.883031 0.836844 92 | vt 0.707162 0.685094 93 | vt 0.515507 0.658239 94 | vt 0.344354 0.610131 95 | vt 0.344354 0.377842 96 | vt 0.515507 0.329734 97 | vt 0.784786 0.508339 98 | vt 0.784786 0.624515 99 | vt 0.777915 0.624515 100 | vt 0.777915 0.508339 101 | vt 0.792476 0.508339 102 | vt 0.792476 0.624515 103 | vt 0.785605 0.624515 104 | vt 0.785605 0.508339 105 | vt 0.777096 0.508339 106 | vt 0.777096 0.624516 107 | vt 0.770226 0.624516 108 | vt 0.770226 0.508339 109 | vt 0.721656 0.574769 110 | vt 0.715121 0.576892 111 | vt 0.711083 0.571333 112 | vt 0.715121 0.565775 113 | vt 0.721656 0.567898 114 | vt 0.688298 0.651369 115 | vt 0.804475 0.651368 116 | vt 0.804475 0.658239 117 | vt 0.688298 0.658239 118 | vt 0.688298 0.643679 119 | vt 0.804475 0.643679 120 | vt 0.804475 0.650549 121 | vt 0.688298 0.650549 122 | vt 0.721656 0.299947 123 | vt 0.715121 0.302070 124 | vt 0.711083 0.296512 125 | vt 0.715121 0.290953 126 | vt 0.721656 0.293076 127 | vt 0.796897 0.291243 128 | vt 0.783798 0.255138 129 | vt 0.796897 0.233517 130 | vt 0.750579 0.577560 131 | vt 0.733927 0.542949 132 | vt 0.750579 0.508339 133 | vt 0.751398 0.563184 134 | vt 0.769406 0.508339 135 | vt 0.769406 0.564956 136 | vt 0.744643 0.303557 137 | vt 0.744643 0.321653 138 | vt 0.688298 0.316109 139 | vt 0.806394 0.508339 140 | vt 0.806394 0.566065 141 | vt 0.793295 0.544444 142 | vt 0.710263 0.508339 143 | vt 0.710263 0.577560 144 | vt 0.688298 0.542949 145 | vt 0.791752 0.303557 146 | vt 0.791752 0.328837 147 | vt 0.769017 0.307525 148 | vt 0.710323 0.578379 149 | vt 0.710323 0.634996 150 | vt 0.688298 0.612952 151 | vt 0.733167 0.578379 152 | vt 0.733167 0.634997 153 | vt 0.711142 0.600424 154 | vt 0.792571 0.307904 155 | vt 0.817474 0.303557 156 | vt 0.817474 0.326636 157 | vt 0.711083 0.542912 158 | vt 0.733108 0.508339 159 | vt 0.733108 0.564956 160 | vt 0.745462 0.307525 161 | vt 0.768198 0.303557 162 | vt 0.768198 0.328837 163 | vt 0.688298 0.268128 164 | vt 0.710264 0.233517 165 | vt 0.710264 0.302738 166 | vt 0.818198 0.589963 167 | vt 0.793295 0.571230 168 | vt 0.818198 0.566884 169 | vt 0.711083 0.255561 170 | vt 0.733108 0.233517 171 | vt 0.733108 0.290134 172 | vt 0.751649 0.636106 173 | vt 0.733986 0.582314 174 | vt 0.751649 0.578379 175 | vt 0.752468 0.600000 176 | vt 0.765567 0.578379 177 | vt 0.765567 0.636106 178 | vt 0.750579 0.233517 179 | vt 0.750579 0.302738 180 | vt 0.733927 0.268128 181 | vt 0.782979 0.291243 182 | vt 0.769880 0.269622 183 | vt 0.782979 0.233517 184 | vt 0.751398 0.287309 185 | vt 0.769061 0.233517 186 | vt 0.769061 0.291243 187 | vn 0.6786 -0.2811 -0.6786 188 | vn 0.3574 0.8629 -0.3574 189 | vn 0.3574 -0.8629 -0.3574 190 | vn 0.6786 0.2811 -0.6786 191 | vn 0.6786 -0.2811 0.6786 192 | vn 0.3574 0.8629 0.3574 193 | vn 0.3574 -0.8629 0.3574 194 | vn 0.6786 0.2811 0.6786 195 | vn -0.6786 -0.2811 0.6786 196 | vn -0.3574 0.8629 0.3574 197 | vn -0.3574 -0.8629 0.3574 198 | vn -0.6786 0.2811 0.6786 199 | vn -0.6786 -0.2811 -0.6786 200 | vn -0.3574 0.8629 -0.3574 201 | vn -0.3574 -0.8629 -0.3574 202 | vn -0.6786 0.2811 -0.6786 203 | vn -0.5878 0.0000 0.8090 204 | vn -0.9511 0.0000 -0.3090 205 | vn 0.0000 0.0000 -1.0000 206 | vn 0.0000 1.0000 0.0000 207 | vn 0.9511 0.0000 -0.3090 208 | vn 0.5878 0.0000 0.8090 209 | vn 0.0000 -1.0000 0.0000 210 | vn 0.3154 -0.9489 -0.0091 211 | vn 0.7687 -0.6198 -0.1580 212 | vn -0.7870 -0.6127 -0.0722 213 | vn -0.7828 -0.5534 -0.2845 214 | vn 0.3245 -0.8195 -0.4723 215 | vn 0.9848 -0.1712 -0.0285 216 | vn 0.7824 -0.4616 0.4181 217 | vn -0.9900 -0.0924 0.1062 218 | vn -0.9845 -0.0139 -0.1747 219 | vn 0.8017 -0.1861 -0.5679 220 | vn 0.9845 0.0139 0.1747 221 | vn -0.8017 0.1861 0.5680 222 | vn -0.9848 0.1712 0.0285 223 | vn -0.7824 0.4616 -0.4181 224 | vn 0.9900 0.0924 -0.1062 225 | vn 0.7828 0.5534 0.2845 226 | vn -0.3245 0.8195 0.4723 227 | vn -0.7687 0.6198 0.1580 228 | vn -0.3154 0.9489 0.0091 229 | vn 0.7870 0.6127 0.0722 230 | usemtl マテリアル 231 | s off 232 | f 2/1/1 1/2/1 4/3/1 5/4/1 233 | f 14/5/2 6/6/2 3/7/2 234 | f 10/8/3 2/9/3 5/10/3 235 | f 1/11/4 14/12/4 3/13/4 4/14/4 236 | f 5/15/5 4/16/5 8/17/5 9/18/5 237 | f 3/19/6 6/20/6 7/21/6 238 | f 10/22/7 5/23/7 9/24/7 239 | f 4/25/8 3/26/8 7/27/8 8/28/8 240 | f 9/29/9 8/30/9 12/31/9 13/32/9 241 | f 7/33/10 6/34/10 11/35/10 242 | f 10/36/11 9/37/11 13/38/11 243 | f 8/39/12 7/40/12 11/41/12 12/42/12 244 | f 13/43/13 12/44/13 1/45/13 2/46/13 245 | f 11/47/14 6/48/14 14/49/14 246 | f 10/50/15 13/51/15 2/52/15 247 | f 12/53/16 11/54/16 14/55/16 1/56/16 248 | f 15/57/17 16/58/17 18/59/17 17/60/17 249 | f 17/61/18 18/62/18 20/63/18 19/64/18 250 | f 19/65/19 20/66/19 22/67/19 21/68/19 251 | f 18/69/20 16/70/20 24/71/20 22/72/20 20/73/20 252 | f 21/74/21 22/75/21 24/76/21 23/77/21 253 | f 23/78/22 24/79/22 16/80/22 15/81/22 254 | f 15/82/23 17/83/23 19/84/23 21/85/23 23/86/23 255 | f 25/87/24 26/88/24 27/89/24 256 | f 26/90/25 25/91/25 30/92/25 257 | f 25/93/26 27/94/26 28/95/26 258 | f 25/96/27 28/97/27 29/98/27 259 | f 25/99/28 29/100/28 30/101/28 260 | f 26/102/29 30/103/29 35/104/29 261 | f 27/105/30 26/106/30 31/107/30 262 | f 28/108/31 27/109/31 32/110/31 263 | f 29/111/32 28/112/32 33/113/32 264 | f 30/114/33 29/115/33 34/116/33 265 | f 26/117/34 35/118/34 31/119/34 266 | f 27/120/35 31/121/35 32/122/35 267 | f 28/123/36 32/124/36 33/125/36 268 | f 29/126/37 33/127/37 34/128/37 269 | f 30/129/38 34/130/38 35/131/38 270 | f 31/132/39 35/133/39 36/134/39 271 | f 32/135/40 31/136/40 36/137/40 272 | f 33/138/41 32/139/41 36/140/41 273 | f 34/141/42 33/142/42 36/143/42 274 | f 35/144/43 34/145/43 36/146/43 275 | -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/assets/minecraft/models/item/apple.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "special-model-loader:builtin/obj", 3 | "ambientocclusion": true, 4 | "flip_v": true, 5 | "model": "minecraft:models/item/3d_apple.obj" 6 | } -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/assets/minecraft/textures/item/3d_apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/test-resourcepacks/SMLTestPack/assets/minecraft/textures/item/3d_apple.png -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/assets/sml-test-pack/sml_load_scopes/test_scopes.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "entry": [ 4 | "minecraft:item/apple" 5 | ] 6 | } -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 12, 4 | "description": "The SML Test Pack" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test-resourcepacks/SMLTestPack/pack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamFelNull/SpecialModelLoader/c7ad159a7232da77e43422e84a6f4b6a76a4ebd2/test-resourcepacks/SMLTestPack/pack.png --------------------------------------------------------------------------------