B3D Improvements
- fixed keyframe transformation application - textures are now resolved the same way as in vanilla models - added the ability to use forge blockstate texture information - removed unused code from the B3D example
This commit is contained in:
parent
581363fddd
commit
d6bc936ffa
5 changed files with 96 additions and 133 deletions
|
@ -30,8 +30,10 @@ import net.minecraftforge.client.model.IColoredBakedQuad.ColoredBakedQuad;
|
|||
import net.minecraftforge.client.model.ICustomModelLoader;
|
||||
import net.minecraftforge.client.model.IFlexibleBakedModel;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
import net.minecraftforge.client.model.IModelCustomData;
|
||||
import net.minecraftforge.client.model.IModelPart;
|
||||
import net.minecraftforge.client.model.IModelState;
|
||||
import net.minecraftforge.client.model.IRetexturableModel;
|
||||
import net.minecraftforge.client.model.ISmartBlockModel;
|
||||
import net.minecraftforge.client.model.ISmartItemModel;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
|
@ -56,11 +58,14 @@ import org.apache.logging.log4j.Level;
|
|||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/*
|
||||
|
@ -238,24 +243,28 @@ public class B3DLoader implements ICustomModelLoader
|
|||
public static TRSRTransformation getNodeMatrix(Animation animation, Node<?> node, int frame)
|
||||
{
|
||||
TRSRTransformation ret = TRSRTransformation.identity();
|
||||
if(node.getParent() != null)
|
||||
{
|
||||
TRSRTransformation pm = cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node.getParent(), frame));
|
||||
ret = ret.compose(pm);
|
||||
}
|
||||
Key key = null;
|
||||
if(animation != null) key = animation.getKeys().get(frame, node);
|
||||
else if(key == null && node.getAnimation() != null && node.getAnimation() != animation) key = node.getAnimation().getKeys().get(frame, node);
|
||||
if(key == null)
|
||||
if(key != null)
|
||||
{
|
||||
FMLLog.severe("invalid key index: " + frame);
|
||||
Node<?> parent = node.getParent();
|
||||
if(parent != null)
|
||||
{
|
||||
TRSRTransformation pm = cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node.getParent(), frame));
|
||||
ret = ret.compose(pm);
|
||||
ret = ret.compose(new TRSRTransformation(parent.getPos(), parent.getRot(), parent.getScale(), null));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ret.compose(new TRSRTransformation(key.getPos(), key.getRot(), key.getScale(), null));
|
||||
Matrix4f rm = new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null).getMatrix();
|
||||
rm.invert();
|
||||
ret = ret.compose(new TRSRTransformation(rm));
|
||||
if(parent != null)
|
||||
{
|
||||
rm = new TRSRTransformation(parent.getPos(), parent.getRot(), parent.getScale(), null).getMatrix();
|
||||
rm.invert();
|
||||
ret = ret.compose(new TRSRTransformation(rm));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -305,14 +314,14 @@ public class B3DLoader implements ICustomModelLoader
|
|||
}
|
||||
}
|
||||
|
||||
public static class Wrapper extends PartWrapper<Mesh> implements IModel
|
||||
public static class Wrapper extends PartWrapper<Mesh> implements IRetexturableModel, IModelCustomData
|
||||
{
|
||||
private final ResourceLocation location;
|
||||
private final ImmutableMap<String, ResourceLocation> textures;
|
||||
|
||||
public Wrapper(ResourceLocation location, List<Texture> textures, B3DModel.Node<Mesh> mesh)
|
||||
{
|
||||
this(location, buildTextures(location, textures), mesh);
|
||||
this(location, buildTextures(textures), mesh);
|
||||
}
|
||||
|
||||
public Wrapper(ResourceLocation location, ImmutableMap<String, ResourceLocation> textures, B3DModel.Node<Mesh> mesh)
|
||||
|
@ -322,19 +331,24 @@ public class B3DLoader implements ICustomModelLoader
|
|||
this.textures = textures;
|
||||
}
|
||||
|
||||
private static ImmutableMap<String, ResourceLocation> buildTextures(ResourceLocation location, List<Texture> textures)
|
||||
private static ImmutableMap<String, ResourceLocation> buildTextures(List<Texture> textures)
|
||||
{
|
||||
ImmutableMap.Builder<String, ResourceLocation> builder = ImmutableMap.builder();
|
||||
|
||||
for(Texture t : textures)
|
||||
{
|
||||
String path = t.getPath();
|
||||
if(path.endsWith(".png")) path = path.substring(0, path.length() - ".png".length());
|
||||
builder.put(t.getPath(), new ResourceLocation(location.getResourceDomain(), path));
|
||||
builder.put(path, new ResourceLocation(getLocation(path)));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static String getLocation(String path)
|
||||
{
|
||||
if(path.endsWith(".png")) path = path.substring(0, path.length() - ".png".length());
|
||||
return path;
|
||||
}
|
||||
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
// no dependencies for in-file models
|
||||
|
@ -344,17 +358,32 @@ public class B3DLoader implements ICustomModelLoader
|
|||
|
||||
public Collection<ResourceLocation> getTextures()
|
||||
{
|
||||
return textures.values();
|
||||
return Collections2.filter(textures.values(), new Predicate<ResourceLocation>()
|
||||
{
|
||||
public boolean apply(ResourceLocation loc)
|
||||
{
|
||||
return !loc.getResourcePath().startsWith("#");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
ImmutableMap.Builder<String, TextureAtlasSprite> builder = ImmutableMap.builder();
|
||||
for(String path : textures.keySet())
|
||||
TextureAtlasSprite missing = bakedTextureGetter.apply(new ResourceLocation("missingno"));
|
||||
for(Map.Entry<String, ResourceLocation> e : textures.entrySet())
|
||||
{
|
||||
builder.put(path, bakedTextureGetter.apply(textures.get(path)));
|
||||
if(e.getValue().getResourcePath().startsWith("#"))
|
||||
{
|
||||
FMLLog.severe("unresolved texture '%s' for b3d model '%s'", e.getValue().getResourcePath(), location);
|
||||
builder.put(e.getKey(), missing);
|
||||
}
|
||||
builder.put("missingno", bakedTextureGetter.apply(new ResourceLocation("missingno")));
|
||||
else
|
||||
{
|
||||
builder.put(e.getKey(), bakedTextureGetter.apply(e.getValue()));
|
||||
}
|
||||
}
|
||||
builder.put("missingno", missing);
|
||||
return new BakedWrapper(this, state, format, builder.build());
|
||||
}
|
||||
|
||||
|
@ -396,6 +425,35 @@ public class B3DLoader implements ICustomModelLoader
|
|||
else if (!location.equals(other.location)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModel retexture(ImmutableMap<String, String> textures)
|
||||
{
|
||||
ImmutableMap.Builder<String, ResourceLocation> builder = ImmutableMap.builder();
|
||||
for(Map.Entry<String, ResourceLocation> e : this.textures.entrySet())
|
||||
{
|
||||
String path = e.getKey();
|
||||
String loc = getLocation(path);
|
||||
if(textures.containsKey(loc))
|
||||
{
|
||||
String newLoc = textures.get(loc);
|
||||
if(newLoc == null) newLoc = getLocation(path);
|
||||
builder.put(e.getKey(), new ResourceLocation(newLoc));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.put(e);
|
||||
}
|
||||
}
|
||||
return new Wrapper(location, builder.build(), getNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModel process(ImmutableMap<String, String> customData)
|
||||
{
|
||||
// TODO keyframe
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BakedWrapper implements IFlexibleBakedModel, ISmartBlockModel, ISmartItemModel
|
||||
|
@ -454,9 +512,10 @@ public class B3DLoader implements ICustomModelLoader
|
|||
for(Face f : faces)
|
||||
{
|
||||
buf.clear();
|
||||
List<Texture> textures = f.getBrush().getTextures();
|
||||
List<Texture> textures = null;
|
||||
if(f.getBrush() != null) textures = f.getBrush().getTextures();
|
||||
TextureAtlasSprite sprite;
|
||||
if(textures.isEmpty()) sprite = this.textures.get("missingno");
|
||||
if(textures == null || textures.isEmpty()) sprite = this.textures.get("missingno");
|
||||
else if(textures.get(0) == B3DModel.Texture.White) sprite = ModelLoader.White.instance;
|
||||
else sprite = this.textures.get(textures.get(0).getPath());
|
||||
putVertexData(f.getV1(), sprite);
|
||||
|
|
|
@ -64,14 +64,9 @@ public class ModelLoaderRegistryDebug
|
|||
|
||||
private void clientPreInit()
|
||||
{
|
||||
//ModelLoaderRegistry.registerLoader(DummyModelLoader.instance);
|
||||
B3DLoader.instance.addDomain(MODID.toLowerCase());
|
||||
//ModelBakery.addVariantName(Item.getItemFromBlock(CustomModelBlock.instance), "forgedebug:dummymodel");
|
||||
String modelLocation = MODID.toLowerCase() + ":untitled2.b3d";
|
||||
ModelBakery.addVariantName(Item.getItemFromBlock(CustomModelBlock.instance), modelLocation);
|
||||
Item item = Item.getItemFromBlock(CustomModelBlock.instance);
|
||||
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(modelLocation, "inventory"));
|
||||
//ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation("forgedebug:dummymodel", "inventory"));
|
||||
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(MODID.toLowerCase() + ":" + CustomModelBlock.name, "inventory"));
|
||||
}
|
||||
|
||||
public static class CustomModelBlock extends Block
|
||||
|
@ -100,9 +95,7 @@ public class ModelLoaderRegistryDebug
|
|||
@Override
|
||||
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
IModel model = ModelLoaderRegistry.getModel(new ResourceLocation(MODID.toLowerCase(),"block/untitled2.b3d"));
|
||||
B3DLoader.B3DState defaultState = ((B3DLoader.Wrapper)model).getDefaultState();
|
||||
B3DLoader.B3DState newState = new B3DLoader.B3DState(defaultState.getAnimation(), counter);
|
||||
B3DLoader.B3DState newState = new B3DLoader.B3DState(null, counter);
|
||||
return ((IExtendedBlockState)this.state.getBaseState()).withProperty(B3DLoader.B3DFrameProperty.instance, newState);
|
||||
}
|
||||
|
||||
|
@ -120,106 +113,4 @@ public class ModelLoaderRegistryDebug
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DummyModelLoader implements ICustomModelLoader
|
||||
{
|
||||
public static final DummyModelLoader instance = new DummyModelLoader();
|
||||
public static final ResourceLocation dummyTexture = new ResourceLocation("minecraft:blocks/dirt");
|
||||
|
||||
public boolean accepts(ResourceLocation modelLocation)
|
||||
{
|
||||
return modelLocation.getResourceDomain().equals("forgedebug") && modelLocation.getResourcePath().contains("dummymodel");
|
||||
}
|
||||
|
||||
public IModel loadModel(ResourceLocation model)
|
||||
{
|
||||
return DummyModel.instance;
|
||||
}
|
||||
|
||||
public static enum DummyModel implements IModel
|
||||
{
|
||||
instance;
|
||||
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Collection<ResourceLocation> getTextures()
|
||||
{
|
||||
return Collections.singletonList(dummyTexture);
|
||||
}
|
||||
|
||||
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> textures)
|
||||
{
|
||||
return new DummyBakedModel(textures.apply(dummyTexture));
|
||||
}
|
||||
|
||||
public IModelState getDefaultState()
|
||||
{
|
||||
return ModelRotation.X0_Y0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DummyBakedModel implements IFlexibleBakedModel
|
||||
{
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
public DummyBakedModel(TextureAtlasSprite texture)
|
||||
{
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
public List<BakedQuad> getFaceQuads(EnumFacing side)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private int[] vertexToInts(float x, float y, float z, int color, float u, float v)
|
||||
{
|
||||
return new int[] {
|
||||
Float.floatToRawIntBits(x),
|
||||
Float.floatToRawIntBits(y),
|
||||
Float.floatToRawIntBits(z),
|
||||
color,
|
||||
Float.floatToRawIntBits(texture.getInterpolatedU(u)),
|
||||
Float.floatToRawIntBits(texture.getInterpolatedV(v)),
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
public List<BakedQuad> getGeneralQuads()
|
||||
{
|
||||
List<BakedQuad> ret = new ArrayList<BakedQuad>();
|
||||
// 1 half-way rotated quad looking UP
|
||||
ret.add(new BakedQuad(Ints.concat(
|
||||
vertexToInts(0, .5f, .5f, -1, 0, 0),
|
||||
vertexToInts(.5f, .5f, 1, -1, 0, 16),
|
||||
vertexToInts(1, .5f, .5f, -1, 16, 16),
|
||||
vertexToInts(.5f, .5f, 0, -1, 16, 0)
|
||||
), -1, EnumFacing.UP));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean isGui3d() { return true; }
|
||||
|
||||
public boolean isAmbientOcclusion() { return true; }
|
||||
|
||||
public boolean isBuiltInRenderer() { return false; }
|
||||
|
||||
public TextureAtlasSprite getTexture() { return this.texture; }
|
||||
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return ItemCameraTransforms.DEFAULT;
|
||||
}
|
||||
|
||||
public VertexFormat getFormat()
|
||||
{
|
||||
return Attributes.DEFAULT_BAKED_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"forge_marker": 1,
|
||||
"defaults": {
|
||||
"textures": {
|
||||
"#texture": "forgedebugmodelloaderregistry:texture",
|
||||
"#chest": "entity/chest/normal"
|
||||
},
|
||||
"model": "forgedebugmodelloaderregistry:chest.b3d"
|
||||
},
|
||||
"variants": {
|
||||
"normal" : { "model" : "forgedebugmodelloaderregistry:untitled2.b3d" }
|
||||
"normal": {
|
||||
"dummy": ""
|
||||
},
|
||||
"inventory": {
|
||||
"dummy": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue