commit 59d2f2cae8af362729c225eb29dbb8e22e6318c7 Author: josua Date: Wed Jun 10 11:21:57 2020 +1000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c3dff2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin/ +.classpath diff --git a/.project b/.project new file mode 100644 index 0000000..7b27ea6 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + GlEngine + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/src/gl_engine/MathHelpers.java b/src/gl_engine/MathHelpers.java new file mode 100755 index 0000000..0074ca1 --- /dev/null +++ b/src/gl_engine/MathHelpers.java @@ -0,0 +1,134 @@ +package gl_engine; + +import gl_engine.vec.Vec2d; +import gl_engine.vec.Vec3d; + +public class MathHelpers +{ + public static final double FallSpeed = 0.00098; + + public static double nextPowerOf(double x, double n) + { + double i = 1; + + while(i < x) { + i *= n; + } + + return i; + } + + public static int nextPowerOf(double x, int n) + { + int i = 1; + + while(i < x) { + i *= n; + } + + return i; + } + + public static double squared(double x) { + return x*x; + } + + public static double pow(int c, double x) + { + double res = 1; + + for(int i=0;i b) return a; + else return b; + } + + public static double smallest(double a, double b) + { + if(a < b) return a; + else return b; + } +} diff --git a/src/gl_engine/ResourceLoader.java b/src/gl_engine/ResourceLoader.java new file mode 100644 index 0000000..c6f75bb --- /dev/null +++ b/src/gl_engine/ResourceLoader.java @@ -0,0 +1,150 @@ +package gl_engine; +import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS; +import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; +import static org.lwjgl.opengl.GL20.GL_LINK_STATUS; +import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; +import static org.lwjgl.opengl.GL20.glAttachShader; +import static org.lwjgl.opengl.GL20.glCompileShader; +import static org.lwjgl.opengl.GL20.glCreateProgram; +import static org.lwjgl.opengl.GL20.glCreateShader; +import static org.lwjgl.opengl.GL20.glDeleteShader; +import static org.lwjgl.opengl.GL20.glGetProgramInfoLog; +import static org.lwjgl.opengl.GL20.glGetProgramiv; +import static org.lwjgl.opengl.GL20.glGetShaderInfoLog; +import static org.lwjgl.opengl.GL20.glGetShaderiv; +import static org.lwjgl.opengl.GL20.glLinkProgram; +import static org.lwjgl.opengl.GL20.glShaderSource; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ResourceLoader +{ + public static byte[] loadResource(String name) + { + try + { + InputStream in = ResourceLoader.class.getResourceAsStream(name); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + if(in == null) { + return new byte[0]; + } + + byte buffer[] = new byte[1024]; + int size = 0; + + while((size = in.read(buffer)) != -1) { + out.write(buffer, 0, size); + } + + in.close(); + + return out.toByteArray(); + } + + catch(IOException e) { + e.printStackTrace(); + return new byte[0]; + } + } + + /*private static int countDp(String str) + { + byte[] str_b = str.getBytes(); + int count = 0; + + for(int i=0;i tree = new ArrayList(); + String data = new String(loadResource(path)); + String[] resources = data.split("\n"); + + for(int i=0;i raw_textures; + public ArrayList tex_refs; + + public TextureAtlas2D() + { + raw_textures = new ArrayList(); + tex_refs = new ArrayList(); + raw_textures.add(TextureRaw.createEmpty()); + + width = 0; + height = 0; + } + + public void add(TextureRaw tex) { + raw_textures.add(tex); + } + + public void clear() { + raw_textures.clear(); + raw_textures.add(TextureRaw.createEmpty()); + } + + private static String getParentPath(String path) + { + int at = 0; + byte[] path_b = path.getBytes(); + + for(int i=0;i= other.y + other.h || other.y >= check.y + check.h) { + return false; + } + + if(check.x >= other.x + other.w || other.x >= check.x + check.w) { + return false; + } + + return true; + } + + private TextureRect refHasCollision(ArrayList refs, TextureRect other) + { + for(TextureRect ref : refs) { + if(refHasCollision(ref, other)) { + return ref; + } + } + + return null; + } + + public void bind() { + glBindTexture(GL_TEXTURE_2D, texture); + } + + public void generate() + { + tex_refs.clear(); + + int size = 1; + + ArrayList tex_rects = new ArrayList(); + TextureRect lastRect = null; + + raw_textures.sort(new Comparator() { + + @Override + public int compare(TextureRaw o1, TextureRaw o2) + { + if(o1.height < o2.height) { + return 1; + } + + if(o1.height > o2.height) { + return -1; + } + + if(o1.width > o2.width) { + return 1; + } + + if(o1.width < o2.width) { + return -1; + } + + return 0; + } + }); + + long millis_now = System.currentTimeMillis(); + long millis_last = millis_now; + + // Work out the positions of each rect + for(int i=0;i 1000) { + millis_last += 1000; + System.out.println("Generating atlas " + i + "/" + raw_textures.size()); + } + + TextureRaw tex = raw_textures.get(i); + + TextureRect rect = new TextureRect(); + rect.r = tex; + rect.w = tex.width; + rect.h = tex.height; + rect.x = 0; + rect.y = 0; + + if(lastRect != null) { + if(lastRect.h <= rect.h && lastRect.w <= rect.w) { + rect.x = lastRect.x; + rect.y = lastRect.y; + } + } + + while(true) + { + TextureRect collision = refHasCollision(tex_rects, rect); + + if(collision == null) { + break; + } + + int change = collision.x + collision.w; + + if(change != rect.x) { + rect.x = change; + } else { + rect.x += 1; + } + + if(rect.x + rect.w > size) { + rect.y += 1; + rect.x = 0; + } + + if(rect.y + rect.h > size) { + size *= 2; + rect.x = 0; + rect.y = 0; + } + } + + TextureRef2D ref = new TextureRef2D(); + ref.texmap = this; + ref.ref = tex.ref; + ref.sx = rect.x; + ref.sy = rect.y; + ref.ex = rect.x + rect.w; + ref.ey = rect.y + rect.h; + + lastRect = rect; + tex_rects.add(rect); + tex_refs.add(ref); + + if(rect.h > height) { + height = rect.h; + } + } + + for(TextureRef2D ref : tex_refs) { + ref.sx /= size; + ref.ex /= size; + ref.sy /= size; + ref.ey /= size; + } + + width = size; + height = size; + + byte[] texmap_b = new byte[width*height*4]; + Range2i texmap_r = new Range2i(width, height); + TextureRect last_rect = null; + + for(int i=0;i 1000) { + millis_last += 1000; + System.out.println("Rendering atlas " + ((int)(i / ((double)width*height) * 1000)) / (double)10 + "%"); + } + + if( + last_rect != null && + pos.x >= last_rect.x && pos.x < last_rect.x + last_rect.w && + pos.y >= last_rect.y && pos.y < last_rect.y + last_rect.h + ) { + found = true; + r = last_rect; + } + + if(!found) + { + //System.out.println("hi"); + + for(TextureRect rect : tex_rects) { + if( + pos.x >= rect.x && pos.x < rect.x + rect.w && + pos.y >= rect.y && pos.y < rect.y + rect.h + ) { + r = rect; + last_rect = rect; + found = true; + break; + } + } + } + + + if(r == null) { + texmap_b[i*4+0] = 0; + texmap_b[i*4+1] = 0; + texmap_b[i*4+2] = 0; + texmap_b[i*4+3] = 0; + continue; + } + + Range2i tex_r = new Range2i(r.w, r.h); + Vec2i tex_p = new Vec2i(pos.x - r.x, pos.y - r.y); + int tex_id = tex_p.getId(tex_r); + + if(tex_p.x == r.w - 1 && tex_p.y == r.h - 1) { + tex_rects.remove(r); + } + + texmap_b[i*4+0] = r.r.bytes[tex_id*4+0]; + texmap_b[i*4+1] = r.r.bytes[tex_id*4+1]; + texmap_b[i*4+2] = r.r.bytes[tex_id*4+2]; + texmap_b[i*4+3] = r.r.bytes[tex_id*4+3]; + + millis_now = System.currentTimeMillis(); + } + + //System.out.println(Arrays.toString(texmap_b)); + System.out.println("Atlas size: "+size+" x "+size); + + ByteBuffer texmap_buff = ByteBuffer.allocateDirect(texmap_b.length); + texmap_buff.put(texmap_b); + texmap_buff.position(0); + + texture = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texmap_buff); + glGenerateMipmap(GL_TEXTURE_2D); + + raw_textures.clear(); + } +} diff --git a/src/gl_engine/texture/TextureAtlas3D.java b/src/gl_engine/texture/TextureAtlas3D.java new file mode 100644 index 0000000..3b697ea --- /dev/null +++ b/src/gl_engine/texture/TextureAtlas3D.java @@ -0,0 +1,375 @@ +package gl_engine.texture; + +import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.GL_RGBA; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL11.glGenTextures; +import static org.lwjgl.opengl.GL11.glTexParameteri; +import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D; +import static org.lwjgl.opengl.GL12.glTexImage3D; +import static org.lwjgl.opengl.GL30.glGenerateMipmap; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Comparator; + +import gl_engine.ResourceLoader; +import gl_engine.range.Range2i; +import gl_engine.range.Range3i; +import gl_engine.vec.Vec2i; +import gl_engine.vec.Vec3i; + +public class TextureAtlas3D +{ + int texture; + public int size, depth; + public ArrayList raw_textures; + public ArrayList tex_refs; + + public TextureAtlas3D() + { + raw_textures = new ArrayList(); + tex_refs = new ArrayList(); + raw_textures.add(TextureRaw.createEmpty()); + + size = 0; + } + + public void add(TextureRaw tex) { + raw_textures.add(tex); + } + + public void clear() { + raw_textures.clear(); + raw_textures.add(TextureRaw.createEmpty()); + } + + private static String getParentPath(String path) + { + int at = 0; + byte[] path_b = path.getBytes(); + + for(int i=0;i= other.y + other.h || other.y >= check.y + check.h) { + return false; + } + + if(check.x >= other.x + other.w || other.x >= check.x + check.w) { + return false; + } + + return true; + } + + private TextureRect refHasCollision(ArrayList refs, TextureRect other) + { + for(TextureRect ref : refs) { + if(refHasCollision(ref, other)) { + return ref; + } + } + + return null; + } + + public void bind() { + glBindTexture(GL_TEXTURE_2D, texture); + } + + public void generate() + { + tex_refs.clear(); + depth = 1; + size = 1; + + ArrayList tex_rects = new ArrayList(); + TextureRect lastRect = null; + + raw_textures.sort(new Comparator() { + + @Override + public int compare(TextureRaw o1, TextureRaw o2) + { + if(o1.height < o2.height) { + return 1; + } + + if(o1.height > o2.height) { + return -1; + } + + if(o1.width > o2.width) { + return 1; + } + + if(o1.width < o2.width) { + return -1; + } + + return 0; + } + }); + + long millis_now = System.currentTimeMillis(); + long millis_last = millis_now; + + // Work out the positions of each rect + for(int i=0;i 1000) { + millis_last += 1000; + System.out.println("Generating atlas " + i + "/" + raw_textures.size()); + } + + TextureRaw tex = raw_textures.get(i); + + TextureRect rect = new TextureRect(); + rect.r = tex; + rect.w = tex.width; + rect.h = tex.height; + rect.x = 0; + rect.y = 0; + rect.z = 0; + + if(lastRect != null) { + if(lastRect.h <= rect.h && lastRect.w <= rect.w) { + rect.x = lastRect.x; + rect.y = lastRect.y; + rect.z = lastRect.z; + } + } + + while(true) + { + TextureRect collision = refHasCollision(tex_rects, rect); + + while(rect.w > size || rect.h > size) { + size *= 2; + } + + if( + collision == null && + rect.x + rect.w <= size && + rect.y + rect.h <= size + ) { + break; + } + + if(collision == null) { + collision = rect; + } + + int change = collision.x + collision.w; + + if(change != rect.x) { + rect.x = change; + } else { + rect.x += 1; + } + + if(rect.x + rect.w > size) { + rect.y += 1; + rect.x = 0; + } + + if(rect.y + rect.h > size) { + rect.z += 1; + rect.x = 0; + rect.y = 0; + } + + if(rect.z > size) { + size *= 2; + rect.x = 0; + rect.y = 0; + rect.z = 0; + } + } + + while(rect.z >= depth) { + depth *= 2; + } + + TextureRef3D ref = new TextureRef3D(); + ref.texmap = this; + ref.ref = tex.ref; + ref.sx = rect.x; + ref.sy = rect.y; + ref.ex = rect.x + rect.w; + ref.ey = rect.y + rect.h; + ref.z = rect.z; + + lastRect = rect; + tex_rects.add(rect); + tex_refs.add(ref); + } + + for(TextureRef3D ref : tex_refs) { + ref.sx /= size; + ref.ex /= size; + ref.sy /= size; + ref.ey /= size; + + ref.z = (ref.z + 0.5f) / depth; + } + + int pixels = size * size * depth; + + if(((long)pixels) * 4 > 2147483647) { + System.err.println("Texture atlas is too big."); + System.err.println("Atlas size: "+size+" x "+size+" x "+depth); + System.exit(1); + } + + byte[] texmap_b = new byte[pixels*4]; + Range3i texmap_r = new Range3i(size, size, depth); + TextureRect last_rect = null; + + for(int i=0;i 1000) { + millis_last += 1000; + System.out.println("Rendering atlas " + ((int)(i / ((double)pixels) * 1000)) / (double)10 + "%"); + } + + if( + last_rect != null && + pos.x >= last_rect.x && pos.x < last_rect.x + last_rect.w && + pos.y >= last_rect.y && pos.y < last_rect.y + last_rect.h && + pos.z == last_rect.z + ) { + found = true; + r = last_rect; + } + + if(!found) + { + //System.out.println("hi"); + + for(TextureRect rect : tex_rects) { + if( + pos.x >= rect.x && pos.x < rect.x + rect.w && + pos.y >= rect.y && pos.y < rect.y + rect.h && + pos.z == rect.z + ) { + r = rect; + last_rect = rect; + found = true; + break; + } + } + } + + + if(r == null) { + texmap_b[i*4+0] = 0; + texmap_b[i*4+1] = 0; + texmap_b[i*4+2] = 0; + texmap_b[i*4+3] = 0; + continue; + } + + Range2i tex_r = new Range2i(r.w, r.h); + Vec2i tex_p = new Vec2i(pos.x - r.x, pos.y - r.y); + int tex_id = tex_p.getId(tex_r); + + if(tex_p.x == r.w - 1 && tex_p.y == r.h - 1) { + tex_rects.remove(r); + } + + texmap_b[i*4+0] = r.r.bytes[tex_id*4+0]; + texmap_b[i*4+1] = r.r.bytes[tex_id*4+1]; + texmap_b[i*4+2] = r.r.bytes[tex_id*4+2]; + texmap_b[i*4+3] = r.r.bytes[tex_id*4+3]; + + millis_now = System.currentTimeMillis(); + } + + //System.out.println(Arrays.toString(texmap_b)); + System.out.println("Atlas size: "+size+" x "+size+" x "+depth); + + ByteBuffer texmap_buff = ByteBuffer.allocateDirect(texmap_b.length); + texmap_buff.put(texmap_b); + texmap_buff.position(0); + + texture = glGenTextures(); + glBindTexture(GL_TEXTURE_3D, texture); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, size, size, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, texmap_buff); + glGenerateMipmap(GL_TEXTURE_3D); + + raw_textures.clear(); + } +} diff --git a/src/gl_engine/texture/TextureRaw.java b/src/gl_engine/texture/TextureRaw.java new file mode 100644 index 0000000..47c47f9 --- /dev/null +++ b/src/gl_engine/texture/TextureRaw.java @@ -0,0 +1,72 @@ +package gl_engine.texture; + +import java.nio.ByteBuffer; + +import org.lwjgl.stb.STBImage; + +import gl_engine.ResourceLoader; + +public class TextureRaw +{ + public byte[] bytes; + public int width, height; + public String ref; + + public TextureRaw(String ref, byte[] bytes, int width, int height) + { + this.ref = ref; + this.bytes = bytes; + this.width = width; + this.height = height; + } + + public static TextureRaw createEmpty() + { + return new TextureRaw("EMPTY", new byte[] { + (byte)255, (byte)0, (byte)255, (byte)255, + (byte)0, (byte)0, (byte)0, (byte)255, + (byte)0, (byte)0, (byte)0, (byte)255, + (byte)255, (byte)0, (byte)255, (byte)255, + }, 2, 2); + } + + public static TextureRaw loadFromFile(String src) + { + int width[] = {0}; + int height[] = {0}; + int channels[] = {0}; + + byte[] png = ResourceLoader.loadResource(src); + + // Send back a "checkerboard" texture if the texture is invalid + if(png.length == 0) { + return null; + } + + STBImage.stbi_set_flip_vertically_on_load(true); + ByteBuffer texture = STBImage.stbi_load_from_memory( + getByteBuffer(png), + width, height, channels, + STBImage.STBI_rgb_alpha); + + if(texture == null) { + return null; + } + + byte[] texture_b = new byte[texture.remaining()]; + texture.get(texture_b); + + return new TextureRaw(src, texture_b, width[0], height[0]); + } + + private static ByteBuffer getByteBuffer(byte[] bytes) + { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); + + for(int i=0;i dy) return dx; + if(dy > dz) return dy; + else return dz; + } + + public Vec3i toInt() { + return new Vec3i(MathHelpers.floor(x), MathHelpers.floor(y), MathHelpers.floor(z)); + } + + @Override + public void BdfClassLoad(BdfObject bdf) { + double data[] = bdf.getDoubleArray(); + if(data.length != 3) return; + x = data[0]; + y = data[1]; + z = data[2]; + } + + @Override + public void BdfClassSave(BdfObject bdf) { + bdf.setDoubleArray(new double[] {x, y, z}); + }; + + public Vec3d(BdfObject bdf) { + BdfClassLoad(bdf); + } +} diff --git a/src/gl_engine/vec/Vec3i.java b/src/gl_engine/vec/Vec3i.java new file mode 100755 index 0000000..1d7f2da --- /dev/null +++ b/src/gl_engine/vec/Vec3i.java @@ -0,0 +1,132 @@ +package gl_engine.vec; + +import bdf.classes.IBdfClassManager; +import bdf.types.BdfObject; +import gl_engine.MathHelpers; +import gl_engine.range.Range3i; + +public class Vec3i implements IBdfClassManager +{ + public int x; + public int y; + public int z; + + public Vec3i(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public double distance(Vec3i other) { + return MathHelpers.distance3d(x, y, z, other.x, other.y, other.z); + } + + public static double distance(Vec3i v1, Vec3i v2) { + return v1.distance(v2); + } + + public int getId(Range3i range) + { + int x = MathHelpers.mod(this.x, range.mx); + int y = MathHelpers.mod(this.y, range.my); + int z = MathHelpers.mod(this.z, range.mz); + + int id = 0; + int m = 1; + + id += x; + m = range.mx; + id += y*m; + m *= range.my; + id += z*m; + + return id; + } + + public static Vec3i fromId(Range3i range, int id) + { + int x = MathHelpers.mod(id, range.mx); + id -= x; + id /= range.mx; + int y = MathHelpers.mod(id, range.my); + id -= y; + id /= range.my; + int z = MathHelpers.mod(id, range.mz); + + return new Vec3i(x, y, z); + } + + public boolean equal(Vec3i other) { + return x == other.x && y == other.y && z == other.z; + } + + public Vec3i add(Vec3i other) { + return new Vec3i(this.x + other.x, this.y + other.y, this.z + other.z); + } + + public Vec3i subtract(Vec3i other) { + return new Vec3i(this.x - other.x, this.y - other.y, this.z - other.z); + } + + public Vec3i multiply(Vec3i other) { + return new Vec3i(this.x * other.x, this.y * other.y, this.z * other.z); + } + + public Vec3i divide(Vec3i other) { + return new Vec3i(this.x / other.x, this.y / other.y, this.z / other.z); + } + + public Vec3i add(int v) { + return new Vec3i(this.x + v, this.y + v, this.z + v); + } + + public Vec3i subtract(int v) { + return new Vec3i(this.x - v, this.y - v, this.z - v); + } + + public Vec3i multiply(int v) { + return new Vec3i(this.x * v, this.y * v, this.z * v); + } + + public Vec3i divide(int v) { + return new Vec3i(this.x / v, this.y / v, this.z / v); + } + + public Vec3i copy() { + return new Vec3i(x, y, z); + } + + public int squareDistance(Vec3i other) + { + int dx = MathHelpers.positive(other.x - x); + int dy = MathHelpers.positive(other.y - y); + int dz = MathHelpers.positive(other.z - z); + + if(dx > dy) return dx; + if(dy > dz) return dy; + else return dz; + } + + public Vec3d toDouble() { + return new Vec3d(x, y, z); + } + + @Override + public void BdfClassLoad(BdfObject bdf) { + int data[] = bdf.getIntegerArray(); + if(data.length != 3) return; + x = data[0]; + y = data[1]; + z = data[2]; + } + + @Override + public void BdfClassSave(BdfObject bdf) { + bdf.setIntegerArray(new int[] {x, y, z}); + }; + + public Vec3i(BdfObject bdf) { + BdfClassLoad(bdf); + } +} diff --git a/src/gl_engine/vec/Vec4d.java b/src/gl_engine/vec/Vec4d.java new file mode 100755 index 0000000..47c61e5 --- /dev/null +++ b/src/gl_engine/vec/Vec4d.java @@ -0,0 +1,122 @@ +package gl_engine.vec; + +import bdf.classes.IBdfClassManager; +import bdf.types.BdfObject; +import gl_engine.MathHelpers; + +public class Vec4d implements IBdfClassManager +{ + public double x; + public double y; + public double z; + public double m; + + public Vec4d(double x, double y, double z, double m) + { + this.x = x; + this.y = y; + this.z = z; + this.m = m; + } + + public double distance(Vec4d other) { + return Math.sqrt( + MathHelpers.squared(this.x - other.x) + + MathHelpers.squared(this.y - other.y) + + MathHelpers.squared(this.z - other.z) + + MathHelpers.squared(this.m - other.m)); + } + + public double dot(Vec4d other) { + return x * other.x + y * other.y + z * other.z + m * other.m; + } + + public double length() { + return Math.sqrt(x*x + y*y + z*z + m*m); + } + + public Vec4d normalize() { + double len = length(); + return divide(len); + } + + public static double distance(Vec4d v1, Vec4d v2) { + return v1.distance(v2); + } + + public boolean equal(Vec4d other) { + return x == other.x && y == other.y && z == other.z && m == other.m; + } + + public Vec4d add(Vec4d other) { + return new Vec4d(this.x + other.x, this.y + other.y, this.z + other.z, this.m + other.m); + } + + public Vec4d subtract(Vec4d other) { + return new Vec4d(this.x - other.x, this.y - other.y, this.z - other.z, this.m - other.m); + } + + public Vec4d multiply(Vec4d other) { + return new Vec4d(this.x * other.x, this.y * other.y, this.z * other.z, this.m * other.m); + } + + public Vec4d divide(Vec4d other) { + return new Vec4d(this.x / other.x, this.y / other.y, this.z / other.z, this.m / other.m); + } + + public Vec4d add(double v) { + return new Vec4d(this.x + v, this.y + v, this.z + v, this.m + v); + } + + public Vec4d subtract(double v) { + return new Vec4d(this.x - v, this.y - v, this.z - v, this.m - v); + } + + public Vec4d multiply(double v) { + return new Vec4d(this.x * v, this.y * v, this.z * v, this.m * v); + } + + public Vec4d divide(double v) { + return new Vec4d(this.x / v, this.y / v, this.z / v, this.m / v); + } + + public Vec4d copy() { + return new Vec4d(x, y, z, m); + } + + public double squareDistance(Vec4d other) + { + double dx = MathHelpers.positive(other.x - x); + double dy = MathHelpers.positive(other.y - y); + double dz = MathHelpers.positive(other.z - z); + double dm = MathHelpers.positive(other.m - m); + + if(dx > dy) return dx; + if(dy > dz) return dy; + if(dz > dm) return dz; + else return dm; + } + + public Vec4i toInt() { + return new Vec4i(MathHelpers.floor(x), MathHelpers.floor(y), MathHelpers.floor(z), MathHelpers.floor(m)); + } + + @Override + public void BdfClassLoad(BdfObject bdf) { + double data[] = bdf.getDoubleArray(); + if(data.length != 4) return; + x = data[0]; + y = data[1]; + z = data[2]; + m = data[3]; + } + + @Override + public void BdfClassSave(BdfObject bdf) { + bdf.setDoubleArray(new double[] {x, y, z, m}); + }; + + public Vec4d(BdfObject bdf) { + BdfClassLoad(bdf); + } +} diff --git a/src/gl_engine/vec/Vec4i.java b/src/gl_engine/vec/Vec4i.java new file mode 100755 index 0000000..84c1bd5 --- /dev/null +++ b/src/gl_engine/vec/Vec4i.java @@ -0,0 +1,147 @@ +package gl_engine.vec; + +import bdf.classes.IBdfClassManager; +import bdf.types.BdfObject; +import gl_engine.MathHelpers; +import gl_engine.range.Range4i; + +public class Vec4i implements IBdfClassManager +{ + public int x; + public int y; + public int z; + public int m; + + public Vec4i(int x, int y, int z, int m) + { + this.x = x; + this.y = y; + this.z = z; + this.m = m; + } + + public double distance(Vec4i other) { + return Math.sqrt( + MathHelpers.squared(this.x - other.x) + + MathHelpers.squared(this.y - other.y) + + MathHelpers.squared(this.z - other.z) + + MathHelpers.squared(this.m - other.m)); + } + + public static double distance(Vec4i v1, Vec4i v2) { + return v1.distance(v2); + } + + public int getId(Range4i range) + { + int x = MathHelpers.mod(this.x, range.mx); + int y = MathHelpers.mod(this.y, range.my); + int z = MathHelpers.mod(this.z, range.mz); + int m = MathHelpers.mod(this.m, range.mm); + + int id = 0; + int mu = 1; + + id += x; + mu = range.mx; + id += y*mu; + mu *= range.my; + id += z*mu; + mu *= range.mz; + id += m*mu; + + return id; + } + + public static Vec4i fromId(Range4i range, int id) + { + int x = MathHelpers.mod(id, range.mx); + id -= x; + id /= range.mx; + int y = MathHelpers.mod(id, range.my); + id -= y; + id /= range.my; + int z = MathHelpers.mod(id, range.mz); + id -= z; + id /= range.mz; + int m = MathHelpers.mod(id, range.mm); + + return new Vec4i(x, y, z, m); + } + + public boolean equal(Vec4i other) { + return x == other.x && y == other.y && z == other.z; + } + + public Vec4i add(Vec4i other) { + return new Vec4i(this.x + other.x, this.y + other.y, this.z + other.z, this.m + other.m); + } + + public Vec4i subtract(Vec4i other) { + return new Vec4i(this.x - other.x, this.y - other.y, this.z - other.z, this.m - other.m); + } + + public Vec4i multiply(Vec4i other) { + return new Vec4i(this.x * other.x, this.y * other.y, this.z * other.z, this.m * other.m); + } + + public Vec4i divide(Vec4i other) { + return new Vec4i(this.x / other.x, this.y / other.y, this.z / other.z, this.m / other.m); + } + + public Vec4i add(int v) { + return new Vec4i(this.x + v, this.y + v, this.z + v, this.m + v); + } + + public Vec4i subtract(int v) { + return new Vec4i(this.x - v, this.y - v, this.z - v, this.m - v); + } + + public Vec4i multiply(int v) { + return new Vec4i(this.x * v, this.y * v, this.z * v, this.m * v); + } + + public Vec4i divide(int v) { + return new Vec4i(this.x / v, this.y / v, this.z / v, this.m / v); + } + + public Vec4i copy() { + return new Vec4i(x, y, z, m); + } + + public int squareDistance(Vec4i other) + { + int dx = MathHelpers.positive(other.x - x); + int dy = MathHelpers.positive(other.y - y); + int dz = MathHelpers.positive(other.z - z); + int dm = MathHelpers.positive(other.m - m); + + if(dx > dy) return dx; + if(dy > dz) return dy; + if(dz > dm) return dz; + else return dm; + } + + public Vec4d toDouble() { + return new Vec4d(x, y, z, m); + } + + @Override + public void BdfClassLoad(BdfObject bdf) { + int data[] = bdf.getIntegerArray(); + if(data.length != 4) return; + x = data[0]; + y = data[1]; + z = data[2]; + m = data[3]; + } + + @Override + public void BdfClassSave(BdfObject bdf) { + bdf.setIntegerArray(new int[] {x, y, z, m}); + }; + + public Vec4i(BdfObject bdf) { + BdfClassLoad(bdf); + } +}