package net.hvidtfeldts.meshia.engine3d; import java.awt.Component; import java.util.HashMap; import java.util.Map; import javax.swing.ProgressMonitor; import net.hvidtfeldts.meshia.math.Vector3; import com.jogamp.opengl.util.glsl.ShaderState; public class SimpleMarchingCubes extends MarchingCubes { private PolygonBuilder builder; private int count; private float delta; public SimpleMarchingCubes() { }; @Override public void initMarchingCubes(double isolevel, int nx, int ny, int nz, Component parentComponent, Vector3 from, Vector3 to) { super.initMarchingCubes(isolevel, nx, ny, nz, parentComponent, from, to); delta = (to.getX() - from.getX()) / ((nx - 1) * 120.0f); } public SunflowRenderable getObject3D(ShaderState shaderState, ProgressMonitor pm) { builder = new PolygonBuilder(shaderState, String.format("MC %S,%S,%S", nx, ny, nz)); polygonise(pm); return builder; } Map<Vector3, Integer> vectorCache = new HashMap<>(); Vector3 color = new Vector3(1, 1, 1); private int reuseVector(Vector3 p1) { Integer integer = vectorCache.get(p1); // integer = null; if (integer != null) { return integer; } int i = builder.addColorVertex(p1, null, color); vectorCache.put(new Vector3(p1), i); return i; } @Override protected void createPolygon(Vector3 p1, Vector3 p2, Vector3 p3) { boolean faceNormals = true; boolean reuse = false; if (faceNormals) { if (reuse) { Vector3 normal = Vector3.getPlaneNormal(p1, p2, p3); normal.normalize(); int i1 = reuseVector(p1); int i2 = reuseVector(p2); int i3 = reuseVector(p3); builder.setNormal(i1, normal); builder.setNormal(i2, normal); builder.setNormal(i3, normal); builder.addTriangle(i1, i2, i3); } else { Vector3 normal = Vector3.getPlaneNormal(p1, p2, p3); normal.normalize(); builder.addColorVertex(p1, normal, color); builder.addColorVertex(p2, normal, color); builder.addColorVertex(p3, normal, color); builder.addTriangle(count++, count++, count++); } } else { builder.addColorVertex(p1, getNormal(p1), color); builder.addColorVertex(p2, getNormal(p2), color); builder.addColorVertex(p3, getNormal(p3), color); } } protected final Vector3 getNormal(Vector3 p) { Vector3 pp = new Vector3(p); pp.setX(p.getX() - delta); double dx = getValue(pp); pp.setX(p.getX() + delta); dx -= getValue(pp); pp.setX(p.getX()); pp.setY(p.getY() - delta); double dy = getValue(pp); pp.setY(p.getY() + delta); dy -= getValue(pp); pp.setY(p.getY()); pp.setZ(p.getZ() - delta); double dz = getValue(pp); pp.setZ(p.getZ() + delta); dz -= getValue(pp); pp.setZ(p.getZ()); pp.setX((float) dx); pp.setY((float) dy); pp.setZ((float) dz); pp.normalize(); pp.multiply(-1.0f); return pp; } @Override protected final Vector3 getPosition(int i, int j, int k) { return Vector3.interpolate(from, to, ((float) i / nx), ((float) j / ny), ((float) k / nz)); } protected double getValuexx(Vector3 p) { return p.getLength() - 0.8; } protected double getValue2xd(Vector3 p) { return p.getLength() - 0.5; } @Override protected double getValue(Vector3 p) { double power = 6; p.multiply(1.15f); double x = p.getX(); double y = p.getY(); double z = p.getZ(); double r = 0; double dr = 1; for (int j = 0; j < 10; j++) { if (x * x + y * y + z * z > 10000) break; double phi = Math.atan2(y, x); r = Math.sqrt(x * x + y * y + z * z); double theta = Math.acos(z / r); dr = Math.pow(r, power - 1.0) * power * dr + 1.0; r = Math.pow(r, power); double sin = Math.sin(power * theta); x = r * sin * Math.cos(power * phi); y = r * sin * Math.sin(power * phi); z = r * Math.cos(power * theta); x += p.getX(); y += p.getY(); z += p.getZ(); // Logger.log("J p" + j + " " + p); } double d = (0.5 * Math.log(r) * r / dr) - 0.0019; double co = 0.1; if (p.getZ() < 0) { co = 0.2; } double rr = -0.2 + co * Math.abs(p.getZ()); if (Math.abs(p.getZ()) < 0.5) { rr += -0.7 * (0.5 - Math.abs(p.getZ())); } double d2 = -Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY()) - rr; return Math.max(d2, d); } protected double getValue2(Vector3 p) { boolean simple = false; if (simple) { double d = p.getLength() - 0.3; Vector3 p2 = new Vector3(p); p2.setX(p2.getX() + 0.3f); double d2 = p2.getLength() - 0.4; p2.setY(p2.getY() + 0.2f); double d3 = p2.getLength() - 0.3; return Math.max(-d3, Math.min(d, d2)); } else { double f = p.getLength() - 0.9; p.multiply(12.0f); double d = Math.cos(p.getX()) * Math.sin(p.getY()) + Math.cos(p.getY()) * Math.sin(p.getZ()) + Math.cos(p.getZ()) * Math.sin(p.getX()); return Math.max(f, Math.abs(d) - 0.2); } } }