Optimized Model loader to no longer require vertex duplication

This commit is contained in:
Speiger 2022-04-24 21:55:05 +02:00
parent ede8b1d1a1
commit c95e7ce20d
10 changed files with 89 additions and 74 deletions

View File

@ -33,8 +33,7 @@ public class Language
public String translate(String key) public String translate(String key)
{ {
String result = translations.get(key); return translations.getOrDefault(key, key);
return result == null ? key : result;
} }
public String translate(String key, Object...args) public String translate(String key, Object...args)

View File

@ -9,7 +9,7 @@ import speiger.src.coreengine.rendering.gui.helper.animations.transitions.ITrans
public class Animation public class Animation
{ {
Object2ObjectMap<AnimationTarget, ITransition> transitions = new Object2ObjectLinkedOpenHashMap<AnimationTarget, ITransition>(); Object2ObjectMap<AnimationTarget, ITransition> transitions = new Object2ObjectLinkedOpenHashMap<>();
AnimationListener listener; AnimationListener listener;
float duration = 0F; float duration = 0F;
@ -28,7 +28,7 @@ public class Animation
public AnimationInstance createInstance(GuiComponent comp, AnimationInstance old, float delay, boolean reverse) public AnimationInstance createInstance(GuiComponent comp, AnimationInstance old, float delay, boolean reverse)
{ {
Object2ObjectMap<AnimationTarget, IValue> values = new Object2ObjectLinkedOpenHashMap<AnimationTarget, IValue>(); Object2ObjectMap<AnimationTarget, IValue> values = new Object2ObjectLinkedOpenHashMap<>();
for(Object2ObjectMap.Entry<AnimationTarget, ITransition> entry : Object2ObjectMaps.fastIterable(transitions)) for(Object2ObjectMap.Entry<AnimationTarget, ITransition> entry : Object2ObjectMaps.fastIterable(transitions))
{ {
AnimationTarget target = entry.getKey(); AnimationTarget target = entry.getKey();

View File

@ -45,14 +45,11 @@ public class Animator
} }
public void update(float particalTicks) public void update(float particalTicks)
{
if(listeners.size() > 0)
{ {
for(int i = 0,m=listeners.size();i<m;i++) for(int i = 0,m=listeners.size();i<m;i++)
{ {
listeners.get(i).accept(owner, this); listeners.get(i).accept(owner, this);
} }
}
if(animations.isEmpty() && !changed) if(animations.isEmpty() && !changed)
{ {
return; return;
@ -84,18 +81,9 @@ public class Animator
private void resetValues() private void resetValues()
{ {
if(!changed) if(!changed) return;
{ if(!owner.hasConstraints()) owner.changeVisibility(1F / visibilityMod).getBox().move(-xMod, -yMod).grow(-widthMod, -heightMod).scale(1F / scaleMod);
return; else owner.changeVisibility(1F / visibilityMod).getBox().scale(1F / scaleMod);
}
if(!owner.hasConstraints())
{
owner.changeVisibility(1F / visibilityMod).getBox().move(-xMod, -yMod).grow(-widthMod, -heightMod).scale(1F / scaleMod);
}
else
{
owner.changeVisibility(1F / visibilityMod).getBox().scale(1F / scaleMod);
}
xMod = 0F; xMod = 0F;
yMod = 0F; yMod = 0F;
widthMod = 0F; widthMod = 0F;

View File

@ -1,10 +1,12 @@
package speiger.src.coreengine.rendering.models; package speiger.src.coreengine.rendering.models;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.gson.JsonElement;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.coreengine.rendering.models.loader.VertexLoader.JsonList;
public enum DataType public enum DataType
{ {
@ -40,32 +42,40 @@ public enum DataType
return this == FLOAT || this == DOUBLE; return this == FLOAT || this == DOUBLE;
} }
public void putIntoBuffer(ByteBuffer buffer, List<Number> data, int offset, int size) public void putIntoBuffer(ByteBuffer buffer, JsonList list, int offset, int stride, int size)
{ {
for(int i = 0;i<size;putIntoBuffer(buffer, data.get(offset+i)),i++); int index = offset;
for(int i = 0,m=list.size();i<m;)
{
putIntoBuffer(buffer, index, list.get(i));
index += byteSize;
if(++i % size == 0) {
index+=stride;
}
}
} }
public void putIntoBuffer(ByteBuffer buffer, Number data) public void putIntoBuffer(ByteBuffer buffer, int index, JsonElement element)
{ {
switch(this) switch(this)
{ {
case BYTE: case BYTE:
buffer.put(data.byteValue()); buffer.put(index, element.getAsByte());
break; break;
case SHORT: case SHORT:
buffer.putShort(data.shortValue()); buffer.putShort(index, element.getAsShort());
break; break;
case INT: case INT:
buffer.putInt(data.intValue()); buffer.putInt(index, element.getAsInt());
break; break;
case LONG: case LONG:
buffer.putLong(data.longValue()); buffer.putLong(index, element.getAsLong());
break; break;
case FLOAT: case FLOAT:
buffer.putFloat(data.floatValue()); buffer.putFloat(index, element.getAsFloat());
break; break;
case DOUBLE: case DOUBLE:
buffer.putDouble(data.doubleValue()); buffer.putDouble(index, element.getAsDouble());
break; break;
} }
} }

View File

@ -47,7 +47,7 @@ public class ModelCache implements IReloadableResource
{ {
if(data.isEmpty()) if(data.isEmpty())
{ {
System.out.println("["+location+"]Found Empty Model Data"); System.out.println("["+location+"] Found Empty Model Data");
return; return;
} }
models.put(location, data); models.put(location, data);

View File

@ -57,7 +57,6 @@ public class BufferAttachment implements IFrameAttachment
@Override @Override
public void init(int type, int width, int height, int samples) public void init(int type, int width, int height, int samples)
{ {
this.type = type; this.type = type;
this.samples = samples; this.samples = samples;
if(id == 0) if(id == 0)

View File

@ -42,6 +42,11 @@ public class VertexEntry
return size; return size;
} }
public int getByteSize()
{
return size * glType.getByteSize();
}
public GLDataType getType() public GLDataType getType()
{ {
return glType; return glType;
@ -59,7 +64,7 @@ public class VertexEntry
{ {
VertexEntry entry = array.get(i); VertexEntry entry = array.get(i);
if(entry.isOptional() && excludeOptional) continue; if(entry.isOptional() && excludeOptional) continue;
result += entry.getSize() * entry.getType().getByteSize(); result += entry.getByteSize();
} }
return result; return result;
} }

View File

@ -4,6 +4,8 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.List; import java.util.List;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
@ -21,35 +23,21 @@ public class VertexLoader
public static ByteBuffer parseVertexData(JsonObject obj, int vertexCount, List<VertexEntry> entries, boolean excludeOptional) public static ByteBuffer parseVertexData(JsonObject obj, int vertexCount, List<VertexEntry> entries, boolean excludeOptional)
{ {
List<Number> numbers = parseVertexData(obj, entries, excludeOptional); int byteStride = VertexEntry.caculateByteSize(entries, excludeOptional);
ByteBuffer buffer = ByteBuffer.allocate(vertexCount * VertexEntry.caculateByteSize(entries, excludeOptional)).order(ByteOrder.nativeOrder()); JsonArray vertexes = obj.getAsJsonArray("vertexes");
for(int i = 0,offset=0,m=vertexCount*entries.size();i<m;i++) ByteBuffer buffer = ByteBuffer.allocate(vertexCount * byteStride).order(ByteOrder.nativeOrder());
{
VertexEntry entry = entries.get(i % entries.size());
if(entry.isOptional() && excludeOptional) continue;
entry.getType().getDataType().putIntoBuffer(buffer, numbers, offset, entry.getSize());
offset+=entry.getSize();
}
return buffer;
}
public static List<Number> parseVertexData(JsonObject obj, List<VertexEntry> entries, boolean excludeOptional)
{
int stride = VertexEntry.caclulateStride(entries); int stride = VertexEntry.caclulateStride(entries);
int outStride = excludeOptional ? VertexEntry.calculateNonOptionalStride(entries) : stride; for(int i = 0,offset = 0, byteOffset = 0,m=entries.size();i<m;i++)
int[] vertexes = JsonUtil.parseIntArray(obj.getAsJsonArray("vertexes"));
Number[] data = new Number[excludeOptional ? (vertexes.length / stride) * outStride : vertexes.length];
for(int i = 0,inOff=0,outOff=0,m=entries.size();i<m;i++)
{ {
VertexEntry entry = entries.get(i); VertexEntry entry = entries.get(i);
if(!entry.isOptional() || !excludeOptional) if(!entry.isOptional() || !excludeOptional)
{ {
deserializeIndecies(vertexes, JsonUtil.parseArray(obj.getAsJsonArray(entry.getName())), entry.getSize(), stride, inOff, data, outStride, outOff); entry.getType().getDataType().putIntoBuffer(buffer, new JsonWrapper(vertexes, obj.getAsJsonArray(entry.getName()), offset, stride, entry.getSize(), vertexCount), byteOffset, byteStride, entry.getSize());
outOff += entry.getSize(); byteOffset += entry.getByteSize();
} }
inOff += entry.getSize(); offset += entry.getSize();
} }
return ObjectArrayList.wrap(data); return buffer;
} }
public static Object2ObjectMap<String, List<Number>> parseMappedVertexData(JsonObject obj, List<VertexEntry> entries, boolean excludeOptional) public static Object2ObjectMap<String, List<Number>> parseMappedVertexData(JsonObject obj, List<VertexEntry> entries, boolean excludeOptional)
@ -66,14 +54,6 @@ public class VertexLoader
return mappedData; return mappedData;
} }
public static <T> void deserializeIndecies(int[] indecies, T[] in, int size, int stride, int offset, T[] out, int outStride, int outOffset)
{
for(int i = 0,m=(indecies.length/stride)*size;i<m;i++)
{
out[outOffset + ((i/size) * outStride) + (i % size)] = in[indecies[offset + ((i/size) * stride) + (i % size)]];
}
}
public static <T> List<T> deserializeIndecies(int[] indecies, T[] in, int size, int stride, int offset) public static <T> List<T> deserializeIndecies(int[] indecies, T[] in, int size, int stride, int offset)
{ {
List<T> out = new ObjectArrayList<>(); List<T> out = new ObjectArrayList<>();
@ -83,4 +63,43 @@ public class VertexLoader
} }
return out; return out;
} }
public static interface JsonList
{
public JsonElement get(int index);
public int size();
}
private static class JsonWrapper implements JsonList
{
JsonArray array;
JsonArray vertexes;
int offset;
int size;
int stride;
int max;
public JsonWrapper(JsonArray vertexes, JsonArray array, int offset, int stride, int size, int max)
{
this.array = array;
this.vertexes = vertexes;
this.offset = offset;
this.size = size;
this.stride = stride;
this.max = max;
}
@Override
public int size()
{
return max;
}
@Override
public JsonElement get(int index)
{
return array.get(vertexes.get(offset + ((index/size) * stride) + (index % size)).getAsInt());
}
}
} }

View File

@ -13,7 +13,7 @@ import speiger.src.coreengine.assets.reloader.IReloadableResource;
public class ShaderTracker implements IReloadableResource public class ShaderTracker implements IReloadableResource
{ {
public static final ShaderTracker INSTANCE = new ShaderTracker(); public static final ShaderTracker INSTANCE = new ShaderTracker();
List<ReloadReference<?>> programs = new ObjectArrayList<ReloadReference<?>>(); List<ReloadReference<?>> programs = new ObjectArrayList<>();
int activeShader = 0; int activeShader = 0;
boolean reloading = false; boolean reloading = false;
AssetManager assets; AssetManager assets;
@ -27,8 +27,7 @@ public class ShaderTracker implements IReloadableResource
{ {
T result = creator.get(); T result = creator.get();
result.init(); result.init();
ReloadReference<T> reference = new ReloadReference<>(result, creator, reloader); programs.add(new ReloadReference<>(result, creator, reloader));
programs.add(reference);
return result; return result;
} }

View File

@ -19,7 +19,7 @@ public class Listeners
{ {
for(int i = 0;i<unsortedListeners.length;i++) for(int i = 0;i<unsortedListeners.length;i++)
{ {
unsortedListeners[i] = new ObjectLinkedOpenHashSet<Consumer<Event>>(); unsortedListeners[i] = new ObjectLinkedOpenHashSet<>();
} }
} }
@ -46,19 +46,14 @@ public class Listeners
public void removeListeners(Consumer<Event> listener) public void removeListeners(Consumer<Event> listener)
{ {
boolean found = false;
for(int i = 0,m=unsortedListeners.length;i<m;i++) for(int i = 0,m=unsortedListeners.length;i<m;i++)
{ {
if(unsortedListeners[i].remove(listener)) if(unsortedListeners[i].remove(listener))
{
found = true;
}
}
if(found)
{ {
markDirty(); markDirty();
} }
} }
}
public void getListeners(EventPriority entry, List<Consumer<Event>> events) public void getListeners(EventPriority entry, List<Consumer<Event>> events)
{ {
@ -77,6 +72,7 @@ public class Listeners
private void markDirty() private void markDirty()
{ {
if(rebuild) return;
rebuild = true; rebuild = true;
if(childs != null) if(childs != null)
{ {