Initial commit

This commit is contained in:
josua 2020-06-10 11:21:57 +10:00
commit 59d2f2cae8
23 changed files with 2154 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
bin/
.classpath

17
.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>GlEngine</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -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

134
src/gl_engine/MathHelpers.java Executable file
View File

@ -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<c;i++) {
res *= x;
}
return res;
}
public static double distance3d(double x1, double y1, double z1, double x2, double y2, double z2) {
return Math.sqrt( squared(x2 - x1) + squared(y2 - y1) + squared(z2 - z1) );
}
public static double distance2d(double x1, double y1, double x2, double y2) {
return Math.sqrt( squared(x2 - x1) + squared(y2 - y1) );
}
public static double map(double x, double in_min, double in_max, double out_min, double out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
public static Vec2d moveTowards2(double amount, double angle) {
return new Vec2d(Math.sin(angle) * amount, Math.cos(angle) * amount);
}
public static Vec3d moveTowards3(double amount, Vec2d angles)
{
// Create some varibles
Vec3d points = new Vec3d(0, 0, 0);
double m;
points.z = Math.sin(angles.y) * amount;
m = Math.cos(angles.y);
points.x = Math.sin(angles.x) * m * amount;
m = Math.cos(angles.x) * m;
points.y = m * amount;
return points;
}
public static double mod(double a, double b) {
return (((a % b) + b) % b);
}
public static int mod(int a, int b) {
return (((a % b) + b) % b);
}
public static int floor(double a)
{
if((int)a == a) {
return (int) a;
}
else if(a < 0) {
return (int)(a - 1);
}
else {
return (int)a;
}
}
public static double positive(double a) {
if(a < 0) return -a;
else return a;
}
public static int positive(int a) {
if(a < 0) return -a;
else return a;
}
public static Vec2d rotate2(Vec2d pos, double angle)
{
// Calculate 2 sin and cos values
double s = Math.sin(angle);
double c = Math.cos(angle);
// Return and calculate the new positions
return new Vec2d(
pos.x * c - pos.y * s,
pos.x * s + pos.y * c);
}
public static double biggest(double a, double b)
{
if(a > b) return a;
else return b;
}
public static double smallest(double a, double b)
{
if(a < b) return a;
else return b;
}
}

View File

@ -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<str.length();i++) {
if(str_b[i] == '.') {
count += 1;
}
}
return count;
}
public static String[] resourceTree(String path)
{
ArrayList<String> tree = new ArrayList<String>();
String data = new String(loadResource(path));
String[] resources = data.split("\n");
for(int i=0;i<resources.length;i++)
{
String resource = path + "/" + resources[i];
String resource_s[] = resource.split("/");
if(countDp(resource_s[resource_s.length - 1]) == 0)
{
if(resource.endsWith("/")) {
continue;
}
for(String r : resourceTree(resource)) {
tree.add(r);
}
} else {
tree.add(resource);
}
}
String[] tree_array = new String[tree.size()];
for(int i=0;i<tree.size();i++) {
tree_array[i] = tree.get(i);
}
return tree_array;
}*/
public static int loadShader(String name)
{
int vsh = glCreateShader(GL_VERTEX_SHADER);
int fsh = glCreateShader(GL_FRAGMENT_SHADER);
byte[] vsh_source = loadResource(name + ".vsh");
byte[] fsh_source = loadResource(name + ".fsh");
StringBuilder vsh_sb = new StringBuilder(new String(vsh_source));
StringBuilder fsh_sb = new StringBuilder(new String(fsh_source));
glShaderSource(vsh, vsh_sb);
glShaderSource(fsh, fsh_sb);
glCompileShader(vsh);
glCompileShader(fsh);
int vsh_success[] = new int[1];
int fsh_success[] = new int[1];
glGetShaderiv(vsh, GL_COMPILE_STATUS, vsh_success);
glGetShaderiv(fsh, GL_COMPILE_STATUS, fsh_success);
if(vsh_success[0] == 0) {
System.err.println("ERROR:SHADER:VERTEX:" + name + ":" + glGetShaderInfoLog(vsh));
System.exit(1);
}
if(fsh_success[0] == 0) {
System.err.println("ERROR:SHADER:FRAGMENT:" + name + ":" + glGetShaderInfoLog(fsh));
System.exit(1);
}
int program = glCreateProgram();
glAttachShader(program, vsh);
glAttachShader(program, fsh);
glLinkProgram(program);
int success[] = {0};
glGetProgramiv(program, GL_LINK_STATUS, success);
if(success[0] == 0) {
System.err.println("ERROR:PROGRAM:LINKING:" + name + ":" + glGetProgramInfoLog(program));
System.exit(1);
}
glDeleteShader(vsh);
glDeleteShader(fsh);
return program;
}
}

View File

@ -0,0 +1,51 @@
package gl_engine.graphics;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_FORWARD_COMPAT;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glViewport;
import org.lwjgl.opengl.GL;
public class GraphicsHelpers
{
public static long initWindow(String title, int width, int height, long monitor)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
long window = glfwCreateWindow(width, height, title, monitor, 0);
if(window == 0) {
glfwTerminate();
throw new RuntimeException("GLFW window initialization failed");
}
glfwMakeContextCurrent(window);
glfwShowWindow(window);
GL.createCapabilities();
glViewport(0, 0, width, height);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
return window;
}
}

View File

@ -0,0 +1,18 @@
package gl_engine.graphics;
import org.lwjgl.opengl.GL33;
import gl_engine.ResourceLoader;
public class GraphicsShader
{
public int program;
public void use() {
GL33.glUseProgram(program);
}
public GraphicsShader(String name) {
program = ResourceLoader.loadShader(name);
}
}

View File

@ -0,0 +1,168 @@
package gl_engine.matrix;
import bdf.classes.IBdfClassManager;
import bdf.types.BdfObject;
import gl_engine.vec.Vec3d;
public class Matrix4 implements IBdfClassManager
{
public static final int SIZE = 4;
private float[] elements;
public Matrix4() {
elements = new float[SIZE * SIZE];
}
public float[] getArray() {
return elements;
}
public static Matrix4 identity()
{
Matrix4 mat = new Matrix4();
for(int i=0;i<SIZE;i++) {
for(int j=0;j<SIZE;j++) {
mat.set(i, j, i == j ? 1 : 0);
}
}
return mat;
}
public static Matrix4 translate(Vec3d vec) {
return translate(vec.x, vec.y, vec.z);
}
public static Matrix4 translate(double x, double y, double z)
{
Matrix4 result = identity();
result.set(3, 0, x);
result.set(3, 1, y);
result.set(3, 2, z);
return result;
}
public static Matrix4 rotate(double angle, double x, double y, double z)
{
Matrix4 result = identity();
double angle_rad = Math.toRadians(angle);
double sin = Math.sin(angle_rad);
double cos = Math.cos(angle_rad);
double icos = 1 - cos;
result.set(0, 0, cos + x * x * icos);
result.set(0, 1, x * y * icos - z * sin);
result.set(0, 2, x * z * icos + y * sin);
result.set(1, 0, y * x * icos + z * sin);
result.set(1, 1, cos + y * y * icos);
result.set(1, 2, y * z * icos - x * sin);
result.set(2, 0, z * x * icos - y * sin);
result.set(2, 1, z * y * icos + x * sin);
result.set(2, 2, cos + z * z * icos);
return result;
}
public static Matrix4 rotate(double angle, Vec3d axis) {
return rotate(angle, axis.x, axis.y, axis.z);
}
public static Matrix4 scale(Vec3d vec)
{
Matrix4 result = identity();
result.set(0, 0, vec.x);
result.set(1, 1, vec.y);
result.set(2, 2, vec.z);
return result;
}
public static Matrix4 multiply(Matrix4 mat1, Matrix4 mat2)
{
Matrix4 result = new Matrix4();
for(int i=0;i<SIZE;i++) {
for(int j=0;j<SIZE;j++) {
result.set(i, j, mat1.get(i, 0) * mat2.get(0, j) +
mat1.get(i, 1) * mat2.get(1, j) +
mat1.get(i, 2) * mat2.get(2, j) +
mat1.get(i, 3) * mat2.get(3, j));
}
}
return result;
}
public static Matrix4 transform(Vec3d position, Vec3d rotation, Vec3d scale)
{
Matrix4 scaleMatrix = scale(scale);
Matrix4 translationMatrix = translate(position);
Matrix4 rotationXMatrix = rotate(rotation.x, 1, 0, 0);
Matrix4 rotationYMatrix = rotate(rotation.y, 0, 1, 0);
Matrix4 rotationZMatrix = rotate(rotation.z, 0, 0, 1);
Matrix4 rotationMatrix = multiply(rotationXMatrix, multiply(rotationYMatrix, rotationZMatrix));
Matrix4 result = multiply(translationMatrix, multiply(rotationMatrix, scaleMatrix));
return result;
}
public static Matrix4 projection(double aspect, double fov, double near, double far)
{
double tan = Math.tan(Math.toRadians(fov / 2.0));
double diff = far - near;
Matrix4 result = identity();
result.set(0, 0, 1 / (aspect * tan));
result.set(1, 1, 1 / tan);
result.set(2, 2, -(far + near) / diff);
result.set(3, 2, -(2 * far * near) / diff);
result.set(2, 3, -1);
result.set(3, 3, 0);
return result;
}
public void set(int x, int y, double v) {
set(x, y, (float)v);
}
public void set(int x, int y, float v)
{
int id = x * 4 + y;
elements[id] = v;
}
public double get(int x, int y)
{
int id = x * 4 + y;
return elements[id];
}
@Override
public void BdfClassLoad(BdfObject bdf)
{
elements = bdf.getFloatArray();
if(elements.length != 16) {
elements = identity().elements;
}
}
@Override
public void BdfClassSave(BdfObject bdf) {
bdf.setFloatArray(elements);
}
public Matrix4(BdfObject bdf) {
BdfClassLoad(bdf);
}
}

View File

@ -0,0 +1,17 @@
package gl_engine.range;
public class Range2i
{
public int mx;
public int my;
public Range2i(int mx, int my)
{
this.mx = mx;
this.my = my;
}
public int maxValue() {
return mx * my;
}
}

View File

@ -0,0 +1,19 @@
package gl_engine.range;
public class Range3i
{
public int mx;
public int my;
public int mz;
public Range3i(int mx, int my, int mz)
{
this.mx = mx;
this.my = my;
this.mz = mz;
}
public int maxValue() {
return mx * my * mz;
}
}

View File

@ -0,0 +1,21 @@
package gl_engine.range;
public class Range4i
{
public int mx;
public int my;
public int mz;
public int mm;
public Range4i(int mx, int my, int mz, int mm)
{
this.mx = mx;
this.my = my;
this.mz = mz;
this.mm = mm;
}
public int maxValue() {
return mx * my * mz * mm;
}
}

View File

@ -0,0 +1,338 @@
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.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;
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.vec.Vec2i;
public class TextureAtlas2D
{
int texture;
public int width, height;
public ArrayList<TextureRaw> raw_textures;
public ArrayList<TextureRef2D> tex_refs;
public TextureAtlas2D()
{
raw_textures = new ArrayList<TextureRaw>();
tex_refs = new ArrayList<TextureRef2D>();
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<path_b.length;i++) {
if(path_b[i] == '/') {
at = i;
}
}
return path.substring(0, at + 1);
}
public static TextureAtlas2D loadAll(String path)
{
String path_parent = getParentPath(path);
String[] tree = new String(ResourceLoader.loadResource(path)).split("\n");
TextureAtlas2D texmap = new TextureAtlas2D();
for(String dir : tree) {
if(dir.endsWith(".png"))
{
while(dir.startsWith("./")) {
dir = dir.substring(2, dir.length());
}
TextureRaw tex = TextureRaw.loadFromFile(path_parent + dir);
if(tex == null) {
continue;
}
tex.ref = "/" + dir;
texmap.add(tex);
}
}
return texmap;
}
public TextureRef2D get(String ref)
{
for(TextureRef2D tex_ref : tex_refs) {
if(tex_ref.ref.contentEquals(ref)) {
return tex_ref;
}
}
for(TextureRef2D tex_ref : tex_refs) {
if(tex_ref.ref.contentEquals("EMPTY")) {
return get("EMPTY");
}
}
System.err.println("Error: atlas not generated");
System.exit(0);
return null;
}
private boolean refHasCollision(TextureRect check, TextureRect other)
{
if(check.y >= 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<TextureRect> 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<TextureRect> tex_rects = new ArrayList<TextureRect>();
TextureRect lastRect = null;
raw_textures.sort(new Comparator<TextureRaw>() {
@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<raw_textures.size();i++)
{
millis_now = System.currentTimeMillis();
if(millis_now - millis_last > 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<width*height;i++)
{
Vec2i pos = Vec2i.fromId(texmap_r, i);
TextureRect r = null;
boolean found = false;
if(millis_now - millis_last > 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();
}
}

View File

@ -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<TextureRaw> raw_textures;
public ArrayList<TextureRef3D> tex_refs;
public TextureAtlas3D()
{
raw_textures = new ArrayList<TextureRaw>();
tex_refs = new ArrayList<TextureRef3D>();
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<path_b.length;i++) {
if(path_b[i] == '/') {
at = i;
}
}
return path.substring(0, at + 1);
}
public static TextureAtlas3D loadAll(String path)
{
String path_parent = getParentPath(path);
String[] tree = new String(ResourceLoader.loadResource(path)).split("\n");
TextureAtlas3D texmap = new TextureAtlas3D();
for(String dir : tree) {
if(dir.endsWith(".png"))
{
while(dir.startsWith("./")) {
dir = dir.substring(2, dir.length());
}
TextureRaw tex = TextureRaw.loadFromFile(path_parent + dir);
if(tex == null) {
continue;
}
tex.ref = "/" + dir;
texmap.add(tex);
}
}
return texmap;
}
public TextureRef3D get(String ref)
{
for(TextureRef3D tex_ref : tex_refs) {
if(tex_ref.ref.contentEquals(ref)) {
return tex_ref;
}
}
for(TextureRef3D tex_ref : tex_refs) {
if(tex_ref.ref.contentEquals("EMPTY")) {
return get("EMPTY");
}
}
System.err.println("Error: atlas not generated");
System.exit(0);
return null;
}
private boolean refHasCollision(TextureRect check, TextureRect other)
{
if(check.z != other.z) {
return false;
}
if(check.y >= 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<TextureRect> 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<TextureRect> tex_rects = new ArrayList<TextureRect>();
TextureRect lastRect = null;
raw_textures.sort(new Comparator<TextureRaw>() {
@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<raw_textures.size();i++)
{
millis_now = System.currentTimeMillis();
if(millis_now - millis_last > 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<pixels;i++)
{
Vec3i pos = Vec3i.fromId(texmap_r, i);
TextureRect r = null;
boolean found = false;
if(millis_now - millis_last > 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();
}
}

View File

@ -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<bytes.length;i++) {
buffer.put(i, bytes[i]);
}
return buffer;
}
}

View File

@ -0,0 +1,6 @@
package gl_engine.texture;
class TextureRect {
int x, y, w, h, z;
TextureRaw r;
}

View File

@ -0,0 +1,8 @@
package gl_engine.texture;
public class TextureRef2D
{
public String ref;
public TextureAtlas2D texmap;
public float sx, sy, ex, ey;
}

View File

@ -0,0 +1,8 @@
package gl_engine.texture;
public class TextureRef3D
{
public String ref;
public TextureAtlas3D texmap;
public float sx, sy, ex, ey, z;
}

106
src/gl_engine/vec/Vec2d.java Executable file
View File

@ -0,0 +1,106 @@
package gl_engine.vec;
import bdf.classes.IBdfClassManager;
import bdf.types.BdfObject;
import gl_engine.MathHelpers;
public class Vec2d implements IBdfClassManager
{
public double x;
public double y;
public Vec2d(double x, double y)
{
this.x = x;
this.y = y;
}
public double distance(Vec2d other) {
return MathHelpers.distance2d(x, y, other.x, other.y);
}
public static double distance(Vec2d v1, Vec2d v2) {
return v1.distance(v2);
}
public double dot(Vec2d other) {
return x * other.x + y * other.y;
}
public double length() {
return Math.sqrt(x*x + y*y);
}
public Vec2d normalize() {
double len = length();
return divide(len);
}
public boolean equal(Vec2d other) {
return x == other.x && y == other.y;
}
public Vec2d add(Vec2d other) {
return new Vec2d(this.x + other.x, this.y + other.y);
}
public Vec2d subtract(Vec2d other) {
return new Vec2d(this.x - other.x, this.y - other.y);
}
public Vec2d multiply(Vec2d other) {
return new Vec2d(this.x * other.x, this.y * other.y);
}
public Vec2d divide(Vec2d other) {
return new Vec2d(this.x / other.x, this.y / other.y);
}
public Vec2d add(double v) {
return new Vec2d(this.x + v, this.y + v);
}
public Vec2d subtract(double v) {
return new Vec2d(this.x - v, this.y - v);
}
public Vec2d multiply(double v) {
return new Vec2d(this.x * v, this.y * v);
}
public Vec2d divide(double v) {
return new Vec2d(this.x / v, this.y / v);
}
public Vec2d copy() {
return new Vec2d(x, y);
}
public double squareDistance(Vec2d other)
{
double dx = MathHelpers.positive(other.x - x);
double dy = MathHelpers.positive(other.y - y);
return MathHelpers.biggest(dx, dy);
}
public Vec2i toInt() {
return new Vec2i(MathHelpers.floor(x), MathHelpers.floor(y));
}
@Override
public void BdfClassLoad(BdfObject bdf) {
double data[] = bdf.getDoubleArray();
if(data.length != 2) return;
x = data[0];
y = data[1];
}
@Override
public void BdfClassSave(BdfObject bdf) {
bdf.setDoubleArray(new double[] {x, y});
};
public Vec2d(BdfObject bdf) {
BdfClassLoad(bdf);
}
}

119
src/gl_engine/vec/Vec2i.java Executable file
View File

@ -0,0 +1,119 @@
package gl_engine.vec;
import bdf.classes.IBdfClassManager;
import bdf.types.BdfObject;
import gl_engine.MathHelpers;
import gl_engine.range.Range2i;
public class Vec2i implements IBdfClassManager
{
public int x;
public int y;
public Vec2i(int x, int y)
{
this.x = x;
this.y = y;
}
public double distance(Vec2i other) {
return MathHelpers.distance2d(x, y, other.x, other.y);
}
public static double distance(Vec2i v1, Vec2i v2) {
return v1.distance(v2);
}
public int getId(Range2i range)
{
int x = MathHelpers.mod(this.x, range.mx);
int y = MathHelpers.mod(this.y, range.my);
int id = 0;
int m = 1;
id += x;
m = range.mx;
id += y*m;
return id;
}
public static Vec2i fromId(Range2i range, int id)
{
int x = MathHelpers.mod(id, range.mx);
id -= x;
id /= range.mx;
int y = MathHelpers.mod(id, range.my);
return new Vec2i(x, y);
}
public boolean equal(Vec2i other) {
return x == other.x && y == other.y;
}
public Vec2i add(Vec2i other) {
return new Vec2i(this.x + other.x, this.y + other.y);
}
public Vec2i subtract(Vec2i other) {
return new Vec2i(this.x - other.x, this.y - other.y);
}
public Vec2i multiply(Vec2i other) {
return new Vec2i(this.x * other.x, this.y * other.y);
}
public Vec2i divide(Vec2i other) {
return new Vec2i(this.x / other.x, this.y / other.y);
}
public Vec2i add(int v) {
return new Vec2i(this.x + v, this.y + v);
}
public Vec2i subtract(int v) {
return new Vec2i(this.x - v, this.y - v);
}
public Vec2i multiply(int v) {
return new Vec2i(this.x * v, this.y * v);
}
public Vec2i divide(int v) {
return new Vec2i(this.x / v, this.y / v);
}
public Vec2i copy() {
return new Vec2i(x, y);
}
public double squareDistance(Vec2i other)
{
int dx = MathHelpers.positive(other.x - x);
int dy = MathHelpers.positive(other.y - y);
return MathHelpers.biggest(dx, dy);
}
public Vec2d toDouble() {
return new Vec2d(x, y);
}
@Override
public void BdfClassLoad(BdfObject bdf) {
int data[] = bdf.getIntegerArray();
if(data.length != 2) return;
x = data[0];
y = data[1];
}
@Override
public void BdfClassSave(BdfObject bdf) {
bdf.setIntegerArray(new int[] {x, y});
};
public Vec2i(BdfObject bdf) {
BdfClassLoad(bdf);
}
}

113
src/gl_engine/vec/Vec3d.java Executable file
View File

@ -0,0 +1,113 @@
package gl_engine.vec;
import bdf.classes.IBdfClassManager;
import bdf.types.BdfObject;
import gl_engine.MathHelpers;
public class Vec3d implements IBdfClassManager
{
public double x;
public double y;
public double z;
public Vec3d(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public double distance(Vec3d other) {
return MathHelpers.distance3d(x, y, z, other.x, other.y, other.z);
}
public double dot(Vec3d other) {
return x * other.x + y * other.y + z * other.z;
}
public double length() {
return Math.sqrt(x*x + y*y + z*z);
}
public Vec3d normalize() {
double len = length();
return divide(len);
}
public static double distance(Vec3d v1, Vec3d v2) {
return v1.distance(v2);
}
public boolean equal(Vec3d other) {
return x == other.x && y == other.y && z == other.z;
}
public Vec3d add(Vec3d other) {
return new Vec3d(this.x + other.x, this.y + other.y, this.z + other.z);
}
public Vec3d subtract(Vec3d other) {
return new Vec3d(this.x - other.x, this.y - other.y, this.z - other.z);
}
public Vec3d multiply(Vec3d other) {
return new Vec3d(this.x * other.x, this.y * other.y, this.z * other.z);
}
public Vec3d divide(Vec3d other) {
return new Vec3d(this.x / other.x, this.y / other.y, this.z / other.z);
}
public Vec3d add(double v) {
return new Vec3d(this.x + v, this.y + v, this.z + v);
}
public Vec3d subtract(double v) {
return new Vec3d(this.x - v, this.y - v, this.z - v);
}
public Vec3d multiply(double v) {
return new Vec3d(this.x * v, this.y * v, this.z * v);
}
public Vec3d divide(double v) {
return new Vec3d(this.x / v, this.y / v, this.z / v);
}
public Vec3d copy() {
return new Vec3d(x, y, z);
}
public double squareDistance(Vec3d other)
{
double dx = MathHelpers.positive(other.x - x);
double dy = MathHelpers.positive(other.y - y);
double dz = MathHelpers.positive(other.z - z);
if(dx > 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);
}
}

132
src/gl_engine/vec/Vec3i.java Executable file
View File

@ -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);
}
}

122
src/gl_engine/vec/Vec4d.java Executable file
View File

@ -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);
}
}

147
src/gl_engine/vec/Vec4i.java Executable file
View File

@ -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);
}
}