├── .gitignore ├── Java3DMeshVsSphereCollisionTest ├── build.xml ├── manifest.mf ├── nbproject │ ├── build-impl.xml │ ├── genfiles.properties │ ├── private │ │ ├── private.properties │ │ └── private.xml │ ├── project.properties │ └── project.xml └── src │ ├── res │ ├── terrain.mtl │ └── terrain.obj │ └── test │ ├── Camera.java │ ├── Edge.java │ ├── Face.java │ ├── Input.java │ ├── MeshLoader.java │ ├── Player.java │ ├── Response.java │ ├── Sphere.java │ ├── Vec3.java │ ├── View.java │ └── World.java ├── Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1 ├── build.xml ├── manifest.mf ├── nbproject │ ├── build-impl.xml │ ├── genfiles.properties │ ├── private │ │ ├── private.properties │ │ └── private.xml │ ├── project.properties │ └── project.xml └── src │ ├── octree │ ├── MeshLoader.java │ ├── Player.java │ ├── View.java │ └── View2.java │ ├── partition │ ├── Box.java │ ├── Node.java │ └── Octree.java │ ├── physics │ ├── Camera.java │ ├── Edge.java │ ├── Face.java │ ├── Input.java │ ├── Response.java │ ├── Sphere.java │ └── Vec3.java │ └── res │ ├── terrain.mtl │ ├── terrain.obj │ └── test ├── Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2 ├── build.xml ├── manifest.mf ├── nbproject │ ├── build-impl.xml │ ├── genfiles.properties │ ├── private │ │ ├── private.properties │ │ └── private.xml │ ├── project.properties │ └── project.xml └── src │ ├── res │ ├── cs.mtl │ ├── cs.obj │ ├── princess_peaches_castle_(outside).mtl │ ├── princess_peaches_castle_(outside).obj │ ├── terrain.mtl │ ├── terrain.obj │ └── test │ └── test │ ├── Camera.java │ ├── Edge.java │ ├── Face.java │ ├── Input.java │ ├── MeshLoader.java │ ├── Player.java │ ├── Response.java │ ├── Sphere.java │ ├── Vec3.java │ ├── View.java │ ├── World.java │ └── partition │ ├── Box.java │ ├── FaceBox.java │ ├── Node.java │ └── Octree.java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/dist/ 2 | /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/build/ 3 | /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/build/ 4 | /Java3DMeshVsSphereCollisionTest/build/ 5 | /Java3DMeshVsSphereCollisionTest/dist/ 6 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project Java3DMeshVsSphereCollisionTest. 12 | 13 | 73 | 74 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=8ab8b0e3 2 | build.xml.script.CRC32=a3fa3bb1 3 | build.xml.stylesheet.CRC32=f85dc8f2@1.99.0.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=8ab8b0e3 7 | nbproject/build-impl.xml.script.CRC32=9d421c82 8 | nbproject/build-impl.xml.stylesheet.CRC32=d549e5cc@1.99.0.48 9 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | compile.on.save=true 2 | user.properties.file=C:\\Users\\Leo\\AppData\\Roaming\\NetBeans\\12.4\\build.properties 3 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/World.java 8 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/Face.java 9 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/View.java 10 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/Edge.java 11 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/Response.java 12 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionTest/src/test/Player.java 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processor.options= 4 | annotation.processing.processors.list= 5 | annotation.processing.run.all.processors=true 6 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 7 | build.classes.dir=${build.dir}/classes 8 | build.classes.excludes=**/*.java,**/*.form 9 | # This directory is removed when the project is cleaned: 10 | build.dir=build 11 | build.generated.dir=${build.dir}/generated 12 | build.generated.sources.dir=${build.dir}/generated-sources 13 | # Only compile against the classpath explicitly listed here: 14 | build.sysclasspath=ignore 15 | build.test.classes.dir=${build.dir}/test/classes 16 | build.test.results.dir=${build.dir}/test/results 17 | # Uncomment to specify the preferred debugger connection transport: 18 | #debug.transport=dt_socket 19 | debug.classpath=\ 20 | ${run.classpath} 21 | debug.modulepath=\ 22 | ${run.modulepath} 23 | debug.test.classpath=\ 24 | ${run.test.classpath} 25 | debug.test.modulepath=\ 26 | ${run.test.modulepath} 27 | # Files in build.classes.dir which should be excluded from distribution jar 28 | dist.archive.excludes= 29 | # This directory is removed when the project is cleaned: 30 | dist.dir=dist 31 | dist.jar=${dist.dir}/Java3DMeshVsSphereCollisionTest.jar 32 | dist.javadoc.dir=${dist.dir}/javadoc 33 | dist.jlink.dir=${dist.dir}/jlink 34 | dist.jlink.output=${dist.jlink.dir}/Java3DMeshVsSphereCollisionTest 35 | excludes= 36 | includes=** 37 | jar.compress=false 38 | javac.classpath= 39 | # Space-separated list of extra javac options 40 | javac.compilerargs= 41 | javac.deprecation=false 42 | javac.external.vm=true 43 | javac.modulepath= 44 | javac.processormodulepath= 45 | javac.processorpath=\ 46 | ${javac.classpath} 47 | javac.source=1.8 48 | javac.target=1.8 49 | javac.test.classpath=\ 50 | ${javac.classpath}:\ 51 | ${build.classes.dir} 52 | javac.test.modulepath=\ 53 | ${javac.modulepath} 54 | javac.test.processorpath=\ 55 | ${javac.test.classpath} 56 | javadoc.additionalparam= 57 | javadoc.author=false 58 | javadoc.encoding=${source.encoding} 59 | javadoc.html5=false 60 | javadoc.noindex=false 61 | javadoc.nonavbar=false 62 | javadoc.notree=false 63 | javadoc.private=false 64 | javadoc.splitindex=true 65 | javadoc.use=true 66 | javadoc.version=false 67 | javadoc.windowtitle= 68 | # The jlink additional root modules to resolve 69 | jlink.additionalmodules= 70 | # The jlink additional command line parameters 71 | jlink.additionalparam= 72 | jlink.launcher=true 73 | jlink.launcher.name=Java3DMeshVsSphereCollisionTest 74 | main.class=test.View 75 | manifest.file=manifest.mf 76 | meta.inf.dir=${src.dir}/META-INF 77 | mkdist.disabled=false 78 | platform.active=default_platform 79 | run.classpath=\ 80 | ${javac.classpath}:\ 81 | ${build.classes.dir} 82 | # Space-separated list of JVM arguments used when running the project. 83 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. 84 | # To set system properties for unit tests define test-sys-prop.name=value: 85 | run.jvmargs= 86 | run.modulepath=\ 87 | ${javac.modulepath} 88 | run.test.classpath=\ 89 | ${javac.test.classpath}:\ 90 | ${build.test.classes.dir} 91 | run.test.modulepath=\ 92 | ${javac.test.modulepath} 93 | source.encoding=UTF-8 94 | src.dir=src 95 | test.src.dir=test 96 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | Java3DMeshVsSphereCollisionTest 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/res/terrain.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 500.000001 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.800000 0.800000 0.800000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Camera.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * Camera class. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Camera { 9 | 10 | public static final Vec3 DA = new Vec3(); 11 | public static final Vec3 DB = new Vec3(); 12 | public static final Vec3 POSITION = new Vec3(0, -50, -500); 13 | public static final double DISTANCE = 500; 14 | public static final double SCALE = 50; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Edge.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | 6 | /** 7 | * Edge class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Edge { 12 | 13 | private final Face face; 14 | private final Vec3 a; 15 | private final Vec3 b; 16 | 17 | // points to inside 18 | private final Vec3 normal = new Vec3(); 19 | 20 | private final Vec3 vTmp1 = new Vec3(); 21 | private final Vec3 vTmp2 = new Vec3(); 22 | private final Vec3 vTmp3 = new Vec3(); 23 | 24 | public Edge(Face face, Vec3 a, Vec3 b) { 25 | this.face = face; 26 | this.a = a; 27 | this.b = b; 28 | updateLengthAndNormal(); 29 | } 30 | 31 | private void updateLengthAndNormal() { 32 | normal.set(b); 33 | normal.sub(a); 34 | normal.cross(face.getNormal()); 35 | normal.normalize(); 36 | } 37 | 38 | public Vec3 getA() { 39 | return a; 40 | } 41 | 42 | public Vec3 getB() { 43 | return b; 44 | } 45 | 46 | public boolean isInside(Vec3 contactPoint) { 47 | vTmp1.set(contactPoint); 48 | vTmp1.sub(a); 49 | return vTmp1.dot(normal) >= 0; 50 | } 51 | 52 | public Response checkCollision(Vec3 contactPoint, Sphere sphere, Response response) { 53 | vTmp1.set(contactPoint); 54 | vTmp1.sub(a); 55 | double dot = vTmp1.dot(normal); 56 | vTmp1.set(normal); 57 | vTmp1.scale(-dot); 58 | vTmp1.add(contactPoint); 59 | 60 | // keep contact point inside edge 61 | vTmp3.set(b); 62 | vTmp3.sub(a); 63 | vTmp2.set(vTmp1); 64 | vTmp2.sub(a); 65 | double dot1 = vTmp3.dot(vTmp3); 66 | double dot2 = vTmp3.dot(vTmp2); 67 | if (dot2 < 0) { 68 | vTmp1.set(a); 69 | } 70 | else if (dot2 > dot1) { 71 | vTmp1.set(b); 72 | } 73 | 74 | vTmp2.set(sphere.getPosition()); 75 | vTmp2.sub(vTmp1); 76 | 77 | response.setCollides(vTmp2.getLength() <= sphere.getRadius()); 78 | response.getContactPoint().set(vTmp1); 79 | response.getContactNormal().set(vTmp2); 80 | response.getContactNormal().normalize(); 81 | response.getContactNormal().scale(sphere.getRadius() - vTmp2.getLength() + 0.000000001); 82 | response.setIsEdge(true); 83 | 84 | return response; 85 | } 86 | 87 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 88 | Camera.DA.set(a); 89 | Camera.DA.sub(translate); 90 | Camera.DA.rotateY(-angle); 91 | Camera.DA.scale(scale); 92 | Camera.DA.add(Camera.POSITION); 93 | 94 | Camera.DB.set(b); 95 | Camera.DB.sub(translate); 96 | Camera.DB.rotateY(-angle); 97 | Camera.DB.scale(scale); 98 | Camera.DB.add(Camera.POSITION); 99 | 100 | if (Camera.DA.z >= -0.1) return; 101 | if (Camera.DB.z >= -0.1) return; 102 | 103 | int sax = (int) (Camera.DISTANCE * (Camera.DA.x / -Camera.DA.z)); 104 | int say = (int) (Camera.DISTANCE * (Camera.DA.y / -Camera.DA.z)); 105 | int sbx = (int) (Camera.DISTANCE * (Camera.DB.x / -Camera.DB.z)); 106 | int sby = (int) (Camera.DISTANCE * (Camera.DB.y / -Camera.DB.z)); 107 | 108 | g.setColor(Color.RED); 109 | g.fillOval(sax - 3, say - 3, 6, 6); 110 | g.fillOval(sbx - 3, sby - 3, 6, 6); 111 | g.setColor(Color.BLACK); 112 | g.drawLine(sax, say, sbx, sby); 113 | } 114 | 115 | @Override 116 | public String toString() { 117 | return "Edge{" + "face=" + face + ", a=" + a + ", b=" + b 118 | + ", normal=" + normal + '}'; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Face.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Face class. 10 | * 11 | * @author Leonardo Ono (ono.leo80@gmail.com) 12 | */ 13 | public class Face { 14 | 15 | private final Vec3 normal = new Vec3(); 16 | private final List points = new ArrayList<>(); 17 | private final List edges = new ArrayList<>(); 18 | private final Response response = new Response(); 19 | 20 | public Face() { 21 | } 22 | 23 | public Vec3 getNormal() { 24 | return normal; 25 | } 26 | 27 | public List getPoints() { 28 | return points; 29 | } 30 | 31 | public void addPoint(Vec3 point) { 32 | points.add(point); 33 | } 34 | 35 | public void addPoint(double x, double y, double z) { 36 | points.add(new Vec3(x, y, z)); 37 | } 38 | 39 | public void close() { 40 | Vec3 v1 = new Vec3(points.get(0)); 41 | v1.sub(points.get(1)); 42 | Vec3 v2 = new Vec3(points.get(2)); 43 | v2.sub(points.get(1)); 44 | normal.set(v1); 45 | normal.cross(v2); 46 | normal.normalize(); 47 | 48 | for (int i = 0; i < points.size(); i++) { 49 | Vec3 a = points.get(i); 50 | Vec3 b = points.get((i + 1) % points.size()); 51 | Edge edge = new Edge(this, a, b); 52 | edges.add(edge); 53 | //System.out.println("edge: " + edge); 54 | } 55 | } 56 | private final Vec3 vTmp = new Vec3(); 57 | 58 | public Response checkCollision(Sphere sphere) { 59 | response.setIsEdge(false); 60 | 61 | vTmp.set(sphere.getPosition()); // contact point in the triangle plane 62 | vTmp.sub(points.get(0)); 63 | double dot = vTmp.dot(normal); 64 | 65 | vTmp.set(normal); 66 | vTmp.scale(-dot); 67 | vTmp.add(sphere.getPosition()); 68 | 69 | //System.out.println("contact point: " + vTmp); 70 | 71 | for (Edge edge : edges) { 72 | if (!edge.isInside(vTmp)) { 73 | return edge.checkCollision(vTmp, sphere, response); 74 | } 75 | } 76 | 77 | response.setCollides(Math.abs(dot) <= sphere.getRadius()); 78 | response.getContactPoint().set(vTmp); 79 | response.getContactNormal().set(normal); 80 | response.getContactNormal().scale(sphere.getRadius() - dot + 0.000000001); 81 | 82 | return response; 83 | } 84 | 85 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 86 | edges.forEach((edge) -> { 87 | edge.draw3D(g, scale, angle, translate); 88 | }); 89 | 90 | if (response.isCollides()) { 91 | 92 | Camera.DA.set(response.getContactPoint()); 93 | Camera.DA.sub(translate); 94 | Camera.DA.rotateY(-angle); 95 | Camera.DA.scale(scale); 96 | Camera.DA.add(Camera.POSITION); 97 | 98 | int cpx = (int) (Camera.DISTANCE * (Camera.DA.x / -Camera.DA.z)); 99 | int cpy = (int) (Camera.DISTANCE * (Camera.DA.y / -Camera.DA.z)); 100 | 101 | g.setColor(Color.ORANGE); 102 | g.fillOval(cpx - 5, cpy - 5, 10, 10); 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Input.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.event.KeyAdapter; 4 | import java.awt.event.KeyEvent; 5 | 6 | /** 7 | * Input class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Input extends KeyAdapter { 12 | 13 | public static boolean[] keyPressed = new boolean[256]; 14 | 15 | public static boolean isKeyPressed(int keyCode) { 16 | return keyPressed[keyCode]; 17 | } 18 | 19 | @Override 20 | public void keyPressed(KeyEvent e) { 21 | keyPressed[e.getKeyCode()] = true; 22 | } 23 | 24 | @Override 25 | public void keyReleased(KeyEvent e) { 26 | keyPressed[e.getKeyCode()] = false; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/MeshLoader.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * MeshLoader class. 11 | * 12 | * @author Leonardo Ono (ono.leo80@gmail.com) 13 | */ 14 | public class MeshLoader { 15 | 16 | private final List vertices = new ArrayList<>(); 17 | private final List faces = new ArrayList<>(); 18 | 19 | private double scaleFactor; 20 | private double translateX; 21 | private double translateY; 22 | private double translateZ; 23 | 24 | public MeshLoader() { 25 | } 26 | 27 | public List getVertices() { 28 | return vertices; 29 | } 30 | 31 | public List getFaces() { 32 | return faces; 33 | } 34 | 35 | public double getScaleFactor() { 36 | return scaleFactor; 37 | } 38 | 39 | public double getTranslateX() { 40 | return translateX; 41 | } 42 | 43 | public double getTranslateY() { 44 | return translateY; 45 | } 46 | 47 | public double getTranslateZ() { 48 | return translateZ; 49 | } 50 | 51 | public void load(String meshRes, double scaleFactor, double translateX 52 | , double translateY, double translateZ) throws Exception { 53 | 54 | vertices.clear(); 55 | faces.clear(); 56 | 57 | this.scaleFactor = scaleFactor; 58 | this.translateX = translateX; 59 | this.translateY = translateY; 60 | this.translateZ = translateZ; 61 | 62 | InputStream is = MeshLoader.class.getResourceAsStream(meshRes); 63 | InputStreamReader isr = new InputStreamReader(is); 64 | BufferedReader br = new BufferedReader(isr); 65 | String line; 66 | while ((line = br.readLine()) != null) { 67 | if (line.startsWith("v ")) { 68 | parseVertex(line); 69 | } 70 | else if (line.startsWith("f ")) { 71 | parseFace(line); 72 | } 73 | } 74 | br.close(); 75 | } 76 | 77 | private void parseVertex(String line) { 78 | String[] data = line.split(" "); 79 | double x = Double.parseDouble(data[1]); 80 | double y = Double.parseDouble(data[2]); 81 | double z = Double.parseDouble(data[3]); 82 | double stx = x * scaleFactor + translateX; 83 | double sty = y * scaleFactor + translateY; 84 | double stz = z * scaleFactor + translateZ; 85 | Vec3 v = new Vec3(stx, sty, stz); 86 | vertices.add(v); 87 | } 88 | 89 | private void parseFace(String line) { 90 | String[] data = line.split(" "); 91 | Face face = new Face(); 92 | for (int i = 1; i < data.length; i++) { 93 | String[] data2 = data[i].split("/"); 94 | int index = Integer.parseInt(data2[0]); 95 | face.addPoint(vertices.get(index - 1)); 96 | } 97 | face.close(); 98 | faces.add(face); 99 | } 100 | 101 | @Override 102 | public String toString() { 103 | return "MeshLoader{" + "vertices=" + vertices + ", faces=" + faces 104 | + ", scaleFactor=" + scaleFactor + ", translateX=" + translateX 105 | + ", translateY=" + translateY + '}'; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Player.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Graphics2D; 4 | import java.awt.event.KeyEvent; 5 | 6 | /** 7 | * Player class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Player { 12 | 13 | private Sphere collider = new Sphere(); 14 | private double angle; 15 | private final Vec3 velocity = new Vec3(); 16 | 17 | public Player() { 18 | collider = new Sphere(0.5, 0, 1, -1); 19 | } 20 | 21 | public Sphere getCollider() { 22 | return collider; 23 | } 24 | 25 | public double getAngle() { 26 | return angle; 27 | } 28 | 29 | public Vec3 getVelocity() { 30 | return velocity; 31 | } 32 | 33 | public void update() { 34 | final double maxSpeed = 0.1; 35 | 36 | if (Input.isKeyPressed(KeyEvent.VK_LEFT)) { 37 | //sphere.getPosition().x -= 0.03; 38 | angle -= 0.025; 39 | } 40 | else if (Input.isKeyPressed(KeyEvent.VK_RIGHT)) { 41 | //sphere.getPosition().x += 0.03; 42 | angle += 0.025; 43 | } 44 | double speed = 0; 45 | if (Input.isKeyPressed(KeyEvent.VK_UP)) { 46 | speed = -maxSpeed; 47 | //sphere.getPosition().y += 0.03; 48 | } 49 | else if (Input.isKeyPressed(KeyEvent.VK_DOWN)) { 50 | speed = maxSpeed; 51 | //sphere.getPosition().y -= 0.03; 52 | } 53 | velocity.x = 0; 54 | velocity.z = 0; 55 | 56 | if (speed != 0) { 57 | double dx = speed * Math.cos(angle + Math.toRadians(90)); 58 | double dz = speed * Math.sin(angle + Math.toRadians(90)); 59 | velocity.x = dx; 60 | velocity.z = dz; 61 | } 62 | 63 | if (Input.isKeyPressed(KeyEvent.VK_A)) { 64 | speed = 0.05; 65 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 66 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 67 | velocity.x = dx; 68 | velocity.z = dz; 69 | } 70 | else if (Input.isKeyPressed(KeyEvent.VK_D)) { 71 | speed = -0.05; 72 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 73 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 74 | velocity.x = dx; 75 | velocity.z = dz; 76 | } 77 | 78 | if (Input.isKeyPressed(KeyEvent.VK_SPACE)) { 79 | velocity.y += 0.05; 80 | if (velocity.y > 0.5) { 81 | velocity.y = 0.5; 82 | } 83 | } 84 | 85 | // gravity 86 | velocity.y -= 0.005; 87 | if (velocity.y < -0.5) velocity.y = -0.5; 88 | } 89 | 90 | public void draw3D(Graphics2D g, double scale) { 91 | collider.draw3D(g, scale, angle, collider.getPosition()); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Response.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * (Collision) Response class. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Response { 9 | 10 | private boolean collides; 11 | private final Vec3 contactPoint = new Vec3(); 12 | private final Vec3 contactNormal = new Vec3(); 13 | private boolean edge; 14 | 15 | public boolean isCollides() { 16 | return collides; 17 | } 18 | 19 | public void setCollides(boolean collides) { 20 | this.collides = collides; 21 | } 22 | 23 | public Vec3 getContactPoint() { 24 | return contactPoint; 25 | } 26 | 27 | public Vec3 getContactNormal() { 28 | return contactNormal; 29 | } 30 | 31 | public boolean isEdge() { 32 | return edge; 33 | } 34 | 35 | public void setIsEdge(boolean edge) { 36 | this.edge = edge; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "Response{" + "collides=" + collides 42 | + ", contactPoint=" + contactPoint 43 | + ", contactNormal=" + contactNormal + '}'; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Sphere.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | 6 | /** 7 | * Sphere class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Sphere { 12 | 13 | private double radius; 14 | private Vec3 position = new Vec3(); 15 | 16 | public Sphere() { 17 | } 18 | 19 | public Sphere(double radius) { 20 | this.radius = radius; 21 | } 22 | 23 | public Sphere(double radius, double x, double y, double z) { 24 | this.radius = radius; 25 | this.position.set(x, y, z); 26 | } 27 | 28 | public double getRadius() { 29 | return radius; 30 | } 31 | 32 | public void setRadius(double radius) { 33 | this.radius = radius; 34 | } 35 | 36 | public Vec3 getPosition() { 37 | return position; 38 | } 39 | 40 | public void setPosition(Vec3 position) { 41 | this.position = position; 42 | } 43 | 44 | public void draw(Graphics2D g, double scale) { 45 | g.setColor(Color.BLACK); 46 | int diameter = (int) (2 * radius * scale); 47 | int ox = (int) (scale * (position.x - radius)); 48 | int oy = (int) (scale * (position.y - radius)); 49 | g.drawOval(ox, oy, diameter, diameter); 50 | } 51 | 52 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 53 | Camera.DA.set(position); 54 | Camera.DA.sub(translate); 55 | Camera.DA.rotateY(-angle); 56 | Camera.DA.scale(scale); 57 | Camera.DA.add(Camera.POSITION); 58 | 59 | Camera.DB.set(position); 60 | Camera.DB.sub(translate); 61 | Camera.DB.rotateY(-angle); 62 | Camera.DB.y -= radius; 63 | Camera.DB.scale(scale); 64 | Camera.DB.add(Camera.POSITION); 65 | 66 | int sax = (int) (Camera.DISTANCE * (Camera.DA.x / -Camera.DA.z)); 67 | int say = (int) (Camera.DISTANCE * (Camera.DA.y / -Camera.DA.z)); 68 | int say2 = (int) (Camera.DISTANCE * (Camera.DB.y / -Camera.DA.z)); 69 | 70 | int sRadius = Math.abs(say - say2); 71 | int diameter = sRadius * 2; 72 | g.setColor(Color.BLACK); 73 | g.drawOval(sax - sRadius, say - sRadius, diameter, diameter); 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return "Sphere{" + "radius=" + radius + ", position=" + position + '}'; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/Vec3.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * class Vec3. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Vec3 { 9 | 10 | public double x; 11 | public double y; 12 | public double z; 13 | 14 | public Vec3() { 15 | } 16 | 17 | public Vec3(double x, double y, double z) { 18 | this.x = x; 19 | this.y = y; 20 | this.z = z; 21 | } 22 | 23 | public Vec3(Vec3 v) { 24 | this.x = v.x; 25 | this.y = v.y; 26 | this.z = v.z; 27 | } 28 | 29 | public Vec3(Vec3 a, Vec3 b) { 30 | this.x = b.x - a.x; 31 | this.y = b.y - a.y; 32 | this.z = b.z - a.z; 33 | } 34 | 35 | public void set(double x, double y, double z) { 36 | this.x = x; 37 | this.y = y; 38 | this.z = z; 39 | } 40 | 41 | public void set(Vec3 v) { 42 | this.x = v.x; 43 | this.y = v.y; 44 | this.z = v.z; 45 | } 46 | 47 | public void add(Vec3 v) { 48 | this.x += v.x; 49 | this.y += v.y; 50 | this.z += v.z; 51 | } 52 | 53 | public void sub(Vec3 v) { 54 | this.x -= v.x; 55 | this.y -= v.y; 56 | this.z -= v.z; 57 | } 58 | 59 | public void scale(double s) { 60 | scale(s, s, s); 61 | } 62 | 63 | public void scale(double sx, double sy, double sz) { 64 | this.x *= sx; 65 | this.y *= sy; 66 | this.z *= sz; 67 | } 68 | 69 | public double getLength() { 70 | return Math.sqrt(x * x + y * y + z * z); 71 | } 72 | 73 | public void normalize() { 74 | double length = getLength(); 75 | if (length != 0) { 76 | x /= length; 77 | y /= length; 78 | z /= length; 79 | } 80 | } 81 | 82 | public double dot(Vec3 v) { 83 | return x * v.x + y * v.y + z * v.z; 84 | } 85 | 86 | public double dot2D(Vec3 v) { 87 | return x * v.x + z * v.z; 88 | } 89 | 90 | public void cross(Vec3 v) { 91 | double cx = y * v.z - z * v.y; 92 | double cy = z * v.x - x * v.z; 93 | double cz = x * v.y - y * v.x; 94 | x = cx; 95 | y = cy; 96 | z = cz; 97 | } 98 | 99 | public double cross2D(Vec3 v) { 100 | return x * v.z - z * v.x; 101 | } 102 | 103 | public void rotateY(double angle) { 104 | double s = Math.sin(angle); 105 | double c = Math.cos(angle); 106 | double nx = x * c - z * s; 107 | double nz = x * s + z * c; 108 | set(nx, y, nz); 109 | } 110 | 111 | @Override 112 | public String toString() { 113 | return "Vec3{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/View.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.Graphics; 5 | import java.awt.Graphics2D; 6 | import javax.swing.JFrame; 7 | import javax.swing.JPanel; 8 | import javax.swing.SwingUtilities; 9 | 10 | /** 11 | * Java 3D Mesh vs Sphere Collision Test 12 | * 13 | * @author Leonardo Ono (ono.leo80@gmail.com); 14 | */ 15 | public class View extends JPanel { 16 | 17 | private final World world = new World(); 18 | 19 | public View() { 20 | } 21 | 22 | public void start() { 23 | addKeyListener(new Input()); 24 | } 25 | 26 | @Override 27 | protected void paintComponent(Graphics g) { 28 | super.paintComponent(g); 29 | update(); 30 | draw((Graphics2D) g); 31 | try { 32 | Thread.sleep(1000 / 60); 33 | } catch (InterruptedException ex) { 34 | } 35 | repaint(); 36 | } 37 | 38 | private void update() { 39 | world.update(); 40 | 41 | } 42 | 43 | private void draw(Graphics2D g) { 44 | g.clearRect(0, 0, getWidth(), getHeight()); 45 | //g.drawLine(0, 0, getWidth(), getHeight()); 46 | 47 | g.translate(400, 300); 48 | g.scale(1, -1); 49 | 50 | world.draw(g); 51 | } 52 | 53 | public static void main(String[] args) { 54 | SwingUtilities.invokeLater(() -> { 55 | View view = new View(); 56 | view.setPreferredSize(new Dimension(800, 600)); 57 | JFrame frame = new JFrame(); 58 | frame.setTitle("Java 3D Mesh vs Sphere Collision - NEW"); 59 | frame.getContentPane().add(view); 60 | frame.setResizable(false); 61 | frame.pack(); 62 | frame.setLocationRelativeTo(null); 63 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 64 | frame.setVisible(true); 65 | view.requestFocus(); 66 | view.start(); 67 | }); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionTest/src/test/World.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Graphics2D; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.logging.Level; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * class World. 12 | * 13 | * @author Leonardo Ono (ono.leo80@gmail.com) 14 | */ 15 | public class World { 16 | 17 | private final List faces = new ArrayList<>(); 18 | private final Player player = new Player(); 19 | private MeshLoader terrain; 20 | 21 | public World() { 22 | createTest2(); 23 | } 24 | 25 | private void createTest2() { 26 | terrain = new MeshLoader(); 27 | try { 28 | terrain.load("/res/terrain.obj", 20, 0, -5, 0); 29 | } catch (Exception ex) { 30 | Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex); 31 | System.exit(1); 32 | } 33 | faces.addAll(terrain.getFaces()); 34 | } 35 | 36 | private void createTest() { 37 | Face face = new Face(); 38 | face.addPoint(2, 0, 2); 39 | face.addPoint(-2, 0, -2); 40 | face.addPoint(2, 0, -2); 41 | face.close(); 42 | faces.add(face); 43 | 44 | Face face2 = new Face(); 45 | face2.addPoint(-2, 0, 2); 46 | face2.addPoint(-2, 0, -2); 47 | face2.addPoint(2, 0, 2); 48 | face2.close(); 49 | faces.add(face2); 50 | 51 | Face face3 = new Face(); 52 | face3.addPoint(-2, 0, -2); 53 | face3.addPoint(-2, 2, -2.0); 54 | face3.addPoint(2, 2, -2.0); 55 | face3.close(); 56 | faces.add(face3); 57 | 58 | Face face4 = new Face(); 59 | face4.addPoint(-2, 0, -2); 60 | face4.addPoint(2, 2, -2.0); 61 | face4.addPoint(2, 0, -2); 62 | face4.close(); 63 | faces.add(face4); 64 | 65 | } 66 | 67 | private final Vec3 playerPreviousPosition = new Vec3(); 68 | private final Vec3 resultPush = new Vec3(); 69 | 70 | public void update() { 71 | player.update(); 72 | 73 | // update player position 74 | player.getCollider().getPosition().add(player.getVelocity()); 75 | 76 | // save player position 77 | playerPreviousPosition.set(player.getCollider().getPosition()); 78 | 79 | boolean keepChecking = true; 80 | 81 | // detect collision with all polygons 82 | outer: 83 | while (keepChecking) { 84 | keepChecking = false; 85 | 86 | // give priority for non edge collisions first 87 | for (Face face : faces) { 88 | Response response = face.checkCollision(player.getCollider()); 89 | if (response.isCollides() 90 | && response.getContactNormal().getLength() > 0 91 | && !response.isEdge()) { 92 | 93 | Vec3 contactNormal = response.getContactNormal(); 94 | player.getCollider().getPosition().add(contactNormal); 95 | keepChecking = true; 96 | continue outer; 97 | } 98 | } 99 | 100 | // check the edge collisions 101 | for (Face face : faces) { 102 | Response response = face.checkCollision(player.getCollider()); 103 | if (response.isCollides() 104 | && response.getContactNormal().getLength() > 0 105 | && response.isEdge()) { 106 | 107 | Vec3 contactNormal = response.getContactNormal(); 108 | player.getCollider().getPosition().add(contactNormal); 109 | keepChecking = true; 110 | continue outer; 111 | } 112 | } 113 | } 114 | 115 | resultPush.set(player.getCollider().getPosition()); 116 | resultPush.sub(playerPreviousPosition); 117 | 118 | // if colliding, fix velocity 119 | resultPush.normalize(); 120 | double dot = resultPush.dot(player.getVelocity()); 121 | resultPush.scale(dot); 122 | player.getVelocity().sub(resultPush); 123 | } 124 | 125 | public void draw(Graphics2D g) { 126 | player.draw3D(g, Camera.SCALE); 127 | faces.forEach((face) -> { 128 | face.draw3D(g, Camera.SCALE 129 | , player.getAngle(), player.getCollider().getPosition()); 130 | }); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project Java3DMeshTerrainVsPlayerCollisionOctreeTest. 12 | 13 | 73 | 74 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=e2d1b696 2 | build.xml.script.CRC32=a544bd90 3 | build.xml.stylesheet.CRC32=f85dc8f2@1.99.0.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=e2d1b696 7 | nbproject/build-impl.xml.script.CRC32=e416671d 8 | nbproject/build-impl.xml.stylesheet.CRC32=d549e5cc@1.99.0.48 9 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | compile.on.save=true 2 | user.properties.file=C:\\Users\\Leo\\AppData\\Roaming\\NetBeans\\12.4\\build.properties 3 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/physics/Input.java 7 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/partition/Node.java 8 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/octree/View.java 9 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/partition/Box.java 10 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/octree/Player.java 11 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/octree/MeshLoader.java 12 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/octree/View2.java 13 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/physics/Face.java 14 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionOctreeTest/src/partition/Octree.java 15 | 16 | 17 | file:/D:/work/java/git/Java3DMeshVsSphereCollisionTest/Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/octree/MeshLoader.java 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processor.options= 4 | annotation.processing.processors.list= 5 | annotation.processing.run.all.processors=true 6 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 7 | build.classes.dir=${build.dir}/classes 8 | build.classes.excludes=**/*.java,**/*.form 9 | # This directory is removed when the project is cleaned: 10 | build.dir=build 11 | build.generated.dir=${build.dir}/generated 12 | build.generated.sources.dir=${build.dir}/generated-sources 13 | # Only compile against the classpath explicitly listed here: 14 | build.sysclasspath=ignore 15 | build.test.classes.dir=${build.dir}/test/classes 16 | build.test.results.dir=${build.dir}/test/results 17 | # Uncomment to specify the preferred debugger connection transport: 18 | #debug.transport=dt_socket 19 | debug.classpath=\ 20 | ${run.classpath} 21 | debug.modulepath=\ 22 | ${run.modulepath} 23 | debug.test.classpath=\ 24 | ${run.test.classpath} 25 | debug.test.modulepath=\ 26 | ${run.test.modulepath} 27 | # Files in build.classes.dir which should be excluded from distribution jar 28 | dist.archive.excludes= 29 | # This directory is removed when the project is cleaned: 30 | dist.dir=dist 31 | dist.jar=${dist.dir}/Java3DMeshTerrainVsPlayerCollisionOctreeTest.jar 32 | dist.javadoc.dir=${dist.dir}/javadoc 33 | dist.jlink.dir=${dist.dir}/jlink 34 | dist.jlink.output=${dist.jlink.dir}/Java3DMeshTerrainVsPlayerCollisionOctreeTest 35 | excludes= 36 | includes=** 37 | jar.compress=false 38 | javac.classpath= 39 | # Space-separated list of extra javac options 40 | javac.compilerargs= 41 | javac.deprecation=false 42 | javac.external.vm=true 43 | javac.modulepath= 44 | javac.processormodulepath= 45 | javac.processorpath=\ 46 | ${javac.classpath} 47 | javac.source=1.8 48 | javac.target=1.8 49 | javac.test.classpath=\ 50 | ${javac.classpath}:\ 51 | ${build.classes.dir} 52 | javac.test.modulepath=\ 53 | ${javac.modulepath} 54 | javac.test.processorpath=\ 55 | ${javac.test.classpath} 56 | javadoc.additionalparam= 57 | javadoc.author=false 58 | javadoc.encoding=${source.encoding} 59 | javadoc.html5=false 60 | javadoc.noindex=false 61 | javadoc.nonavbar=false 62 | javadoc.notree=false 63 | javadoc.private=false 64 | javadoc.splitindex=true 65 | javadoc.use=true 66 | javadoc.version=false 67 | javadoc.windowtitle= 68 | # The jlink additional root modules to resolve 69 | jlink.additionalmodules= 70 | # The jlink additional command line parameters 71 | jlink.additionalparam= 72 | jlink.launcher=true 73 | jlink.launcher.name=Java3DMeshTerrainVsPlayerCollisionOctreeTest 74 | main.class=octree.View2 75 | manifest.file=manifest.mf 76 | meta.inf.dir=${src.dir}/META-INF 77 | mkdist.disabled=false 78 | platform.active=default_platform 79 | run.classpath=\ 80 | ${javac.classpath}:\ 81 | ${build.classes.dir} 82 | # Space-separated list of JVM arguments used when running the project. 83 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. 84 | # To set system properties for unit tests define test-sys-prop.name=value: 85 | run.jvmargs= 86 | run.modulepath=\ 87 | ${javac.modulepath} 88 | run.test.classpath=\ 89 | ${javac.test.classpath}:\ 90 | ${build.test.classes.dir} 91 | run.test.modulepath=\ 92 | ${javac.test.modulepath} 93 | source.encoding=UTF-8 94 | src.dir=src 95 | test.src.dir=test 96 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | Java3DMeshTerrainVsPlayerCollisionOctreeTest 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/octree/MeshLoader.java: -------------------------------------------------------------------------------- 1 | package octree; 2 | 3 | 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import physics.Face; 11 | import physics.Vec3; 12 | 13 | /** 14 | * MeshLoader class. 15 | * 16 | * @author Leonardo Ono (ono.leo80@gmail.com) 17 | */ 18 | public class MeshLoader { 19 | 20 | private final List vertices = new ArrayList<>(); 21 | private final List faces = new ArrayList<>(); 22 | 23 | private double scaleFactor; 24 | private double translateX; 25 | private double translateY; 26 | private double translateZ; 27 | 28 | private Vec3 min = new Vec3(); 29 | private Vec3 max = new Vec3(); 30 | 31 | public MeshLoader() { 32 | min.set(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 33 | max.set(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE); 34 | } 35 | 36 | public List getVertices() { 37 | return vertices; 38 | } 39 | 40 | public List getFaces() { 41 | return faces; 42 | } 43 | 44 | public double getScaleFactor() { 45 | return scaleFactor; 46 | } 47 | 48 | public double getTranslateX() { 49 | return translateX; 50 | } 51 | 52 | public double getTranslateY() { 53 | return translateY; 54 | } 55 | 56 | public double getTranslateZ() { 57 | return translateZ; 58 | } 59 | 60 | public Vec3 getMin() { 61 | return min; 62 | } 63 | 64 | public void setMin(Vec3 min) { 65 | this.min = min; 66 | } 67 | 68 | public Vec3 getMax() { 69 | return max; 70 | } 71 | 72 | public void setMax(Vec3 max) { 73 | this.max = max; 74 | } 75 | 76 | public void load(String meshRes, double scaleFactor 77 | , double translateX, double translateY, double translateZ) throws Exception { 78 | 79 | vertices.clear(); 80 | faces.clear(); 81 | 82 | this.scaleFactor = scaleFactor; 83 | this.translateX = translateX; 84 | this.translateY = translateY; 85 | this.translateZ = translateZ; 86 | 87 | InputStream is = MeshLoader.class.getResourceAsStream(meshRes); 88 | InputStreamReader isr = new InputStreamReader(is); 89 | BufferedReader br = new BufferedReader(isr); 90 | String line; 91 | while ((line = br.readLine()) != null) { 92 | if (line.startsWith("v ")) { 93 | parseVertex(line); 94 | } 95 | else if (line.startsWith("f ")) { 96 | parseFace(line); 97 | } 98 | } 99 | br.close(); 100 | 101 | //Vec3 tMin = new Vec3(-1, -1, -1); 102 | //Vec3 tMax = new Vec3(1, 1, 1); 103 | 104 | //min.add(tMin); 105 | //max.add(tMax); 106 | 107 | //min.set(-100, -100, -100); 108 | //max.set(100, 100, 100); 109 | } 110 | 111 | private void parseVertex(String line) { 112 | String[] data = line.split(" "); 113 | double x = Double.parseDouble(data[1]); 114 | double y = Double.parseDouble(data[2]); 115 | double z = Double.parseDouble(data[3]); 116 | double stx = x * scaleFactor + translateX; 117 | double sty = y * scaleFactor + translateY; 118 | double stz = z * scaleFactor + translateZ; 119 | Vec3 v = new Vec3(stx, sty, stz); 120 | vertices.add(v); 121 | updateMinMax(v); 122 | } 123 | 124 | private void parseFace(String line) { 125 | String[] data = line.split(" "); 126 | //List ps = new ArrayList<>(); 127 | Face face = new Face(); 128 | for (int i = 1; i < data.length; i++) { 129 | String[] data2 = data[i].split("/"); 130 | int index = Integer.parseInt(data2[0]); 131 | //ps.add(vertices.get(index - 1)); 132 | Vec3 p = vertices.get(index - 1); 133 | face.addPoint(p); 134 | } 135 | face.close(); 136 | faces.add(face); 137 | } 138 | 139 | private void updateMinMax(Vec3 p) { 140 | if (p.x < min.x) { 141 | min.x = p.x; 142 | } 143 | if (p.y < min.y) { 144 | min.y = p.y; 145 | } 146 | if (p.z < min.z) { 147 | min.z = p.z; 148 | } 149 | if (p.x > max.x) { 150 | max.x = p.x; 151 | } 152 | if (p.y > max.y) { 153 | max.y = p.y; 154 | } 155 | if (p.z > max.z) { 156 | max.z = p.z; 157 | } 158 | } 159 | 160 | @Override 161 | public String toString() { 162 | return "MeshLoader{" + "vertices=" + vertices + ", faces=" + faces 163 | + ", scaleFactor=" + scaleFactor + ", translateX=" + translateX 164 | + ", translateY=" + translateY + '}'; 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/octree/Player.java: -------------------------------------------------------------------------------- 1 | package octree; 2 | 3 | 4 | import java.awt.Color; 5 | import java.awt.Graphics2D; 6 | import java.awt.event.KeyEvent; 7 | import partition.Box; 8 | import physics.Input; 9 | import physics.Sphere; 10 | import physics.Vec3; 11 | 12 | 13 | /** 14 | * 15 | * @author admin 16 | */ 17 | public class Player { 18 | 19 | private Sphere collider = new Sphere(); 20 | private double angle; 21 | private final Vec3 velocity = new Vec3(); 22 | private final Box box = new Box(); 23 | 24 | public Player() { 25 | collider = new Sphere(5, 0, 0, 0); 26 | } 27 | 28 | public Sphere getCollider() { 29 | return collider; 30 | } 31 | 32 | public double getAngle() { 33 | return angle; 34 | } 35 | 36 | public Vec3 getVelocity() { 37 | return velocity; 38 | } 39 | 40 | public void update() { 41 | if (Input.isKeyPressed(KeyEvent.VK_LEFT)) { 42 | System.out.println("left pressed"); 43 | //sphere.getPosition().x -= 0.03; 44 | angle -= 0.025; 45 | } 46 | else if (Input.isKeyPressed(KeyEvent.VK_RIGHT)) { 47 | //sphere.getPosition().x += 0.03; 48 | angle += 0.025; 49 | } 50 | double speed = 0; 51 | if (Input.isKeyPressed(KeyEvent.VK_UP)) { 52 | speed = -1; 53 | //sphere.getPosition().y += 0.03; 54 | } 55 | else if (Input.isKeyPressed(KeyEvent.VK_DOWN)) { 56 | speed = 1; 57 | //sphere.getPosition().y -= 0.03; 58 | } 59 | velocity.x = 0; 60 | velocity.z = 0; 61 | 62 | if (speed != 0) { 63 | double dx = speed * Math.cos(angle + Math.toRadians(90)); 64 | double dz = speed * Math.sin(angle + Math.toRadians(90)); 65 | velocity.x = dx; 66 | velocity.z = dz; 67 | } 68 | 69 | if (Input.isKeyPressed(KeyEvent.VK_A)) { 70 | speed = 0.05; 71 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 72 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 73 | velocity.x = dx; 74 | velocity.z = dz; 75 | } 76 | else if (Input.isKeyPressed(KeyEvent.VK_D)) { 77 | speed = -0.05; 78 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 79 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 80 | velocity.x = dx; 81 | velocity.z = dz; 82 | } 83 | 84 | if (Input.isKeyPressed(KeyEvent.VK_SPACE)) { 85 | velocity.y += 0.05; 86 | if (velocity.y > 0.2) { 87 | velocity.y = 0.2; 88 | } 89 | //sphere.getPosition().y -= 0.03; 90 | } 91 | 92 | // gravity 93 | //velocity.y -= 0.005; 94 | 95 | 96 | 97 | // if (Input.isKeyPressed(KeyEvent.VK_Q)) { 98 | // collider.getPosition().y -= 0.025; 99 | // } 100 | // else if (Input.isKeyPressed(KeyEvent.VK_A)) { 101 | // collider.getPosition().y += 0.025; 102 | // } 103 | collider.getPosition().add(velocity); 104 | 105 | System.out.println("player position: " + collider.getPosition()); 106 | 107 | } 108 | 109 | public void draw(Graphics2D g, double scale) { 110 | collider.draw(g, scale); 111 | } 112 | 113 | public void draw3D(Graphics2D g, double scale) { 114 | collider.draw3D(g, scale, angle, collider.getPosition()); 115 | } 116 | 117 | public Box getBox() { 118 | box.getMin().set(collider.getPosition()); 119 | box.getMin().x -= collider.getRadius(); 120 | box.getMin().y -= collider.getRadius(); 121 | box.getMin().z -= collider.getRadius(); 122 | box.getMax().set(collider.getPosition()); 123 | box.getMax().x += collider.getRadius(); 124 | box.getMax().y += collider.getRadius(); 125 | box.getMax().z += collider.getRadius(); 126 | box.updateLength(); 127 | return box; 128 | } 129 | 130 | public void drawTop(Graphics2D g) { 131 | g.setColor(Color.MAGENTA); 132 | Box box = getBox(); 133 | box.drawTop(g); 134 | } 135 | 136 | public void drawFront(Graphics2D g) { 137 | g.setColor(Color.MAGENTA); 138 | Box box = getBox(); 139 | box.drawFront(g); 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/octree/View.java: -------------------------------------------------------------------------------- 1 | package octree; 2 | 3 | 4 | 5 | import java.awt.Color; 6 | import java.awt.Dimension; 7 | import java.awt.Graphics; 8 | import java.awt.Graphics2D; 9 | import java.awt.event.KeyEvent; 10 | import java.awt.geom.AffineTransform; 11 | import javax.swing.JFrame; 12 | import javax.swing.JPanel; 13 | import javax.swing.SwingUtilities; 14 | import partition.Box; 15 | import physics.Input; 16 | import physics.Vec3; 17 | 18 | /** 19 | * Java 3D Terrain Mesh vs Ball Player Collision Test 20 | * 21 | * @author Leonardo Ono (ono.leo80@gmail.com); 22 | */ 23 | public class View extends JPanel { 24 | 25 | private final Box box1 = new Box(new Vec3(-50, -50, -50), new Vec3(50, 150, 50), Color.BLACK); 26 | private final Box box2 = new Box(new Vec3(-20, -20, -20), new Vec3(20, 100, 20), Color.BLUE); 27 | 28 | public View() { 29 | } 30 | 31 | public void start() { 32 | addKeyListener(new Input()); 33 | } 34 | 35 | @Override 36 | protected void paintComponent(Graphics g) { 37 | super.paintComponent(g); 38 | update(); 39 | draw((Graphics2D) g); 40 | try { 41 | Thread.sleep(1000 / 60); 42 | } catch (InterruptedException ex) { 43 | } 44 | repaint(); 45 | } 46 | 47 | private void update() { 48 | if (Input.isKeyPressed(KeyEvent.VK_LEFT)) { 49 | box2.translate(-1, 0, 0); 50 | } 51 | else if (Input.isKeyPressed(KeyEvent.VK_RIGHT)) { 52 | box2.translate(1, 0, 0); 53 | } 54 | 55 | if (Input.isKeyPressed(KeyEvent.VK_UP)) { 56 | box2.translate(0, 0, -1); 57 | } 58 | else if (Input.isKeyPressed(KeyEvent.VK_DOWN)) { 59 | box2.translate(0, 0, 1); 60 | } 61 | 62 | if (Input.isKeyPressed(KeyEvent.VK_Q)) { 63 | box2.translate(0, 1, 0); 64 | } 65 | else if (Input.isKeyPressed(KeyEvent.VK_A)) { 66 | box2.translate(0, -1, 0); 67 | } 68 | } 69 | 70 | private void draw(Graphics2D g) { 71 | g.clearRect(0, 0, getWidth(), getHeight()); 72 | g.drawLine(0, 0, getWidth(), getHeight()); 73 | 74 | AffineTransform at = g.getTransform(); 75 | 76 | // front 77 | g.setTransform(at); 78 | g.translate(getWidth() / 4, getHeight() / 2); 79 | g.setColor(Color.BLACK); 80 | g.drawString("Front", 0, -200); 81 | g.scale(1, -1); 82 | drawFront(g); 83 | 84 | // top 85 | g.setTransform(at); 86 | g.translate(3 * getWidth() / 4, getHeight() / 2); 87 | g.setColor(Color.BLACK); 88 | g.drawString("Top", 0, -200); 89 | drawTop(g); 90 | 91 | // box inside ? 92 | g.setTransform(at); 93 | boolean completelyInside = box2.isCompletelyInside(box1); 94 | boolean intersects = box2.intersects(box1); 95 | g.setColor(Color.RED); 96 | g.drawString("completely inside? " + completelyInside, 50, 50); 97 | g.drawString("intersects? " + intersects, 50, 70); 98 | 99 | } 100 | 101 | private void drawFront(Graphics2D g) { 102 | box1.drawFront(g); 103 | box2.drawFront(g); 104 | } 105 | 106 | private void drawTop(Graphics2D g) { 107 | box1.drawTop(g); 108 | box2.drawTop(g); 109 | } 110 | 111 | public static void main(String[] args) { 112 | SwingUtilities.invokeLater(() -> { 113 | View view = new View(); 114 | view.setPreferredSize(new Dimension(800, 600)); 115 | JFrame frame = new JFrame(); 116 | frame.setTitle("Java Octree Test"); 117 | frame.getContentPane().add(view); 118 | frame.setResizable(false); 119 | frame.pack(); 120 | frame.setLocationRelativeTo(null); 121 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 122 | frame.setVisible(true); 123 | view.requestFocus(); 124 | view.start(); 125 | }); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/octree/View2.java: -------------------------------------------------------------------------------- 1 | package octree; 2 | 3 | 4 | 5 | import java.awt.Color; 6 | import java.awt.Dimension; 7 | import java.awt.Graphics; 8 | import java.awt.Graphics2D; 9 | import java.awt.event.KeyEvent; 10 | import java.awt.geom.AffineTransform; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.logging.Level; 14 | import java.util.logging.Logger; 15 | import javax.swing.JFrame; 16 | import javax.swing.JPanel; 17 | import javax.swing.SwingUtilities; 18 | import partition.Box; 19 | import partition.Octree; 20 | import physics.Face; 21 | import physics.Input; 22 | import physics.Vec3; 23 | 24 | /** 25 | * Java 3D Terrain Mesh vs Ball Player Collision Test 26 | * 27 | * @author Leonardo Ono (ono.leo80@gmail.com); 28 | */ 29 | public class View2 extends JPanel { 30 | 31 | private final Box box1 = new Box(new Vec3(-50, -50, -50), new Vec3(50, 150, 50), Color.BLACK); 32 | private Box box2; // = new Box(new Vec3(-20, -20, -20), new Vec3(20, 100, 20), Color.BLUE); 33 | 34 | private List boxes = new ArrayList<>(); // = new Box(new Vec3(-20, -20, -20), new Vec3(20, 100, 20), Color.BLUE); 35 | 36 | private Box playerBox = new Box(new Vec3(-5, -5, -5), new Vec3(5, 5, 5), Color.BLACK); 37 | 38 | private MeshLoader terrain = new MeshLoader(); 39 | 40 | private Octree octree; 41 | 42 | private List retrievedFaces = new ArrayList<>(); 43 | 44 | private Player player = new Player(); 45 | 46 | private int selectedPlayer = 1; 47 | 48 | public View2() { 49 | } 50 | 51 | public void start() { 52 | addKeyListener(new Input()); 53 | 54 | terrain = new MeshLoader(); 55 | try { 56 | //terrain.load("/res/terrain.obj", 200, 0, -5, 0); 57 | terrain.load("/res/terrain.obj", 200, 0, -5, 0); 58 | } catch (Exception ex) { 59 | Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex); 60 | System.exit(1); 61 | } 62 | 63 | //box2 = new Box(terrain.getFaces().get(0)); 64 | for (Face face : terrain.getFaces()) { 65 | boxes.add(new Box(face, Color.GRAY)); 66 | } 67 | 68 | box2 = new Box(terrain.getMin(), terrain.getMax(), Color.RED); 69 | 70 | octree = new Octree(terrain.getMin(), terrain.getMax()); 71 | 72 | for (int i = 0; i < terrain.getFaces().size(); i++) { 73 | Face face = terrain.getFaces().get(i); 74 | octree.addFace(face); 75 | } 76 | } 77 | 78 | @Override 79 | protected void paintComponent(Graphics g) { 80 | super.paintComponent(g); 81 | update(); 82 | draw((Graphics2D) g); 83 | try { 84 | Thread.sleep(1000 / 60); 85 | } catch (InterruptedException ex) { 86 | } 87 | repaint(); 88 | } 89 | 90 | private void update() { 91 | if (Input.isKeyPressed(KeyEvent.VK_0)) { 92 | selectedPlayer = 0; 93 | } 94 | else if (Input.isKeyPressed(KeyEvent.VK_1)) { 95 | selectedPlayer = 1; 96 | } 97 | 98 | if (selectedPlayer == 0) { 99 | updatePlayer(); 100 | } 101 | else if (selectedPlayer == 1) { 102 | updatePlayerBox(); 103 | } 104 | } 105 | 106 | private void updatePlayer() { 107 | player.update(); 108 | //updatePlayerBox(); 109 | retrievedFaces.clear(); 110 | octree.retrieveFaces(player.getBox(), retrievedFaces); 111 | } 112 | 113 | private void updatePlayerBox() { 114 | if (Input.isKeyPressed(KeyEvent.VK_LEFT)) { 115 | playerBox.translate(-1, 0, 0); 116 | } 117 | else if (Input.isKeyPressed(KeyEvent.VK_RIGHT)) { 118 | playerBox.translate(1, 0, 0); 119 | } 120 | 121 | if (Input.isKeyPressed(KeyEvent.VK_UP)) { 122 | playerBox.translate(0, 0, -1); 123 | } 124 | else if (Input.isKeyPressed(KeyEvent.VK_DOWN)) { 125 | playerBox.translate(0, 0, 1); 126 | } 127 | 128 | if (Input.isKeyPressed(KeyEvent.VK_Q)) { 129 | playerBox.translate(0, 1, 0); 130 | } 131 | else if (Input.isKeyPressed(KeyEvent.VK_A)) { 132 | playerBox.translate(0, -1, 0); 133 | } 134 | retrievedFaces.clear(); 135 | octree.retrieveFaces(playerBox, retrievedFaces); 136 | } 137 | 138 | private void draw(Graphics2D g) { 139 | g.clearRect(0, 0, getWidth(), getHeight()); 140 | //g.drawLine(0, 0, getWidth(), getHeight()); 141 | 142 | AffineTransform at = g.getTransform(); 143 | 144 | // front 145 | g.setTransform(at); 146 | g.translate(getWidth() / 4, getHeight() / 2); 147 | g.setColor(Color.BLACK); 148 | g.drawString("Front", 0, -230); 149 | g.scale(1, -1); 150 | drawFront(g); 151 | 152 | // top 153 | g.setTransform(at); 154 | g.translate(3 * getWidth() / 4, getHeight() / 2); 155 | g.setColor(Color.BLACK); 156 | g.drawString("Top", 0, -230); 157 | g.scale(1, 1); 158 | drawTop(g); 159 | 160 | // box inside ? 161 | g.setTransform(at); 162 | boolean completelyInside = box2.isCompletelyInside(box1); 163 | boolean intersects = box2.intersects(box1); 164 | g.setColor(Color.RED); 165 | g.drawString("completely inside? " + completelyInside, 50, 50); 166 | g.drawString("intersects? " + intersects, 50, 70); 167 | 168 | // retrieved faces 169 | g.drawString("retrieved faces = " + retrievedFaces.size(), 50, 90); 170 | 171 | if (selectedPlayer == 0) { 172 | g.drawString("selected: player", 50, 110); 173 | } 174 | else if (selectedPlayer == 1) { 175 | g.drawString("selected: playerBox", 50, 110); 176 | } 177 | 178 | } 179 | 180 | private void drawFront(Graphics2D g) { 181 | if (selectedPlayer == 1) { 182 | playerBox.drawFront(g); 183 | } 184 | 185 | //box2.drawFront(g); 186 | //for (Box box : boxes) { 187 | // box.drawFront(g); 188 | //} 189 | 190 | 191 | octree.drawPartitionsFront(g); 192 | 193 | for (Face face : retrievedFaces) { 194 | face.drawFront(g, Color.GREEN); 195 | } 196 | 197 | if (selectedPlayer == 0) { 198 | player.getBox().drawFront(g); 199 | } 200 | } 201 | 202 | private void drawTop(Graphics2D g) { 203 | if (selectedPlayer == 1) { 204 | playerBox.drawTop(g); 205 | } 206 | //box2.drawTop(g); 207 | //for (Box box : boxes) { 208 | // box.drawTop(g); 209 | //} 210 | 211 | octree.drawPartitionsTop(g); 212 | 213 | for (Face face : retrievedFaces) { 214 | face.drawTop(g, Color.GREEN); 215 | } 216 | 217 | 218 | if (selectedPlayer == 0) { 219 | player.getBox().drawTop(g); 220 | } 221 | } 222 | 223 | public static void main(String[] args) { 224 | SwingUtilities.invokeLater(() -> { 225 | View2 view = new View2(); 226 | view.setPreferredSize(new Dimension(1000, 600)); 227 | JFrame frame = new JFrame(); 228 | frame.setTitle("Java Octree Test"); 229 | frame.getContentPane().add(view); 230 | frame.setResizable(false); 231 | frame.pack(); 232 | frame.setLocationRelativeTo(null); 233 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 234 | frame.setVisible(true); 235 | view.requestFocus(); 236 | view.start(); 237 | }); 238 | } 239 | 240 | } 241 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/partition/Box.java: -------------------------------------------------------------------------------- 1 | package partition; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Rectangle; 6 | import physics.Face; 7 | import physics.Vec3; 8 | 9 | /** 10 | * 11 | * @author admin 12 | */ 13 | public class Box { 14 | 15 | protected final Vec3 min = new Vec3(); 16 | protected final Vec3 max = new Vec3(); 17 | 18 | 19 | protected final Vec3 length = new Vec3(); 20 | 21 | protected Color color; 22 | 23 | private Face face; 24 | 25 | public Box() { 26 | } 27 | 28 | public Box(Face face, Color color) { 29 | setInternal(face, color); 30 | } 31 | 32 | public void set(Face face) { 33 | setInternal(face, color); 34 | } 35 | 36 | private void setInternal(Face face, Color color) { 37 | this.color = color; 38 | this.face = face; 39 | 40 | double minX = Double.MAX_VALUE; 41 | double minY = Double.MAX_VALUE; 42 | double minZ = Double.MAX_VALUE; 43 | double maxX = -Double.MAX_VALUE; 44 | double maxY = -Double.MAX_VALUE; 45 | double maxZ = -Double.MAX_VALUE; 46 | for (Vec3 point : face.getPoints()) { 47 | if (point.x < minX) { 48 | minX = point.x; 49 | } 50 | if (point.y < minY) { 51 | minY = point.y; 52 | } 53 | if (point.z < minZ) { 54 | minZ = point.z; 55 | } 56 | 57 | if (point.x > maxX) { 58 | maxX = point.x; 59 | } 60 | if (point.y > maxY) { 61 | maxY = point.y; 62 | } 63 | if (point.z > maxZ) { 64 | maxZ = point.z; 65 | } 66 | } 67 | min.set(minX, minY, minZ); 68 | max.set(maxX, maxY, maxZ); 69 | 70 | length.set(max); 71 | length.sub(min); 72 | length.x = Math.abs(length.x); 73 | length.y = Math.abs(length.y); 74 | length.z = Math.abs(length.z); 75 | } 76 | 77 | public Box(Vec3 min, Vec3 max, Color color) { 78 | this.color = color; 79 | this.min.set(min); 80 | this.max.set(max); 81 | 82 | length.set(max); 83 | length.sub(min); 84 | length.x = Math.abs(length.x); 85 | length.y = Math.abs(length.y); 86 | length.z = Math.abs(length.z); 87 | } 88 | 89 | public void set(Vec3 min, Vec3 max) { 90 | this.min.set(min); 91 | this.max.set(max); 92 | 93 | length.set(max); 94 | length.sub(min); 95 | length.x = Math.abs(length.x); 96 | length.y = Math.abs(length.y); 97 | length.z = Math.abs(length.z); 98 | } 99 | 100 | public void updateLength() { 101 | length.set(max); 102 | length.sub(min); 103 | length.x = Math.abs(length.x); 104 | length.y = Math.abs(length.y); 105 | length.z = Math.abs(length.z); 106 | } 107 | 108 | public Vec3 getMin() { 109 | return min; 110 | } 111 | 112 | public Vec3 getMax() { 113 | return max; 114 | } 115 | 116 | public Vec3 getLength() { 117 | return length; 118 | } 119 | 120 | public boolean intersects(Box box) { 121 | double xt1 = (box.length.x + length.x); 122 | double xt2 = Math.abs(Math.max(max.x, box.max.x) - Math.min(min.x, box.min.x)); 123 | if (xt2 > xt1) { 124 | return false; 125 | } 126 | 127 | double yt1 = (box.length.y + length.y); 128 | double yt2 = Math.abs(Math.max(max.y, box.max.y) - Math.min(min.y, box.min.y)); 129 | if (yt2 > yt1) { 130 | return false; 131 | } 132 | 133 | double zt1 = (box.length.z + length.z); 134 | double zt2 = Math.abs(Math.max(max.z, box.max.z) - Math.min(min.z, box.min.z)); 135 | return zt2 <= zt1; 136 | } 137 | 138 | public boolean isCompletelyInside(Box box) { 139 | return min.x >= box.min.x && min.x <= box.max.x 140 | && max.x >= box.min.x && max.x <= box.max.x 141 | && min.y >= box.min.y && min.y <= box.max.y 142 | && max.y >= box.min.y && max.y <= box.max.y 143 | && min.z >= box.min.z && min.z <= box.max.z 144 | && max.z >= box.min.z && max.z <= box.max.z; 145 | } 146 | 147 | @Override 148 | public String toString() { 149 | return "Box{" + "min=" + min + ", max=" + max + '}'; 150 | } 151 | 152 | private final Rectangle rect = new Rectangle(); 153 | 154 | public void drawTop(Graphics2D g) { 155 | if (face != null) { 156 | face.drawTop(g, Color.BLUE); 157 | } 158 | 159 | g.setColor(color); 160 | rect.setBounds((int) min.x, (int) min.z, (int) (max.x - min.x), (int) (max.z - min.z)); 161 | //g.drawString("(" + min.x + "," + min.z + ")", (int) min.x, (int) (min.z)); 162 | //g.drawString("(" + max.x + "," + max.z + ")", (int) max.x, (int) (max.z)); 163 | g.draw(rect); 164 | 165 | } 166 | 167 | public void drawFront(Graphics2D g) { 168 | if (face != null) { 169 | face.drawFront(g, Color.BLUE); 170 | } 171 | 172 | g.setColor(color); 173 | rect.setBounds((int) min.x, (int) min.y, (int) (max.x - min.x), (int) (max.y - min.y)); 174 | //g.drawString("(" + min.x + "," + min.y + ")", (int) min.x, (int) (min.y)); 175 | //g.drawString("(" + max.x + "," + max.y + ")", (int) max.x, (int) (max.y)); 176 | g.draw(rect); 177 | 178 | } 179 | 180 | public void translate(double tx, double ty, double tz) { 181 | min.x += tx; 182 | min.y += ty; 183 | min.z += tz; 184 | max.x += tx; 185 | max.y += ty; 186 | max.z += tz; 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/partition/Node.java: -------------------------------------------------------------------------------- 1 | package partition; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import physics.Face; 8 | import physics.Vec3; 9 | 10 | /** 11 | * 12 | * @author admin 13 | */ 14 | public class Node extends Box { 15 | 16 | protected int depth; 17 | protected List faces = new ArrayList<>(); 18 | protected Node[] children = new Node[8]; 19 | protected Box boxTmp = new Box(); 20 | protected boolean partitioned; 21 | 22 | public Node(int depth, Vec3 min, Vec3 max) { 23 | super(min, max, Color.RED); 24 | this.depth = depth; 25 | } 26 | 27 | protected void partition() { 28 | Vec3 b1Min = new Vec3(min.x, min.y, min.z); 29 | Vec3 b1Max = new Vec3(min.x + length.x / 2, min.y + length.y / 2, min.z + length.z / 2); 30 | 31 | Vec3 b2Min = new Vec3(min.x + length.x / 2, min.y, min.z); 32 | Vec3 b2Max = new Vec3(min.x + length.x, min.y + length.y / 2, min.z + length.z / 2); 33 | 34 | Vec3 b3Min = new Vec3(min.x, min.y, min.z + length.z / 2); 35 | Vec3 b3Max = new Vec3(min.x + length.x / 2, min.y + length.y / 2, min.z + length.z); 36 | 37 | Vec3 b4Min = new Vec3(min.x + length.x / 2, min.y, min.z + length.z / 2); 38 | Vec3 b4Max = new Vec3(min.x + length.x, min.y + length.y / 2, min.z + length.z); 39 | 40 | Vec3 b5Min = new Vec3(min.x, min.y + length.y / 2, min.z); 41 | Vec3 b5Max = new Vec3(min.x + length.x / 2, min.y + length.y, min.z + length.z / 2); 42 | 43 | Vec3 b6Min = new Vec3(min.x + length.x / 2, min.y + length.y / 2, min.z); 44 | Vec3 b6Max = new Vec3(min.x + length.x, min.y + length.y, min.z + length.z / 2); 45 | 46 | Vec3 b7Min = new Vec3(min.x, min.y + length.y / 2, min.z + length.z / 2); 47 | Vec3 b7Max = new Vec3(min.x + length.x / 2, min.y + length.y, min.z + length.z); 48 | 49 | Vec3 b8Min = new Vec3(min.x + length.x / 2, min.y + length.y / 2, min.z + length.z / 2); 50 | Vec3 b8Max = new Vec3(min.x + length.x, min.y + length.y, min.z + length.z); 51 | 52 | Vec3[][] minMax = { 53 | {b1Min, b1Max}, 54 | {b2Min, b2Max}, 55 | {b3Min, b3Max}, 56 | {b4Min, b4Max}, 57 | {b5Min, b5Max}, 58 | {b6Min, b6Max}, 59 | {b7Min, b7Max}, 60 | {b8Min, b8Max}, 61 | }; 62 | 63 | for (int i = 0; i < 8; i++) { 64 | children[i] = new Node(depth + 1, minMax[i][0], minMax[i][1]); 65 | } 66 | 67 | partitioned = true; 68 | } 69 | 70 | 71 | public void addFace(Face face) { 72 | 73 | if (!partitioned) { 74 | partition(); 75 | } 76 | 77 | boolean addFaceInThisNode = true; 78 | 79 | //if (depth < 10) { 80 | boxTmp.set(face); 81 | for (Node node : children) { 82 | if (boxTmp.isCompletelyInside(node)) { 83 | addFaceInThisNode = false; 84 | node.addFace(face); 85 | break; 86 | } 87 | } 88 | //} 89 | 90 | if (addFaceInThisNode) { 91 | faces.add(face); 92 | System.out.println("added face " + face + " depth=" + depth + " faces.size()=" + faces.size()); 93 | } 94 | } 95 | 96 | public void retrieveFaces(Box box, List result) { 97 | if (partitioned) { 98 | for (Node node : children) { 99 | if (node.intersects(box)) { 100 | node.retrieveFaces(box, result); 101 | } 102 | } 103 | } 104 | if (intersects(box)) { 105 | result.addAll(faces); 106 | } 107 | } 108 | 109 | public void drawPartitionsTop(Graphics2D g) { 110 | drawTop(g); 111 | if (partitioned) { 112 | for (Node child : children) { 113 | child.drawPartitionsTop(g); 114 | } 115 | } 116 | 117 | for (Face face : faces) { 118 | face.drawTop(g, Color.BLUE); 119 | } 120 | } 121 | 122 | public void drawPartitionsFront(Graphics2D g) { 123 | drawFront(g); 124 | if (partitioned) { 125 | for (Node child : children) { 126 | child.drawPartitionsFront(g); 127 | } 128 | } 129 | 130 | for (Face face : faces) { 131 | face.drawFront(g, Color.BLUE); 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/partition/Octree.java: -------------------------------------------------------------------------------- 1 | package partition; 2 | 3 | import java.util.List; 4 | import physics.Face; 5 | import physics.Vec3; 6 | 7 | /** 8 | * 9 | * @author admin 10 | */ 11 | public class Octree extends Node { 12 | 13 | public Octree(Vec3 min, Vec3 max) { 14 | super(0, min, max); 15 | } 16 | 17 | public void addFaces(List facesAdd) { 18 | for (Face faceAdd : facesAdd) { 19 | addFace(faceAdd); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Camera.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | /** 4 | * 5 | * @author admin 6 | */ 7 | public class Camera { 8 | 9 | public static final Vec3 da = new Vec3(); 10 | public static final Vec3 db = new Vec3(); 11 | public static final Vec3 camera = new Vec3(0, -50, -500); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Edge.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | 4 | import java.awt.Color; 5 | import java.awt.Graphics2D; 6 | 7 | 8 | /** 9 | * 10 | * @author admin 11 | */ 12 | public class Edge { 13 | 14 | private final Face face; 15 | private final Vec3 a; 16 | private final Vec3 b; 17 | private double length; 18 | 19 | // points to inside 20 | private final Vec3 normal = new Vec3(); 21 | 22 | private final Vec3 vTmp1 = new Vec3(); 23 | private final Vec3 vTmp2 = new Vec3(); 24 | private final Vec3 vTmp3 = new Vec3(); 25 | 26 | public Edge(Face face, Vec3 a, Vec3 b) { 27 | this.face = face; 28 | this.a = a; 29 | this.b = b; 30 | updateLengthAndNormal(); 31 | } 32 | 33 | private void updateLengthAndNormal() { 34 | normal.set(b); 35 | normal.sub(a); 36 | length = normal.getLength(); 37 | normal.cross(face.getNormal()); 38 | normal.normalize(); 39 | } 40 | 41 | public Vec3 getA() { 42 | return a; 43 | } 44 | 45 | public Vec3 getB() { 46 | return b; 47 | } 48 | 49 | public boolean isInside(Vec3 contactPoint) { 50 | vTmp1.set(contactPoint); 51 | vTmp1.sub(a); 52 | return vTmp1.dot(normal) >= 0; 53 | } 54 | 55 | public Response checkCollision(Vec3 contactPoint, Sphere sphere, Response response) { 56 | vTmp1.set(contactPoint); 57 | vTmp1.sub(a); 58 | double dot = vTmp1.dot(normal); 59 | vTmp1.set(normal); 60 | vTmp1.scale(-dot); 61 | vTmp1.add(contactPoint); 62 | 63 | // keep contact point inside edge 64 | vTmp3.set(b); 65 | vTmp3.sub(a); 66 | vTmp2.set(vTmp1); 67 | vTmp2.sub(a); 68 | double dot1 = vTmp3.dot(vTmp3); 69 | double dot2 = vTmp3.dot(vTmp2); 70 | if (dot2 < 0) { 71 | vTmp1.set(a); 72 | } 73 | else if (dot2 > dot1) { 74 | vTmp1.set(b); 75 | } 76 | 77 | vTmp2.set(sphere.getPosition()); 78 | vTmp2.sub(vTmp1); 79 | 80 | response.setCollides(vTmp2.getLength() <= sphere.getRadius()); 81 | response.getContactPoint().set(vTmp1); 82 | response.getContactNormal().set(vTmp2); 83 | response.getContactNormal().normalize(); 84 | response.getContactNormal().scale(sphere.getRadius() - vTmp2.getLength()); 85 | 86 | return response; 87 | } 88 | 89 | public void draw(Graphics2D g, double scale) { 90 | g.setColor(Color.BLACK); 91 | g.drawLine((int) (scale * a.x), (int) (scale * a.y), (int) (scale * b.x), (int) (scale * b.y)); 92 | } 93 | 94 | private final Vec3 da = new Vec3(); 95 | private final Vec3 db = new Vec3(); 96 | private final Vec3 camera = new Vec3(0, -50, -500); 97 | 98 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 99 | 100 | da.set(a); 101 | da.sub(translate); 102 | da.rotateY(-angle); 103 | da.scale(scale); 104 | da.add(camera); 105 | 106 | db.set(b); 107 | db.sub(translate); 108 | db.rotateY(-angle); 109 | db.scale(scale); 110 | db.add(camera); 111 | 112 | if (da.z >= -0.1) return; 113 | if (db.z >= -0.1) return; 114 | 115 | // double ax = (scale * (a.x + translate.x)); 116 | // double ay = (scale * (a.y + translate.y)); 117 | // double az = (scale * (a.z + translate.z)); 118 | // double bx = (scale * (b.x + translate.x)); 119 | // double by = (scale * (b.y + translate.y)); 120 | // double bz = (scale * (b.z + translate.z)); 121 | 122 | int sax = (int) (500 * (da.x / -da.z)); 123 | int say = (int) (500 * (da.y / -da.z)); 124 | int sbx = (int) (500 * (db.x / -db.z)); 125 | int sby = (int) (500 * (db.y / -db.z)); 126 | 127 | g.setColor(Color.RED); 128 | g.fillOval(sax - 3, say - 3, 6, 6); 129 | g.fillOval(sbx - 3, sby - 3, 6, 6); 130 | g.setColor(Color.BLACK); 131 | g.drawLine(sax, say, sbx, sby); 132 | 133 | } 134 | 135 | @Override 136 | public String toString() { 137 | return "Edge{" + "face=" + face + ", a=" + a + ", b=" + b 138 | + ", normal=" + normal + '}'; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Face.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Polygon; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * 11 | * @author admin 12 | */ 13 | public class Face { 14 | 15 | private final Vec3 normal = new Vec3(); 16 | private final List points = new ArrayList<>(); 17 | private final List edges = new ArrayList<>(); 18 | private final Response response = new Response(); 19 | 20 | public Face() { 21 | } 22 | 23 | public Vec3 getNormal() { 24 | return normal; 25 | } 26 | 27 | public List getPoints() { 28 | return points; 29 | } 30 | 31 | public void addPoint(Vec3 point) { 32 | points.add(point); 33 | } 34 | 35 | public void addPoint(double x, double y, double z) { 36 | points.add(new Vec3(x, y, z)); 37 | } 38 | 39 | public void close() { 40 | Vec3 v1 = new Vec3(points.get(0)); 41 | v1.sub(points.get(1)); 42 | Vec3 v2 = new Vec3(points.get(2)); 43 | v2.sub(points.get(1)); 44 | normal.set(v1); 45 | normal.cross(v2); 46 | normal.normalize(); 47 | 48 | for (int i = 0; i < points.size(); i++) { 49 | Vec3 a = points.get(i); 50 | Vec3 b = points.get((i + 1) % points.size()); 51 | Edge edge = new Edge(this, a, b); 52 | edges.add(edge); 53 | //System.out.println("edge: " + edge); 54 | } 55 | } 56 | private final Vec3 vTmp = new Vec3(); 57 | 58 | public Response checkCollision(Sphere sphere) { 59 | vTmp.set(sphere.getPosition()); // contact point in the triangle plane 60 | vTmp.sub(points.get(0)); 61 | double dot = vTmp.dot(normal); 62 | 63 | vTmp.set(normal); 64 | vTmp.scale(-dot); 65 | vTmp.add(sphere.getPosition()); 66 | 67 | //System.out.println("contact point: " + vTmp); 68 | 69 | for (Edge edge : edges) { 70 | if (!edge.isInside(vTmp)) { 71 | return edge.checkCollision(vTmp, sphere, response); 72 | } 73 | } 74 | 75 | response.setCollides(Math.abs(dot) <= sphere.getRadius()); 76 | response.getContactPoint().set(vTmp); 77 | response.getContactNormal().set(normal); 78 | response.getContactNormal().scale(sphere.getRadius() - dot); 79 | 80 | return response; 81 | } 82 | 83 | public void draw(Graphics2D g, double scale) { 84 | for (Edge edge : edges) { 85 | edge.draw(g, scale); 86 | } 87 | } 88 | 89 | 90 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 91 | for (Edge edge : edges) { 92 | edge.draw3D(g, scale, angle, translate); 93 | } 94 | 95 | if (response.isCollides()) { 96 | 97 | Camera.da.set(response.getContactPoint()); 98 | Camera.da.sub(translate); 99 | Camera.da.rotateY(-angle); 100 | Camera.da.scale(scale); 101 | Camera.da.add(Camera.camera); 102 | 103 | int cpx = (int) (500 * (Camera.da.x / -Camera.da.z)); 104 | int cpy = (int) (500 * (Camera.da.y / -Camera.da.z)); 105 | 106 | g.setColor(Color.ORANGE); 107 | g.fillOval(cpx - 5, cpy - 5, 10, 10); 108 | 109 | // double x1 = (scale * response.getContactPoint().x); 110 | // double y1 = (scale * response.getContactPoint().y); 111 | // double z1 = (scale * response.getContactPoint().z); 112 | // double x2 = (scale * (response.getContactPoint().x + response.getContactNormal().x)); 113 | // double y2 = (scale * (response.getContactPoint().y + response.getContactNormal().y)); 114 | // double z2 = (scale * (response.getContactPoint().z + response.getContactNormal().z)); 115 | // 116 | // int csx1 = (int) (500 * (x1 / -z1)); 117 | // int csy1 = (int) (500 * (y1 / -z1)); 118 | // int csx2 = (int) (500 * (x2 / -z2)); 119 | // int csy2 = (int) (500 * (y2 / -z2)); 120 | // g.drawLine(csx1, csy1, csx2, csy2); 121 | } 122 | 123 | } 124 | 125 | //private final Color color = Color.BLUE; 126 | private final Polygon polygonTmp = new Polygon(); 127 | 128 | public void drawTop(Graphics2D g, Color color) { 129 | g.setColor(color); 130 | polygonTmp.reset(); 131 | polygonTmp.addPoint((int) points.get(0).x, (int) points.get(0).z); 132 | polygonTmp.addPoint((int) points.get(1).x, (int) points.get(1).z); 133 | polygonTmp.addPoint((int) points.get(2).x, (int) points.get(2).z); 134 | g.draw(polygonTmp); 135 | } 136 | 137 | public void drawFront(Graphics2D g, Color color) { 138 | g.setColor(color); 139 | polygonTmp.reset(); 140 | polygonTmp.addPoint((int) points.get(0).x, (int) points.get(0).y); 141 | polygonTmp.addPoint((int) points.get(1).x, (int) points.get(1).y); 142 | polygonTmp.addPoint((int) points.get(2).x, (int) points.get(2).y); 143 | g.draw(polygonTmp); 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Input.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | 4 | 5 | import java.awt.event.KeyAdapter; 6 | import java.awt.event.KeyEvent; 7 | 8 | /** 9 | * 10 | * @author admin 11 | */ 12 | public class Input extends KeyAdapter { 13 | 14 | public static boolean[] keyPressed = new boolean[256]; 15 | 16 | public static boolean isKeyPressed(int keyCode) { 17 | return keyPressed[keyCode]; 18 | } 19 | 20 | @Override 21 | public void keyPressed(KeyEvent e) { 22 | keyPressed[e.getKeyCode()] = true; 23 | } 24 | 25 | @Override 26 | public void keyReleased(KeyEvent e) { 27 | keyPressed[e.getKeyCode()] = false; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Response.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | 4 | /** 5 | * 6 | * @author admin 7 | */ 8 | public class Response { 9 | 10 | private boolean collides; 11 | private final Vec3 contactPoint = new Vec3(); 12 | private final Vec3 contactNormal = new Vec3(); 13 | 14 | public boolean isCollides() { 15 | return collides; 16 | } 17 | 18 | public void setCollides(boolean collides) { 19 | this.collides = collides; 20 | } 21 | 22 | public Vec3 getContactPoint() { 23 | return contactPoint; 24 | } 25 | 26 | public Vec3 getContactNormal() { 27 | return contactNormal; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "Response{" + "collides=" + collides 33 | + ", contactPoint=" + contactPoint 34 | + ", contactNormal=" + contactNormal + '}'; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Sphere.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | 4 | import java.awt.Color; 5 | import java.awt.Graphics2D; 6 | 7 | 8 | /** 9 | * 10 | * @author admin 11 | */ 12 | public class Sphere { 13 | 14 | private double radius; 15 | private Vec3 position = new Vec3(); 16 | 17 | public Sphere() { 18 | } 19 | 20 | public Sphere(double radius) { 21 | this.radius = radius; 22 | } 23 | 24 | public Sphere(double radius, double x, double y, double z) { 25 | this.radius = radius; 26 | this.position.set(x, y, z); 27 | } 28 | 29 | public double getRadius() { 30 | return radius; 31 | } 32 | 33 | public void setRadius(double radius) { 34 | this.radius = radius; 35 | } 36 | 37 | public Vec3 getPosition() { 38 | return position; 39 | } 40 | 41 | public void setPosition(Vec3 position) { 42 | this.position = position; 43 | } 44 | 45 | public void draw(Graphics2D g, double scale) { 46 | g.setColor(Color.BLACK); 47 | int diameter = (int) (2 * radius * scale); 48 | g.drawOval((int) (scale * (position.x - radius)), (int) (scale * (position.y - radius)), diameter, diameter); 49 | 50 | // if (response.isCollides()) { 51 | // g.setColor(Color.RED); 52 | // int x1 = (int) (scale * response.getContactPoint().x); 53 | // int y1 = (int) (scale * response.getContactPoint().y); 54 | // int x2 = (int) (scale * (response.getContactPoint().x + response.getContactNormal().x)); 55 | // int y2 = (int) (scale * (response.getContactPoint().y + response.getContactNormal().y)); 56 | // g.drawLine(x1, y1, x2, y2); 57 | // } 58 | } 59 | 60 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 61 | Camera.da.set(position); 62 | Camera.da.sub(translate); 63 | Camera.da.rotateY(-angle); 64 | Camera.da.scale(scale); 65 | Camera.da.add(Camera.camera); 66 | 67 | Camera.db.set(position); 68 | Camera.db.sub(translate); 69 | Camera.db.rotateY(-angle); 70 | Camera.db.y -= radius; 71 | Camera.db.scale(scale); 72 | Camera.db.add(Camera.camera); 73 | 74 | 75 | // double ax = scale * (position.x - radius + translate.x); 76 | // double ay = scale * (position.y - radius + translate.y); 77 | // double ax2 = scale * (position.x + radius + translate.x); 78 | // double ay2 = scale * (position.y + radius + translate.y); 79 | // double az = scale * (position.z + translate.z); 80 | 81 | int sax = (int) (500 * (Camera.da.x / -Camera.da.z)); 82 | int say = (int) (500 * (Camera.da.y / -Camera.da.z)); 83 | int sax2 = (int) (500 * (Camera.db.x / -Camera.da.z)); 84 | int say2 = (int) (500 * (Camera.db.y / -Camera.da.z)); 85 | int sr = Math.abs(sax - sax2); // screen radius 86 | 87 | g.setColor(Color.BLACK); 88 | int radius = Math.abs(say - say2); 89 | int diameter = radius * 2; 90 | g.drawOval(sax - radius, say - radius, diameter, diameter); 91 | 92 | // draw contact point 93 | 94 | } 95 | 96 | @Override 97 | public String toString() { 98 | return "Sphere{" + "radius=" + radius + ", position=" + position + '}'; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/physics/Vec3.java: -------------------------------------------------------------------------------- 1 | package physics; 2 | 3 | 4 | 5 | /** 6 | * class Vec3. 7 | * 8 | * @author Leonardo Ono (ono.leo80@gmail.com) 9 | */ 10 | public class Vec3 { 11 | 12 | public double x; 13 | public double y; 14 | public double z; 15 | 16 | public Vec3() { 17 | } 18 | 19 | public Vec3(double x, double y, double z) { 20 | this.x = x; 21 | this.y = y; 22 | this.z = z; 23 | } 24 | 25 | public Vec3(Vec3 v) { 26 | this.x = v.x; 27 | this.y = v.y; 28 | this.z = v.z; 29 | } 30 | 31 | public Vec3(Vec3 a, Vec3 b) { 32 | this.x = b.x - a.x; 33 | this.y = b.y - a.y; 34 | this.z = b.z - a.z; 35 | } 36 | 37 | public void set(double x, double y, double z) { 38 | this.x = x; 39 | this.y = y; 40 | this.z = z; 41 | } 42 | 43 | public void set(Vec3 v) { 44 | this.x = v.x; 45 | this.y = v.y; 46 | this.z = v.z; 47 | } 48 | 49 | public void add(Vec3 v) { 50 | this.x += v.x; 51 | this.y += v.y; 52 | this.z += v.z; 53 | } 54 | 55 | public void sub(Vec3 v) { 56 | this.x -= v.x; 57 | this.y -= v.y; 58 | this.z -= v.z; 59 | } 60 | 61 | public void scale(double s) { 62 | scale(s, s, s); 63 | } 64 | 65 | public void scale(double sx, double sy, double sz) { 66 | this.x *= sx; 67 | this.y *= sy; 68 | this.z *= sz; 69 | } 70 | 71 | public double getLength() { 72 | return Math.sqrt(x * x + y * y + z * z); 73 | } 74 | 75 | public void normalize() { 76 | double length = getLength(); 77 | if (length != 0) { 78 | x /= length; 79 | y /= length; 80 | z /= length; 81 | } 82 | } 83 | 84 | public double dot(Vec3 v) { 85 | return x * v.x + y * v.y + z * v.z; 86 | } 87 | 88 | public double dot2D(Vec3 v) { 89 | return x * v.x + z * v.z; 90 | } 91 | 92 | public void cross(Vec3 v) { 93 | double cx = y * v.z - z * v.y; 94 | double cy = z * v.x - x * v.z; 95 | double cz = x * v.y - y * v.x; 96 | x = cx; 97 | y = cy; 98 | z = cz; 99 | } 100 | 101 | public double cross2D(Vec3 v) { 102 | return x * v.z - z * v.x; 103 | } 104 | 105 | public void rotateY(double angle) { 106 | double s = Math.sin(angle); 107 | double c = Math.cos(angle); 108 | double nx = x * c - z * s; 109 | double nz = x * s + z * c; 110 | set(nx, y, nz); 111 | } 112 | @Override 113 | public String toString() { 114 | return "Vec3{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/res/terrain.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/res/terrain.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.80 (sub 75) OBJ File: '' 2 | # www.blender.org 3 | mtllib terrain.mtl 4 | o Plane 5 | v -1.000107 0.141320 -1.010149 6 | v -0.857380 0.138740 -1.010383 7 | v -0.714332 0.142291 -1.010056 8 | v -0.571429 0.143263 -1.009969 9 | v -0.428571 0.143263 -1.009969 10 | v -0.285714 0.143263 -1.009969 11 | v -0.142857 0.143263 -1.009969 12 | v 0.000000 0.143263 -1.009969 13 | v 0.142857 0.143263 -1.009969 14 | v 0.285714 0.143263 -1.009969 15 | v 0.428571 0.143263 -1.009969 16 | v 0.571429 0.143263 -1.009969 17 | v 0.714332 0.142291 -1.010056 18 | v 0.857380 0.138740 -1.010383 19 | v 1.000107 0.141320 -1.010149 20 | v -1.001998 0.115367 -0.869893 21 | v -0.859781 0.106295 -0.870795 22 | v -0.715016 0.130706 -0.868293 23 | v -0.571434 0.143153 -0.867122 24 | v -0.428570 0.143239 -0.867115 25 | v -0.285682 0.142595 -0.867139 26 | v -0.142804 0.142089 -0.867156 27 | v 0.144469 0.338372 -0.863633 28 | v 0.142805 0.142089 -0.867156 29 | v 0.285682 0.142595 -0.867139 30 | v 0.428570 0.143240 -0.867115 31 | v 0.571434 0.143153 -0.867122 32 | v 0.715016 0.130706 -0.868293 33 | v 0.859781 0.106295 -0.870795 34 | v 1.001998 0.115367 -0.869893 35 | v -1.005888 0.083175 -0.730757 36 | v -0.864697 0.067412 -0.732410 37 | v -0.716947 0.110085 -0.727970 38 | v -0.571285 0.134961 -0.725482 39 | v -0.427828 0.132534 -0.725426 40 | v -0.285017 0.131607 -0.724928 41 | v -0.142518 0.136413 -0.724533 42 | v 0.144521 0.339545 -1.006446 43 | v 0.142518 0.136413 -0.724533 44 | v 0.285009 0.131482 -0.724937 45 | v 0.427830 0.132402 -0.725497 46 | v 0.571365 0.134974 -0.725484 47 | v 0.716949 0.110081 -0.727959 48 | v 0.864697 0.067412 -0.732410 49 | v 1.005888 0.083175 -0.730757 50 | v -1.009614 0.074277 -0.588705 51 | v -0.871050 0.036642 -0.592421 52 | v -0.721471 0.058233 -0.590628 53 | v -0.570636 0.043698 -0.593775 54 | v -0.425717 0.070379 -0.583463 55 | v -0.284768 0.122824 -0.581938 56 | v -0.142450 0.135560 -0.581737 57 | v 0.000000 0.142092 -0.581442 58 | v 0.142449 0.135543 -0.581737 59 | v 0.284676 0.122686 -0.581941 60 | v 0.426192 0.070198 -0.583174 61 | v 0.571534 0.043887 -0.593970 62 | v 0.721490 0.058311 -0.590869 63 | v 0.871051 0.036642 -0.592421 64 | v 1.009614 0.074277 -0.588705 65 | v -1.011588 0.071148 -0.442560 66 | v -0.874202 -0.002128 -0.445229 67 | v -0.723843 0.000691 -0.444881 68 | v -0.580406 -0.023302 -0.426794 69 | v -0.467227 -0.028660 -0.358962 70 | v -0.306562 0.098198 -0.400698 71 | v -0.142864 0.142736 -0.438503 72 | v 0.000000 0.143263 -0.438541 73 | v 0.142864 0.142736 -0.438503 74 | v 0.306547 0.098287 -0.400625 75 | v 0.467552 -0.028839 -0.357853 76 | v 0.580044 -0.023407 -0.426750 77 | v 0.723986 0.000703 -0.445140 78 | v 0.874214 -0.002124 -0.445245 79 | v 1.011588 0.071148 -0.442560 80 | v -1.012095 0.060197 -0.295017 81 | v -0.873022 -0.006817 -0.295930 82 | v -0.722065 0.005625 -0.296347 83 | v -0.585615 -0.005679 -0.267487 84 | v -0.473788 -0.013776 -0.206902 85 | v -0.311734 0.094703 -0.249749 86 | v -0.142932 0.143166 -0.295552 87 | v 0.000000 0.143263 -0.295684 88 | v 0.142932 0.143166 -0.295552 89 | v 0.311738 0.094700 -0.249748 90 | v 0.473749 -0.013759 -0.206912 91 | v 0.585347 -0.005637 -0.266830 92 | v 0.722010 0.005671 -0.296139 93 | v 0.873021 -0.006817 -0.295931 94 | v 1.012095 0.060197 -0.295017 95 | v -1.011561 0.076741 -0.149068 96 | v -0.871190 0.031949 -0.148895 97 | v -0.718397 0.039046 -0.149523 98 | v -0.570892 0.018139 -0.147965 99 | v -0.428858 0.045194 -0.134956 100 | v -0.288854 0.125490 -0.147140 101 | v -0.142969 0.143279 -0.152767 102 | v 0.000000 0.143263 -0.152826 103 | v 0.142969 0.143279 -0.152767 104 | v 0.288869 0.125485 -0.147136 105 | v 0.428831 0.045148 -0.135125 106 | v 0.571156 0.018155 -0.148216 107 | v 0.718389 0.039047 -0.149496 108 | v 0.871190 0.031949 -0.148895 109 | v 1.011561 0.076741 -0.149068 110 | v -1.011045 0.079246 -0.005020 111 | v -0.868969 0.065325 -0.004143 112 | v -0.716574 0.026902 -0.004497 113 | v -0.567083 -0.021347 -0.002567 114 | v -0.419790 0.055889 -0.000830 115 | v -0.294779 0.123322 -0.002164 116 | v -0.152142 0.136961 0.002706 117 | v 0.000000 0.140839 -0.004346 118 | v 0.152143 0.136961 0.002706 119 | v 0.294930 0.123285 -0.002125 120 | v 0.419543 0.055983 -0.000297 121 | v 0.567024 -0.021347 -0.002541 122 | v 0.716576 0.026903 -0.004501 123 | v 0.868969 0.065325 -0.004143 124 | v 1.011045 0.079246 -0.005020 125 | v -1.008924 0.076345 0.137132 126 | v -0.866130 0.070898 0.137336 127 | v -0.716660 0.024674 0.136465 128 | v -0.565500 -0.027092 0.136527 129 | v -0.422555 0.036778 0.133025 130 | v -0.304860 0.082266 0.151191 131 | v -0.163224 0.112614 0.165833 132 | v 0.000000 0.126638 0.166872 133 | v 0.163231 0.112608 0.165847 134 | v 0.305457 0.082155 0.151159 135 | v 0.422642 0.036494 0.133584 136 | v 0.565214 -0.027108 0.136681 137 | v 0.716660 0.024674 0.136465 138 | v 0.866130 0.070898 0.137336 139 | v 1.008924 0.076345 0.137132 140 | v -1.006474 0.076515 0.278437 141 | v -0.863640 0.074971 0.278432 142 | v -0.717510 0.042936 0.274628 143 | v -0.571112 -0.035217 0.273764 144 | v -0.428332 -0.033307 0.275141 145 | v -0.288106 -0.016147 0.284295 146 | v -0.152130 0.018126 0.301454 147 | v 0.000000 0.044177 0.292955 148 | v 0.152136 0.018110 0.301492 149 | v 0.288572 -0.016159 0.284224 150 | v 0.428234 -0.033123 0.274249 151 | v 0.571007 -0.035236 0.273660 152 | v 0.717501 0.042929 0.274630 153 | v 0.863640 0.074971 0.278432 154 | v 1.006474 0.076515 0.278437 155 | v -1.004686 0.078496 0.420568 156 | v -0.862583 0.062683 0.421031 157 | v -0.718035 0.066362 0.417947 158 | v -0.579412 0.011215 0.420401 159 | v -0.452164 -0.015242 0.426836 160 | v -0.302243 -0.016380 0.430103 161 | v -0.141963 0.005010 0.425426 162 | v 0.000000 0.010677 0.423636 163 | v 0.141969 0.005009 0.425421 164 | v 0.301931 -0.016438 0.429915 165 | v 0.451886 -0.015472 0.426256 166 | v 0.579586 0.010924 0.419780 167 | v 0.718147 0.066398 0.417948 168 | v 0.862587 0.062681 0.421039 169 | v 1.004686 0.078496 0.420568 170 | v -1.003795 0.072808 0.563598 171 | v -0.863154 0.006607 0.565566 172 | v -0.719045 0.027143 0.564649 173 | v -0.577379 0.083315 0.564445 174 | v -0.454616 0.103690 0.565073 175 | v -0.311729 0.104871 0.563666 176 | v -0.147715 0.098976 0.563348 177 | v 0.000000 0.095536 0.563204 178 | v 0.147715 0.098976 0.563348 179 | v 0.311714 0.104869 0.563661 180 | v 0.454458 0.103778 0.565277 181 | v 0.577869 0.083292 0.565251 182 | v 0.719403 0.026931 0.564805 183 | v 0.863152 0.006614 0.565547 184 | v 1.003795 0.072808 0.563598 185 | v -1.002562 0.071491 0.706283 186 | v -0.862586 -0.027034 0.709170 187 | v -0.719536 -0.036777 0.710082 188 | v -0.574332 0.020511 0.710512 189 | v -0.434268 0.075765 0.708857 190 | v -0.291616 0.116975 0.705873 191 | v -0.143185 0.139918 0.704457 192 | v 0.000000 0.143242 0.704317 193 | v 0.143185 0.139918 0.704457 194 | v 0.291616 0.116975 0.705873 195 | v 0.434265 0.075759 0.708868 196 | v 0.574361 0.020426 0.710646 197 | v 0.719550 -0.036785 0.710105 198 | v 0.862598 -0.027030 0.709164 199 | v 1.002562 0.071491 0.706283 200 | v -1.000849 0.108450 0.847996 201 | v -0.860393 0.016942 0.850572 202 | v -0.718155 -0.016082 0.852748 203 | v -0.574392 -0.004258 0.855333 204 | v -0.430379 0.002374 0.855610 205 | v -0.286326 0.039284 0.852525 206 | v -0.142921 0.106155 0.848703 207 | v 0.000000 0.139406 0.847326 208 | v 0.142921 0.106155 0.848703 209 | v 0.286326 0.039284 0.852525 210 | v 0.430379 0.002374 0.855610 211 | v 0.574390 -0.004258 0.855333 212 | v 0.718152 -0.016080 0.852754 213 | v 0.860394 0.016943 0.850573 214 | v 1.000849 0.108450 0.847996 215 | v -1.000059 0.140342 0.990097 216 | v -0.857651 0.118888 0.990646 217 | v -0.715381 0.092078 0.992101 218 | v -0.572904 0.061323 0.994770 219 | v -0.429678 0.031493 0.996203 220 | v -0.286106 0.048108 0.994489 221 | v -0.142899 0.102094 0.991615 222 | v 0.000000 0.137218 0.990271 223 | v 0.142899 0.102093 0.991615 224 | v 0.286106 0.048108 0.994489 225 | v 0.429678 0.031493 0.996203 226 | v 0.572904 0.061323 0.994770 227 | v 0.715381 0.092078 0.992101 228 | v 0.857651 0.118888 0.990646 229 | v 1.000059 0.140342 0.990097 230 | v -0.142857 0.143263 -1.009969 231 | v -0.142804 0.142089 -0.867156 232 | v 0.000000 0.143263 -1.009969 233 | v 0.004425 0.483166 -0.859659 234 | v 0.142857 0.143263 -1.009969 235 | v 0.142805 0.142089 -0.867156 236 | v -0.142518 0.136413 -0.724533 237 | v 0.147229 0.482204 -0.859696 238 | v 0.142518 0.136413 -0.724533 239 | v -0.142450 0.135560 -0.581737 240 | v 0.000000 0.142092 -0.581442 241 | v 0.142449 0.135543 -0.581737 242 | v 0.287378 0.339545 -1.006446 243 | v 0.287346 0.338877 -0.863616 244 | v 0.144182 0.332695 -0.721009 245 | v 0.286673 0.327764 -0.721413 246 | v 0.144113 0.331825 -0.578214 247 | v 0.286340 0.318968 -0.578418 248 | v -0.141193 0.339545 -1.006446 249 | v -0.141140 0.338372 -0.863633 250 | v 0.001664 0.339545 -1.006446 251 | v 0.001664 0.339334 -0.863597 252 | v 0.144521 0.339545 -1.006446 253 | v 0.144469 0.338372 -0.863633 254 | v -0.140854 0.332695 -0.721009 255 | v 0.001664 0.337203 -0.720819 256 | v 0.144182 0.332695 -0.721009 257 | v -0.140786 0.331842 -0.578213 258 | v 0.001664 0.338374 -0.577919 259 | v 0.144113 0.331825 -0.578214 260 | v 0.004425 0.481036 -0.716882 261 | v 0.146943 0.476528 -0.717072 262 | v 0.557680 0.535055 -0.946619 263 | v 0.557685 0.534945 -0.803772 264 | v 0.700584 0.534083 -0.946706 265 | v 0.701267 0.522498 -0.804943 266 | v 0.843631 0.530532 -0.947033 267 | v 0.846032 0.498087 -0.807445 268 | v 0.986359 0.533111 -0.946799 269 | v 0.988250 0.507159 -0.806543 270 | v 0.850948 0.459204 -0.669059 271 | v 0.992140 0.474967 -0.667407 272 | v 0.857302 0.428434 -0.529071 273 | v 0.995866 0.466069 -0.525355 274 | vt 0.000000 0.000000 275 | vt 0.071429 0.071429 276 | vt 0.000000 0.071429 277 | vt 0.071429 0.000000 278 | vt 0.142857 0.071429 279 | vt 0.214286 0.000000 280 | vt 0.142857 0.000000 281 | vt 0.285714 0.000000 282 | vt 0.214286 0.071429 283 | vt 0.357143 0.000000 284 | vt 0.285714 0.071429 285 | vt 0.428571 0.000000 286 | vt 0.357143 0.071429 287 | vt 0.571429 0.000000 288 | vt 0.571429 0.071429 289 | vt 0.571429 0.000000 290 | vt 0.571429 0.142857 291 | vt 0.571429 0.214286 292 | vt 0.571429 0.142857 293 | vt 0.571429 0.071429 294 | vt 0.571429 0.000000 295 | vt 0.571429 0.071429 296 | vt 0.642857 0.000000 297 | vt 0.714286 0.071429 298 | vt 0.642857 0.071429 299 | vt 0.714286 0.000000 300 | vt 0.785714 0.071429 301 | vt 0.928572 0.142857 302 | vt 0.928572 0.214286 303 | vt 0.928572 0.214286 304 | vt 0.857143 0.071429 305 | vt 0.928572 0.071429 306 | vt 0.928572 0.071429 307 | vt 0.785714 0.000000 308 | vt 0.785714 0.071429 309 | vt 0.071429 0.142857 310 | vt 0.000000 0.142857 311 | vt 0.142857 0.142857 312 | vt 0.214286 0.142857 313 | vt 0.285714 0.142857 314 | vt 0.428571 0.071429 315 | vt 0.357143 0.142857 316 | vt 0.000000 0.000000 317 | vt 0.000000 0.000000 318 | vt 0.000000 0.000000 319 | vt 0.000000 0.000000 320 | vt 0.000000 0.000000 321 | vt 0.571429 0.142857 322 | vt 0.571429 0.071429 323 | vt 0.714286 0.142857 324 | vt 0.642857 0.142857 325 | vt 0.785714 0.142857 326 | vt 0.857143 0.142857 327 | vt 1.000000 0.214286 328 | vt 1.000000 0.214286 329 | vt 0.071429 0.214286 330 | vt 0.000000 0.214286 331 | vt 0.142857 0.214286 332 | vt 0.214286 0.214286 333 | vt 0.285714 0.214286 334 | vt 0.357143 0.214286 335 | vt 0.428571 0.142857 336 | vt 0.428571 0.214286 337 | vt 0.428571 0.142857 338 | vt 0.428571 0.214286 339 | vt 0.500000 0.214286 340 | vt 0.500000 0.214286 341 | vt 0.642857 0.214286 342 | vt 0.642857 0.142857 343 | vt 0.642857 0.214286 344 | vt 0.714286 0.214286 345 | vt 0.785714 0.214286 346 | vt 0.857143 0.214286 347 | vt 0.000000 0.000000 348 | vt 0.000000 0.000000 349 | vt 0.000000 0.000000 350 | vt 0.000000 0.285714 351 | vt 0.142857 0.285714 352 | vt 0.071429 0.285714 353 | vt 0.214286 0.285714 354 | vt 0.357143 0.285714 355 | vt 0.285714 0.285714 356 | vt 0.428571 0.285714 357 | vt 0.571429 0.285714 358 | vt 0.500000 0.285714 359 | vt 0.571429 0.214286 360 | vt 0.642857 0.285714 361 | vt 0.785714 0.285714 362 | vt 0.714286 0.285714 363 | vt 0.857143 0.285714 364 | vt 1.000000 0.285714 365 | vt 0.928572 0.285714 366 | vt 0.000000 0.357143 367 | vt 0.071429 0.357143 368 | vt 0.142857 0.357143 369 | vt 0.214286 0.357143 370 | vt 0.357143 0.357143 371 | vt 0.285714 0.357143 372 | vt 0.428571 0.357143 373 | vt 0.500000 0.357143 374 | vt 0.571429 0.357143 375 | vt 0.642857 0.357143 376 | vt 0.785714 0.357143 377 | vt 0.714286 0.357143 378 | vt 0.857143 0.357143 379 | vt 0.928572 0.357143 380 | vt 1.000000 0.357143 381 | vt 0.071429 0.428571 382 | vt 0.000000 0.428571 383 | vt 0.142857 0.428571 384 | vt 0.214286 0.428571 385 | vt 0.285714 0.428571 386 | vt 0.428571 0.428571 387 | vt 0.357143 0.428571 388 | vt 0.500000 0.428571 389 | vt 0.571429 0.428571 390 | vt 0.714286 0.428571 391 | vt 0.642857 0.428571 392 | vt 0.785714 0.428571 393 | vt 0.857143 0.428571 394 | vt 0.928572 0.428571 395 | vt 0.071429 0.500000 396 | vt 0.000000 0.500000 397 | vt 0.142857 0.500000 398 | vt 0.214286 0.500000 399 | vt 0.357143 0.500000 400 | vt 0.285714 0.500000 401 | vt 0.428571 0.500000 402 | vt 0.500000 0.500000 403 | vt 0.571429 0.500000 404 | vt 0.642857 0.500000 405 | vt 0.785714 0.500000 406 | vt 0.714286 0.500000 407 | vt 0.857143 0.500000 408 | vt 0.928572 0.500000 409 | vt 1.000000 0.428571 410 | vt 0.000000 0.571429 411 | vt 0.071429 0.571429 412 | vt 0.142857 0.571429 413 | vt 0.285714 0.571429 414 | vt 0.214286 0.571429 415 | vt 0.357143 0.571429 416 | vt 0.428571 0.571429 417 | vt 0.500000 0.571429 418 | vt 0.571429 0.571429 419 | vt 0.642857 0.571429 420 | vt 0.714286 0.571429 421 | vt 0.857143 0.571429 422 | vt 0.785714 0.571429 423 | vt 0.928572 0.571429 424 | vt 1.000000 0.571429 425 | vt 0.000000 0.642857 426 | vt 0.142857 0.642857 427 | vt 0.071429 0.642857 428 | vt 0.214286 0.642857 429 | vt 0.285714 0.642857 430 | vt 0.357143 0.642857 431 | vt 0.500000 0.642857 432 | vt 0.428571 0.642857 433 | vt 0.642857 0.642857 434 | vt 0.571429 0.642857 435 | vt 0.714286 0.642857 436 | vt 0.785714 0.642857 437 | vt 0.857143 0.642857 438 | vt 1.000000 0.642857 439 | vt 0.928572 0.642857 440 | vt 0.000000 0.714286 441 | vt 0.142857 0.714286 442 | vt 0.071429 0.714286 443 | vt 0.214286 0.714286 444 | vt 0.285714 0.714286 445 | vt 0.357143 0.714286 446 | vt 0.500000 0.714286 447 | vt 0.428571 0.714286 448 | vt 0.642857 0.714286 449 | vt 0.571429 0.714286 450 | vt 0.714286 0.714286 451 | vt 0.785714 0.714286 452 | vt 0.857143 0.714286 453 | vt 1.000000 0.714286 454 | vt 0.928572 0.714286 455 | vt 0.000000 0.785714 456 | vt 0.142857 0.785714 457 | vt 0.071429 0.785714 458 | vt 0.214286 0.785714 459 | vt 0.357143 0.785714 460 | vt 0.285714 0.785714 461 | vt 0.428571 0.785714 462 | vt 0.500000 0.785714 463 | vt 0.571429 0.785714 464 | vt 0.642857 0.785714 465 | vt 0.785714 0.785714 466 | vt 0.714286 0.785714 467 | vt 0.857143 0.785714 468 | vt 1.000000 0.785714 469 | vt 0.928572 0.785714 470 | vt 0.000000 0.857143 471 | vt 0.142857 0.857143 472 | vt 0.071429 0.857143 473 | vt 0.214286 0.857143 474 | vt 0.285714 0.857143 475 | vt 0.357143 0.857143 476 | vt 0.428571 0.857143 477 | vt 0.571429 0.857143 478 | vt 0.500000 0.857143 479 | vt 0.642857 0.857143 480 | vt 0.714286 0.857143 481 | vt 0.785714 0.857143 482 | vt 0.857143 0.857143 483 | vt 1.000000 0.857143 484 | vt 0.928572 0.857143 485 | vt 0.071429 0.928572 486 | vt 0.000000 0.928572 487 | vt 0.142857 0.928572 488 | vt 0.285714 0.928572 489 | vt 0.214286 0.928572 490 | vt 0.357143 0.928572 491 | vt 0.428571 0.928572 492 | vt 0.500000 0.928572 493 | vt 0.571429 0.928572 494 | vt 0.642857 0.928572 495 | vt 0.714286 0.928572 496 | vt 0.857143 0.928572 497 | vt 0.785714 0.928572 498 | vt 0.928572 0.928572 499 | vt 0.071429 1.000000 500 | vt 0.000000 1.000000 501 | vt 0.142857 1.000000 502 | vt 0.214286 1.000000 503 | vt 0.285714 1.000000 504 | vt 0.428571 1.000000 505 | vt 0.357143 1.000000 506 | vt 0.500000 1.000000 507 | vt 0.571429 1.000000 508 | vt 0.714286 1.000000 509 | vt 0.642857 1.000000 510 | vt 0.785714 1.000000 511 | vt 0.857143 1.000000 512 | vt 1.000000 0.928572 513 | vt 0.928572 1.000000 514 | vt 0.571429 0.214286 515 | vt 0.000000 0.000000 516 | vt 0.571429 0.142857 517 | vt 0.428571 0.071429 518 | vt 0.428571 0.000000 519 | vt 0.428571 0.071429 520 | vt 0.571429 0.214286 521 | vt 0.428571 0.000000 522 | vt 0.642857 0.071429 523 | vt 0.500000 0.000000 524 | vt 0.500000 0.071429 525 | vt 0.428571 0.142857 526 | vt 0.571429 0.142857 527 | vt 0.571429 0.071429 528 | vt 0.500000 0.142857 529 | vt 0.428571 0.214286 530 | vt 0.500000 0.214286 531 | vt 0.000000 0.000000 532 | vt 0.000000 0.000000 533 | vt 0.000000 0.000000 534 | vt 0.000000 0.000000 535 | vt 0.571429 0.000000 536 | vt 0.642857 0.000000 537 | vt 0.500000 0.071429 538 | vt 0.500000 0.142857 539 | vt 0.857143 0.071429 540 | vt 0.928572 0.000000 541 | vt 0.857143 0.000000 542 | vt 1.000000 0.000000 543 | vt 1.000000 0.071429 544 | vt 0.928572 0.142857 545 | vt 1.000000 0.142857 546 | vt 0.000000 0.000000 547 | vt 0.000000 0.000000 548 | vt 0.000000 0.000000 549 | vt 0.000000 0.000000 550 | vt 0.000000 0.000000 551 | vt 0.000000 0.000000 552 | vt 0.000000 0.000000 553 | vt 0.000000 0.000000 554 | vt 0.000000 0.000000 555 | vt 0.000000 0.000000 556 | vt 0.785714 0.000000 557 | vt 0.000000 0.000000 558 | vt 1.000000 0.500000 559 | vt 1.000000 1.000000 560 | vt 0.000000 0.000000 561 | vt 0.000000 0.000000 562 | vn -0.0637 -0.9812 -0.1824 563 | vn 0.1659 -0.9612 -0.2206 564 | vn 0.0068 -0.9967 -0.0814 565 | vn 0.0000 -1.0000 -0.0008 566 | vn 0.0000 -1.0000 -0.0002 567 | vn 0.0000 -1.0000 -0.0047 568 | vn 0.0000 0.0000 1.0000 569 | vn 1.0000 -0.0085 0.0003 570 | vn 0.0045 -1.0000 -0.0047 571 | vn -0.0006 -1.0000 -0.0002 572 | vn 0.9985 0.0409 -0.0363 573 | vn 0.0099 0.1600 -0.9871 574 | vn 0.9994 0.0351 -0.0000 575 | vn -0.1107 -0.9676 -0.2270 576 | vn 0.2755 -0.9280 -0.2509 577 | vn 0.1690 -0.9755 -0.1410 578 | vn 0.0006 -0.9983 -0.0577 579 | vn -0.0045 -0.9971 -0.0753 580 | vn -0.0035 -0.9970 -0.0770 581 | vn -1.0000 0.0085 -0.0017 582 | vn 0.0061 -0.9969 -0.0779 583 | vn 0.0179 -0.9969 -0.0762 584 | vn -0.0867 -0.9946 -0.0575 585 | vn -0.1670 -0.9758 -0.1411 586 | vn -0.0167 0.1590 -0.9871 587 | vn -0.2632 -0.9624 -0.0672 588 | vn 0.1422 -0.9681 -0.2063 589 | vn -0.0970 -0.9301 -0.3543 590 | vn 0.1884 -0.8068 -0.5600 591 | vn 0.3257 -0.8643 -0.3833 592 | vn 0.0338 -0.9975 -0.0613 593 | vn -1.0000 0.0085 -0.0018 594 | vn 0.0062 -0.9981 -0.0614 595 | vn 0.0165 -0.9162 -0.4003 596 | vn -0.1486 -0.8130 -0.5629 597 | vn -0.2709 -0.9035 -0.3322 598 | vn -0.9990 -0.0389 0.0238 599 | vn -0.2626 -0.9646 -0.0242 600 | vn 0.0187 -0.9669 -0.2543 601 | vn -0.0968 -0.9252 -0.3669 602 | vn 0.1936 -0.9144 -0.3556 603 | vn 0.5607 -0.7908 -0.2452 604 | vn 0.2391 -0.9656 -0.1025 605 | vn 0.0456 -0.9977 0.0501 606 | vn -0.0037 -1.0000 0.0082 607 | vn -0.0898 -0.9947 0.0502 608 | vn -0.3472 -0.9341 -0.0838 609 | vn -0.1811 -0.9121 -0.3677 610 | vn 0.1062 -0.9206 -0.3759 611 | vn -0.1373 -0.9220 -0.3621 612 | vn 0.4610 -0.8556 -0.2353 613 | vn -0.4706 -0.8798 -0.0669 614 | vn 0.0188 -0.9993 -0.0315 615 | vn -0.1691 -0.9850 0.0347 616 | vn -0.1101 -0.9883 0.1057 617 | vn 0.5721 -0.8135 0.1043 618 | vn 0.2727 -0.9620 -0.0129 619 | vn 0.0007 -1.0000 0.0030 620 | vn -0.0037 -1.0000 0.0000 621 | vn -0.2627 -0.9649 0.0030 622 | vn -0.6201 -0.7845 0.0027 623 | vn 0.1222 -0.9881 0.0937 624 | vn 0.1046 -0.9888 0.1064 625 | vn -0.0824 -0.9961 0.0321 626 | vn 0.4341 -0.9005 -0.0248 627 | vn -0.3023 -0.9470 0.1085 628 | vn 0.0802 -0.9641 0.2532 629 | vn -0.1273 -0.9664 0.2232 630 | vn -0.1854 -0.9591 0.2140 631 | vn 0.5838 -0.7676 0.2646 632 | vn 0.1268 -0.9575 0.2590 633 | vn -0.0001 -1.0000 0.0008 634 | vn -0.0007 -1.0000 0.0000 635 | vn -0.2762 -0.9611 0.0008 636 | vn -0.5019 -0.8529 0.1440 637 | vn -0.0967 -0.7982 0.5945 638 | vn 0.1391 -0.9676 0.2107 639 | vn -0.0461 -0.9743 0.2206 640 | vn 0.4205 -0.8760 0.2362 641 | vn -0.0976 -0.9951 0.0177 642 | vn 0.0461 -0.9736 0.2238 643 | vn -0.1390 -0.9870 -0.0809 644 | vn 0.2037 -0.9435 -0.2616 645 | vn 0.4747 -0.8793 0.0380 646 | vn 0.0955 -0.9954 -0.0110 647 | vn 0.0236 -0.9990 -0.0392 648 | vn 0.0001 -0.9999 -0.0163 649 | vn -0.1197 -0.9922 -0.0333 650 | vn -0.4983 -0.8670 0.0077 651 | vn -0.4635 -0.8852 0.0392 652 | vn 0.2950 -0.9243 -0.2423 653 | vn 0.2439 -0.9667 -0.0779 654 | vn 0.2969 -0.9295 0.2189 655 | vn -0.0974 -0.9951 -0.0189 656 | vn -0.2442 -0.9688 0.0431 657 | vn -0.3069 -0.9516 -0.0152 658 | vn 0.4067 -0.9126 -0.0423 659 | vn 0.3743 -0.9191 -0.1235 660 | vn 0.2270 -0.9444 -0.2379 661 | vn 0.0856 -0.9862 -0.1414 662 | vn -0.0216 -0.9963 -0.0826 663 | vn -0.0991 -0.9851 -0.1403 664 | vn -0.4634 -0.8633 -0.1998 665 | vn -0.4626 -0.8788 -0.1172 666 | vn 0.3233 -0.9457 -0.0349 667 | vn 0.2955 -0.9552 -0.0153 668 | vn 0.0381 -0.9985 0.0401 669 | vn -0.0381 -0.9993 0.0019 670 | vn -0.2132 -0.9765 0.0319 671 | vn -0.4674 -0.8768 0.1130 672 | vn 0.0139 -0.9982 -0.0585 673 | vn 0.1373 -0.8906 -0.4336 674 | vn 0.2266 -0.7693 -0.5973 675 | vn 0.1069 -0.8117 -0.5742 676 | vn -0.0752 -0.8345 -0.5458 677 | vn -0.2675 -0.7802 -0.5654 678 | vn -0.3695 -0.7243 -0.5821 679 | vn -0.3659 -0.8398 -0.4011 680 | vn 0.3227 -0.9440 -0.0697 681 | vn 0.2925 -0.9482 0.1235 682 | vn 0.0108 -0.9995 0.0290 683 | vn -0.0108 -0.9998 0.0141 684 | vn 0.0235 -0.9960 -0.0860 685 | vn -0.3678 -0.9179 0.1487 686 | vn -0.2089 -0.9357 0.2844 687 | vn -0.0101 -0.9931 0.1167 688 | vn 0.2418 -0.9701 0.0219 689 | vn 0.0383 -0.9934 -0.1082 690 | vn -0.1503 -0.9577 -0.2455 691 | vn -0.1288 -0.9850 -0.1147 692 | vn -0.1199 -0.9927 0.0091 693 | vn -0.0142 -0.9930 0.1175 694 | vn 0.4553 -0.8563 0.2438 695 | vn 0.2076 -0.9655 0.1572 696 | vn 0.1099 -0.9903 -0.0845 697 | vn -0.1104 -0.9931 -0.0388 698 | vn 0.1295 -0.9246 -0.3582 699 | vn -0.3548 -0.9026 -0.2437 700 | vn -0.2041 -0.8743 0.4405 701 | vn 0.0127 -0.7579 0.6523 702 | vn -0.0253 -0.7411 0.6710 703 | vn -0.0187 -0.8266 0.5624 704 | vn -0.0406 -0.8538 0.5191 705 | vn -0.1254 -0.8175 0.5622 706 | vn 0.0211 -0.7413 0.6708 707 | vn -0.1247 -0.7520 0.6473 708 | vn -0.3352 -0.8451 0.4165 709 | vn -0.0193 -0.9656 -0.2593 710 | vn 0.3977 -0.8549 -0.3332 711 | vn -0.4258 -0.9048 -0.0047 712 | vn -0.0647 -0.9717 -0.2274 713 | vn 0.3408 -0.8611 -0.3773 714 | vn 0.3359 -0.8627 -0.3780 715 | vn 0.0062 -0.9815 -0.1915 716 | vn -0.0356 -0.9953 0.0898 717 | vn -0.0221 -0.9600 0.2792 718 | vn -0.0223 -0.9471 0.3202 719 | vn -0.1496 -0.9509 0.2711 720 | vn -0.2782 -0.9596 0.0424 721 | vn -0.1601 -0.9644 -0.2107 722 | vn -0.3433 -0.8590 -0.3797 723 | vn -0.1264 -0.9085 -0.3983 724 | vn 0.5629 -0.8052 -0.1865 725 | vn -0.5354 -0.8156 0.2192 726 | vn -0.2205 -0.9304 0.2928 727 | vn 0.3635 -0.9224 0.1303 728 | vn 0.0457 -0.9847 -0.1684 729 | vn 0.2138 -0.8714 -0.4415 730 | vn 0.3686 -0.8159 -0.4455 731 | vn 0.2189 -0.9500 -0.2228 732 | vn -0.0232 -0.9994 -0.0268 733 | vn -0.1467 -0.9631 -0.2257 734 | vn -0.2373 -0.8548 -0.4614 735 | vn -0.3270 -0.8417 -0.4296 736 | vn -0.0838 -0.9823 -0.1676 737 | vn 0.0683 -0.9872 0.1440 738 | vn 0.5602 -0.7885 0.2539 739 | vn -0.1462 -0.9651 0.2174 740 | vn -0.1562 -0.7972 0.5832 741 | vn -0.1787 -0.7755 0.6055 742 | vn -0.1891 -0.8878 0.4196 743 | vn 0.2474 -0.9490 0.1953 744 | vn 0.3532 -0.9338 0.0575 745 | vn 0.2384 -0.9708 -0.0276 746 | vn -0.2264 -0.9739 -0.0149 747 | vn -0.4219 -0.9063 -0.0258 748 | vn -0.1155 -0.9914 0.0614 749 | vn -0.0447 -0.9783 0.2024 750 | vn -0.0667 -0.9032 0.4241 751 | vn 0.1889 -0.7739 0.6045 752 | vn 0.4713 -0.7087 0.5250 753 | vn -0.0012 0.0180 -0.9998 754 | vn 0.0000 -0.0179 0.9998 755 | vn 1.0000 -0.0085 0.0017 756 | vn -1.0000 0.0085 -0.0004 757 | vn 1.0000 -0.0085 -0.0004 758 | vn 1.0000 -0.0085 0.0004 759 | vn 0.0035 -1.0000 -0.0082 760 | vn -0.0347 -0.9986 -0.0398 761 | vn -0.0900 -0.9959 -0.0061 762 | vn 0.0000 -1.0000 -0.0082 763 | vn -0.0067 -1.0000 -0.0015 764 | vn 0.0067 -0.9992 -0.0398 765 | vn -0.9998 0.0192 -0.0012 766 | vn 0.0316 -0.9995 -0.0060 767 | vn -0.0459 -0.9989 0.0082 768 | vn -1.0000 0.0086 -0.0041 769 | vn 0.0002 0.0179 -0.9998 770 | vn 1.0000 -0.0085 -0.0005 771 | vn -1.0000 0.0085 -0.0003 772 | vn -1.0000 0.0085 -0.0002 773 | vn 0.0012 0.0179 -0.9998 774 | vn 1.0000 -0.0084 -0.0023 775 | vn -0.0316 -0.9994 -0.0149 776 | vn 0.9998 -0.0192 -0.0003 777 | vn 0.0001 -0.0274 0.9996 778 | vn -0.0005 0.0274 -0.9996 779 | vn -0.0864 -0.9963 -0.0008 780 | vn -0.0249 -0.9964 -0.0813 781 | vn 0.0180 -0.9738 -0.2267 782 | vn 0.0630 -0.9602 -0.2720 783 | vn 0.1108 -0.9696 -0.2181 784 | vn -0.9991 -0.0381 0.0191 785 | vn 0.0058 0.1598 -0.9871 786 | vn 0.0013 -0.1596 0.9872 787 | vn -0.0017 -0.1597 0.9872 788 | vn -0.0005 -0.1596 0.9872 789 | vn 0.9989 0.0390 -0.0245 790 | vn -0.9993 -0.0362 0.0068 791 | vn -0.0180 -0.9738 -0.2267 792 | vn 0.0249 -0.9964 -0.0813 793 | vn 0.0864 -0.9963 -0.0008 794 | vn 0.0006 -1.0000 -0.0002 795 | vn -0.0045 -1.0000 -0.0047 796 | vn -0.0035 -1.0000 -0.0082 797 | vn -0.0630 -0.9602 -0.2720 798 | vn 0.1670 -0.9758 -0.1411 799 | vn 0.0867 -0.9946 -0.0576 800 | vn -0.0168 -0.9970 -0.0752 801 | vn -0.0062 -0.9970 -0.0770 802 | vn 0.0338 -0.9986 -0.0398 803 | vn 0.0045 -0.9971 -0.0763 804 | vn -0.0006 -0.9983 -0.0576 805 | vn -0.1692 -0.9754 -0.1410 806 | vn -0.2756 -0.9280 -0.2509 807 | vn -0.1108 -0.9696 -0.2181 808 | vn 0.2709 -0.9035 -0.3322 809 | vn 0.1484 -0.8125 -0.5637 810 | vn -0.0153 -0.9160 -0.4008 811 | vn -0.0063 -0.9981 -0.0613 812 | vn 0.0891 -0.9960 -0.0060 813 | vn -0.3243 -0.8654 -0.3820 814 | vn -0.1877 -0.8076 -0.5591 815 | vn 0.0968 -0.9301 -0.3544 816 | vn -0.1424 -0.9681 -0.2063 817 | vn -0.4610 -0.8557 -0.2353 818 | vn 0.1374 -0.9221 -0.3618 819 | vn -0.1066 -0.9206 -0.3756 820 | vn 0.1782 -0.9120 -0.3694 821 | vn 0.3483 -0.9335 -0.0850 822 | vn 0.0890 -0.9948 0.0501 823 | vn 0.0037 -1.0000 0.0082 824 | vn -0.0458 -0.9977 0.0502 825 | vn -0.2389 -0.9658 -0.1012 826 | vn -0.5598 -0.7915 -0.2451 827 | vn -0.1920 -0.9138 -0.3580 828 | vn 0.0966 -0.9251 -0.3673 829 | vn -0.0184 -0.9669 -0.2543 830 | vn 0.2626 -0.9646 -0.0242 831 | vn -0.4341 -0.9005 -0.0248 832 | vn 0.0822 -0.9961 0.0321 833 | vn -0.1043 -0.9889 0.1060 834 | vn -0.1211 -0.9884 0.0915 835 | vn 0.6202 -0.7844 0.0031 836 | vn 0.2632 -0.9647 0.0030 837 | vn 0.0037 -1.0000 0.0000 838 | vn -0.0007 -1.0000 0.0030 839 | vn -0.2726 -0.9620 -0.0135 840 | vn -0.5722 -0.8134 0.1048 841 | vn 0.1126 -0.9880 0.1060 842 | vn 0.1695 -0.9849 0.0351 843 | vn -0.0188 -0.9993 -0.0316 844 | vn 0.4706 -0.8798 -0.0669 845 | vn -0.4205 -0.8760 0.2362 846 | vn 0.0462 -0.9743 0.2206 847 | vn -0.1394 -0.9677 0.2100 848 | vn 0.0978 -0.7988 0.5936 849 | vn 0.5017 -0.8529 0.1440 850 | vn 0.2762 -0.9611 0.0008 851 | vn 0.0007 -1.0000 0.0000 852 | vn 0.0001 -1.0000 0.0008 853 | vn -0.1268 -0.9575 0.2590 854 | vn -0.5838 -0.7676 0.2646 855 | vn 0.1850 -0.9591 0.2145 856 | vn 0.1278 -0.9664 0.2231 857 | vn -0.0801 -0.9641 0.2532 858 | vn 0.3023 -0.9470 0.1085 859 | vn -0.2969 -0.9295 0.2189 860 | vn -0.2439 -0.9667 -0.0779 861 | vn -0.2951 -0.9240 -0.2432 862 | vn 0.4637 -0.8851 0.0392 863 | vn 0.4980 -0.8672 0.0074 864 | vn 0.1197 -0.9923 -0.0333 865 | vn -0.0001 -0.9999 -0.0163 866 | vn -0.0236 -0.9990 -0.0392 867 | vn -0.0957 -0.9953 -0.0111 868 | vn -0.4753 -0.8790 0.0379 869 | vn -0.2030 -0.9436 -0.2616 870 | vn 0.1393 -0.9869 -0.0809 871 | vn -0.0461 -0.9736 0.2238 872 | vn 0.0976 -0.9951 0.0177 873 | vn -0.0381 -0.9985 0.0401 874 | vn -0.2955 -0.9552 -0.0153 875 | vn -0.3238 -0.9455 -0.0354 876 | vn 0.4623 -0.8791 -0.1160 877 | vn 0.4634 -0.8631 -0.2006 878 | vn 0.0990 -0.9851 -0.1403 879 | vn 0.0216 -0.9963 -0.0826 880 | vn -0.0857 -0.9862 -0.1414 881 | vn -0.2268 -0.9445 -0.2378 882 | vn -0.3764 -0.9180 -0.1249 883 | vn -0.4062 -0.9128 -0.0431 884 | vn 0.3068 -0.9516 -0.0152 885 | vn 0.2442 -0.9688 0.0431 886 | vn 0.0974 -0.9951 -0.0189 887 | vn -0.0108 -0.9995 0.0290 888 | vn -0.2925 -0.9482 0.1235 889 | vn -0.3232 -0.9438 -0.0691 890 | vn 0.3658 -0.8405 -0.3996 891 | vn 0.3697 -0.7242 -0.5820 892 | vn 0.2680 -0.7801 -0.5654 893 | vn 0.0752 -0.8345 -0.5458 894 | vn -0.1069 -0.8117 -0.5742 895 | vn -0.2264 -0.7694 -0.5972 896 | vn -0.1391 -0.8897 -0.4348 897 | vn -0.0150 -0.9982 -0.0586 898 | vn 0.4672 -0.8769 0.1130 899 | vn 0.2133 -0.9765 0.0319 900 | vn 0.0381 -0.9993 0.0019 901 | vn -0.1099 -0.9903 -0.0845 902 | vn -0.2076 -0.9655 0.1571 903 | vn -0.4554 -0.8558 0.2452 904 | vn 0.0121 -0.9927 0.1201 905 | vn 0.1208 -0.9926 0.0101 906 | vn 0.1281 -0.9851 -0.1147 907 | vn 0.1503 -0.9577 -0.2455 908 | vn -0.0383 -0.9934 -0.1082 909 | vn -0.2411 -0.9703 0.0202 910 | vn 0.0092 -0.9934 0.1139 911 | vn 0.2079 -0.9362 0.2835 912 | vn 0.3692 -0.9174 0.1486 913 | vn -0.0238 -0.9960 -0.0860 914 | vn 0.0108 -0.9998 0.0141 915 | vn -0.3977 -0.8549 -0.3332 916 | vn 0.0191 -0.9659 -0.2581 917 | vn 0.3354 -0.8443 0.4179 918 | vn 0.1214 -0.7514 0.6486 919 | vn -0.0202 -0.7410 0.6712 920 | vn 0.1255 -0.8175 0.5622 921 | vn 0.0406 -0.8538 0.5191 922 | vn 0.0187 -0.8267 0.5624 923 | vn 0.0254 -0.7414 0.6706 924 | vn -0.0132 -0.7588 0.6512 925 | vn 0.2032 -0.8757 0.4380 926 | vn 0.3575 -0.9011 -0.2452 927 | vn -0.1288 -0.9247 -0.3583 928 | vn 0.1104 -0.9931 -0.0388 929 | vn -0.5629 -0.8052 -0.1864 930 | vn 0.1269 -0.9082 -0.3988 931 | vn 0.3409 -0.8611 -0.3773 932 | vn 0.1611 -0.9643 -0.2101 933 | vn 0.2781 -0.9596 0.0423 934 | vn 0.1496 -0.9509 0.2711 935 | vn 0.0223 -0.9471 0.3202 936 | vn 0.0221 -0.9600 0.2792 937 | vn 0.0356 -0.9953 0.0898 938 | vn -0.0053 -0.9813 -0.1922 939 | vn -0.3355 -0.8617 -0.3807 940 | vn -0.3407 -0.8611 -0.3773 941 | vn 0.0648 -0.9717 -0.2274 942 | vn 0.4258 -0.9048 -0.0047 943 | vn -0.5602 -0.7885 0.2539 944 | vn -0.0682 -0.9872 0.1439 945 | vn 0.0838 -0.9822 -0.1680 946 | vn 0.3270 -0.8417 -0.4296 947 | vn 0.2373 -0.8549 -0.4614 948 | vn 0.1467 -0.9631 -0.2257 949 | vn 0.0232 -0.9994 -0.0268 950 | vn -0.2189 -0.9500 -0.2228 951 | vn -0.3686 -0.8159 -0.4455 952 | vn -0.2138 -0.8714 -0.4415 953 | vn -0.0457 -0.9847 -0.1680 954 | vn -0.3631 -0.9226 0.1304 955 | vn 0.2205 -0.9304 0.2928 956 | vn 0.5354 -0.8156 0.2192 957 | vn -0.4713 -0.7087 0.5250 958 | vn -0.1889 -0.7739 0.6044 959 | vn 0.0667 -0.9032 0.4241 960 | vn 0.0447 -0.9783 0.2024 961 | vn 0.1155 -0.9914 0.0614 962 | vn 0.4219 -0.9063 -0.0258 963 | vn 0.2264 -0.9739 -0.0149 964 | vn -0.2384 -0.9708 -0.0276 965 | vn -0.3532 -0.9338 0.0575 966 | vn -0.2474 -0.9490 0.1953 967 | vn 0.1891 -0.8878 0.4196 968 | vn 0.1787 -0.7755 0.6055 969 | vn 0.1562 -0.7972 0.5832 970 | vn 0.1462 -0.9651 0.2174 971 | vn 0.0035 -0.9970 -0.0779 972 | vn -0.0347 -0.9975 -0.0614 973 | vn 0.0067 -1.0000 -0.0015 974 | vn 0.0316 -0.9994 -0.0149 975 | vn 0.0458 -0.9989 0.0082 976 | vn -0.0316 -0.9995 -0.0061 977 | vn -0.0067 -0.9992 -0.0398 978 | vn -0.0068 -0.9967 -0.0814 979 | vn -0.1659 -0.9612 -0.2206 980 | vn 0.0637 -0.9812 -0.1824 981 | vn 0.1107 -0.9676 -0.2270 982 | vn 0.2632 -0.9624 -0.0672 983 | usemtl None 984 | s off 985 | f 1/1/1 17/2/1 16/3/1 986 | f 2/4/2 18/5/2 17/2/2 987 | f 4/6/3 18/5/3 3/7/3 988 | f 5/8/4 19/9/4 4/6/4 989 | f 6/10/5 20/11/5 5/8/5 990 | f 7/12/6 21/13/6 6/10/6 991 | f 9/14/7 231/15/7 230/16/7 992 | f 39/17/7 237/18/7 234/19/7 993 | f 24/20/8 38/21/8 23/22/8 994 | f 10/23/9 26/24/9 25/25/9 995 | f 11/26/10 27/27/10 26/24/10 996 | f 44/28/11 268/29/11 59/30/11 997 | f 28/31/12 263/32/12 29/33/12 998 | f 27/27/13 258/34/13 259/35/13 999 | f 16/3/14 32/36/14 31/37/14 1000 | f 17/2/15 33/38/15 32/36/15 1001 | f 18/5/16 34/39/16 33/38/16 1002 | f 20/11/17 34/39/17 19/9/17 1003 | f 21/13/18 35/40/18 20/11/18 1004 | f 22/41/19 36/42/19 21/13/19 1005 | f 7/43/7 228/44/7 226/45/7 1006 | f 8/46/7 230/47/7 228/44/7 1007 | f 231/15/20 252/48/20 249/49/20 1008 | f 25/25/21 41/50/21 40/51/21 1009 | f 26/24/22 42/52/22 41/50/22 1010 | f 28/31/23 42/52/23 27/27/23 1011 | f 29/33/24 43/53/24 28/31/24 1012 | f 60/54/25 268/29/25 269/55/25 1013 | f 31/37/26 47/56/26 46/57/26 1014 | f 32/36/27 48/58/27 47/56/27 1015 | f 33/38/28 49/59/28 48/58/28 1016 | f 34/39/29 50/60/29 49/59/29 1017 | f 35/40/30 51/61/30 50/60/30 1018 | f 37/62/31 51/61/31 36/42/31 1019 | f 52/63/7 232/64/7 235/65/7 1020 | f 53/66/7 235/65/7 236/67/7 1021 | f 40/51/32 243/68/32 241/69/32 1022 | f 41/50/33 55/70/33 40/51/33 1023 | f 42/52/34 56/71/34 41/50/34 1024 | f 43/53/35 57/72/35 42/52/35 1025 | f 44/28/36 58/73/36 43/53/36 1026 | f 60/74/37 267/75/37 45/76/37 1027 | f 47/56/38 61/77/38 46/57/38 1028 | f 47/56/39 63/78/39 62/79/39 1029 | f 49/59/40 63/78/40 48/58/40 1030 | f 50/60/41 64/80/41 49/59/41 1031 | f 50/60/42 66/81/42 65/82/42 1032 | f 51/61/43 67/83/43 66/81/43 1033 | f 53/66/44 67/83/44 52/63/44 1034 | f 53/66/45 69/84/45 68/85/45 1035 | f 55/70/46 69/84/46 54/86/46 1036 | f 56/71/47 70/87/47 55/70/47 1037 | f 56/71/48 72/88/48 71/89/48 1038 | f 57/72/49 73/90/49 72/88/49 1039 | f 59/30/50 73/90/50 58/73/50 1040 | f 59/30/51 75/91/51 74/92/51 1041 | f 62/79/52 76/93/52 61/77/52 1042 | f 63/78/53 77/94/53 62/79/53 1043 | f 64/80/54 78/95/54 63/78/54 1044 | f 65/82/55 79/96/55 64/80/55 1045 | f 65/82/56 81/97/56 80/98/56 1046 | f 66/81/57 82/99/57 81/97/57 1047 | f 67/83/58 83/100/58 82/99/58 1048 | f 69/84/59 83/100/59 68/85/59 1049 | f 70/87/60 84/101/60 69/84/60 1050 | f 71/89/61 85/102/61 70/87/61 1051 | f 71/89/62 87/103/62 86/104/62 1052 | f 72/88/63 88/105/63 87/103/63 1053 | f 73/90/64 89/106/64 88/105/64 1054 | f 74/92/65 90/107/65 89/106/65 1055 | f 76/93/66 92/108/66 91/109/66 1056 | f 78/95/67 92/108/67 77/94/67 1057 | f 79/96/68 93/110/68 78/95/68 1058 | f 80/98/69 94/111/69 79/96/69 1059 | f 81/97/70 95/112/70 80/98/70 1060 | f 81/97/71 97/113/71 96/114/71 1061 | f 82/99/72 98/115/72 97/113/72 1062 | f 84/101/73 98/115/73 83/100/73 1063 | f 85/102/74 99/116/74 84/101/74 1064 | f 85/102/75 101/117/75 100/118/75 1065 | f 86/104/76 102/119/76 101/117/76 1066 | f 87/103/77 103/120/77 102/119/77 1067 | f 88/105/78 104/121/78 103/120/78 1068 | f 90/107/79 104/121/79 89/106/79 1069 | f 91/109/80 107/122/80 106/123/80 1070 | f 93/110/81 107/122/81 92/108/81 1071 | f 94/111/82 108/124/82 93/110/82 1072 | f 95/112/83 109/125/83 94/111/83 1073 | f 95/112/84 111/126/84 110/127/84 1074 | f 96/114/85 112/128/85 111/126/85 1075 | f 97/113/86 113/129/86 112/128/86 1076 | f 99/116/87 113/129/87 98/115/87 1077 | f 100/118/88 114/130/88 99/116/88 1078 | f 101/117/89 115/131/89 100/118/89 1079 | f 101/117/90 117/132/90 116/133/90 1080 | f 102/119/91 118/134/91 117/132/91 1081 | f 103/120/92 119/135/92 118/134/92 1082 | f 105/136/93 119/135/93 104/121/93 1083 | f 107/122/94 121/137/94 106/123/94 1084 | f 108/124/95 122/138/95 107/122/95 1085 | f 109/125/96 123/139/96 108/124/96 1086 | f 109/125/97 125/140/97 124/141/97 1087 | f 110/127/98 126/142/98 125/140/98 1088 | f 111/126/99 127/143/99 126/142/99 1089 | f 112/128/100 128/144/100 127/143/100 1090 | f 114/130/101 128/144/101 113/129/101 1091 | f 115/131/102 129/145/102 114/130/102 1092 | f 116/133/103 130/146/103 115/131/103 1093 | f 117/132/104 131/147/104 116/133/104 1094 | f 117/132/105 133/148/105 132/149/105 1095 | f 118/134/106 134/150/106 133/148/106 1096 | f 119/135/107 135/151/107 134/150/107 1097 | f 122/138/108 136/152/108 121/137/108 1098 | f 122/138/109 138/153/109 137/154/109 1099 | f 123/139/110 139/155/110 138/153/110 1100 | f 124/141/111 140/156/111 139/155/111 1101 | f 125/140/112 141/157/112 140/156/112 1102 | f 127/143/113 141/157/113 126/142/113 1103 | f 127/143/114 143/158/114 142/159/114 1104 | f 129/145/115 143/158/115 128/144/115 1105 | f 129/145/116 145/160/116 144/161/116 1106 | f 131/147/117 145/160/117 130/146/117 1107 | f 132/149/118 146/162/118 131/147/118 1108 | f 133/148/119 147/163/119 132/149/119 1109 | f 134/150/120 148/164/120 133/148/120 1110 | f 134/150/121 150/165/121 149/166/121 1111 | f 137/154/122 151/167/122 136/152/122 1112 | f 137/154/123 153/168/123 152/169/123 1113 | f 138/153/124 154/170/124 153/168/124 1114 | f 139/155/125 155/171/125 154/170/125 1115 | f 140/156/126 156/172/126 155/171/126 1116 | f 142/159/127 156/172/127 141/157/127 1117 | f 142/159/128 158/173/128 157/174/128 1118 | f 144/161/129 158/173/129 143/158/129 1119 | f 144/161/130 160/175/130 159/176/130 1120 | f 146/162/131 160/175/131 145/160/131 1121 | f 147/163/132 161/177/132 146/162/132 1122 | f 148/164/133 162/178/133 147/163/133 1123 | f 149/166/134 163/179/134 148/164/134 1124 | f 149/166/135 165/180/135 164/181/135 1125 | f 152/169/136 166/182/136 151/167/136 1126 | f 152/169/137 168/183/137 167/184/137 1127 | f 154/170/138 168/183/138 153/168/138 1128 | f 155/171/139 169/185/139 154/170/139 1129 | f 155/171/140 171/186/140 170/187/140 1130 | f 156/172/141 172/188/141 171/186/141 1131 | f 157/174/142 173/189/142 172/188/142 1132 | f 159/176/143 173/189/143 158/173/143 1133 | f 160/175/144 174/190/144 159/176/144 1134 | f 161/177/145 175/191/145 160/175/145 1135 | f 161/177/146 177/192/146 176/193/146 1136 | f 162/178/147 178/194/147 177/192/147 1137 | f 164/181/148 178/194/148 163/179/148 1138 | f 164/181/149 180/195/149 179/196/149 1139 | f 167/184/150 181/197/150 166/182/150 1140 | f 167/184/151 183/198/151 182/199/151 1141 | f 168/183/152 184/200/152 183/198/152 1142 | f 169/185/153 185/201/153 184/200/153 1143 | f 171/186/154 185/201/154 170/187/154 1144 | f 172/188/155 186/202/155 171/186/155 1145 | f 173/189/156 187/203/156 172/188/156 1146 | f 173/189/157 189/204/157 188/205/157 1147 | f 174/190/158 190/206/158 189/204/158 1148 | f 175/191/159 191/207/159 190/206/159 1149 | f 177/192/160 191/207/160 176/193/160 1150 | f 178/194/161 192/208/161 177/192/161 1151 | f 179/196/162 193/209/162 178/194/162 1152 | f 179/196/163 195/210/163 194/211/163 1153 | f 181/197/164 197/212/164 196/213/164 1154 | f 182/199/165 198/214/165 197/212/165 1155 | f 184/200/166 198/214/166 183/198/166 1156 | f 184/200/167 200/215/167 199/216/167 1157 | f 185/201/168 201/217/168 200/215/168 1158 | f 186/202/169 202/218/169 201/217/169 1159 | f 187/203/170 203/219/170 202/218/170 1160 | f 189/204/171 203/219/171 188/205/171 1161 | f 190/206/172 204/220/172 189/204/172 1162 | f 191/207/173 205/221/173 190/206/173 1163 | f 192/208/174 206/222/174 191/207/174 1164 | f 192/208/175 208/223/175 207/224/175 1165 | f 194/211/176 208/223/176 193/209/176 1166 | f 195/210/177 209/225/177 194/211/177 1167 | f 196/213/178 212/226/178 211/227/178 1168 | f 197/212/179 213/228/179 212/226/179 1169 | f 198/214/180 214/229/180 213/228/180 1170 | f 199/216/181 215/230/181 214/229/181 1171 | f 201/217/182 215/230/182 200/215/182 1172 | f 201/217/183 217/231/183 216/232/183 1173 | f 202/218/184 218/233/184 217/231/184 1174 | f 204/220/185 218/233/185 203/219/185 1175 | f 205/221/186 219/234/186 204/220/186 1176 | f 205/221/187 221/235/187 220/236/187 1177 | f 207/224/188 221/235/188 206/222/188 1178 | f 208/223/189 222/237/189 207/224/189 1179 | f 209/225/190 223/238/190 208/223/190 1180 | f 210/239/191 224/240/191 209/225/191 1181 | f 236/67/192 255/241/192 237/18/192 1182 | f 228/44/193 244/242/193 226/45/193 1183 | f 24/20/194 240/243/194 39/17/194 1184 | f 237/18/195 252/48/195 234/19/195 1185 | f 227/244/196 244/245/196 245/246/196 1186 | f 54/86/197 240/243/197 242/247/197 1187 | f 54/86/7 236/67/7 237/18/7 1188 | f 37/62/7 227/244/7 232/64/7 1189 | f 22/41/7 226/248/7 227/244/7 1190 | f 24/20/7 234/19/7 231/15/7 1191 | f 38/21/198 239/249/198 23/22/198 1192 | f 23/22/199 241/69/199 240/243/199 1193 | f 240/243/200 243/68/200 242/247/200 1194 | f 246/250/201 245/246/201 244/245/201 1195 | f 246/250/202 249/49/202 247/251/202 1196 | f 247/251/203 250/252/203 245/246/203 1197 | f 249/49/204 257/253/204 233/254/204 1198 | f 251/255/205 253/256/205 250/252/205 1199 | f 251/255/206 255/241/206 254/257/206 1200 | f 25/25/207 241/69/207 239/249/207 1201 | f 54/86/208 243/68/208 55/70/208 1202 | f 230/47/193 246/258/193 228/44/193 1203 | f 235/65/209 250/252/209 253/256/209 1204 | f 10/259/193 38/260/193 9/261/193 1205 | f 231/15/210 248/262/210 230/16/210 1206 | f 25/25/211 238/263/211 10/23/211 1207 | f 236/67/212 253/256/212 254/257/212 1208 | f 227/244/213 250/252/213 232/64/213 1209 | f 229/264/214 257/253/214 256/265/214 1210 | f 251/255/215 229/264/215 256/265/215 1211 | f 249/49/216 229/264/216 247/251/216 1212 | f 251/255/217 257/253/217 252/48/217 1213 | f 258/34/218 261/266/218 259/35/218 1214 | f 262/267/219 261/266/219 260/268/219 1215 | f 264/269/220 263/32/220 262/267/220 1216 | f 265/270/221 266/271/221 263/32/221 1217 | f 267/272/222 268/29/222 266/271/222 1218 | f 30/273/223 267/75/223 265/274/223 1219 | f 27/27/224 261/266/224 28/31/224 1220 | f 14/275/225 264/276/225 262/277/225 1221 | f 13/278/226 262/277/226 260/279/226 1222 | f 12/280/227 260/279/227 258/281/227 1223 | f 29/33/228 266/271/228 44/28/228 1224 | f 15/282/229 265/274/229 264/276/229 1225 | f 1/1/230 2/4/230 17/2/230 1226 | f 2/4/231 3/7/231 18/5/231 1227 | f 4/6/232 19/9/232 18/5/232 1228 | f 5/8/233 20/11/233 19/9/233 1229 | f 6/10/234 21/13/234 20/11/234 1230 | f 7/12/235 22/41/235 21/13/235 1231 | f 9/14/7 24/20/7 231/15/7 1232 | f 39/17/7 54/86/7 237/18/7 1233 | f 24/20/8 9/14/8 38/21/8 1234 | f 10/23/5 11/26/5 26/24/5 1235 | f 11/26/4 12/283/4 27/27/4 1236 | f 44/28/11 266/271/11 268/29/11 1237 | f 28/31/12 261/266/12 263/32/12 1238 | f 27/27/13 12/283/13 258/34/13 1239 | f 16/3/236 17/2/236 32/36/236 1240 | f 17/2/237 18/5/237 33/38/237 1241 | f 18/5/238 19/9/238 34/39/238 1242 | f 20/11/239 35/40/239 34/39/239 1243 | f 21/13/240 36/42/240 35/40/240 1244 | f 22/41/241 37/62/241 36/42/241 1245 | f 7/43/7 8/46/7 228/44/7 1246 | f 8/46/7 9/261/7 230/47/7 1247 | f 231/15/20 234/19/20 252/48/20 1248 | f 25/25/242 26/24/242 41/50/242 1249 | f 26/24/243 27/27/243 42/52/243 1250 | f 28/31/244 43/53/244 42/52/244 1251 | f 29/33/245 44/28/245 43/53/245 1252 | f 60/54/25 59/30/25 268/29/25 1253 | f 31/37/246 32/36/246 47/56/246 1254 | f 32/36/247 33/38/247 48/58/247 1255 | f 33/38/248 34/39/248 49/59/248 1256 | f 34/39/249 35/40/249 50/60/249 1257 | f 35/40/250 36/42/250 51/61/250 1258 | f 37/62/251 52/63/251 51/61/251 1259 | f 52/63/7 37/62/7 232/64/7 1260 | f 53/66/7 52/63/7 235/65/7 1261 | f 40/51/32 55/70/32 243/68/32 1262 | f 41/50/252 56/71/252 55/70/252 1263 | f 42/52/253 57/72/253 56/71/253 1264 | f 43/53/254 58/73/254 57/72/254 1265 | f 44/28/255 59/30/255 58/73/255 1266 | f 60/74/37 269/284/37 267/75/37 1267 | f 47/56/256 62/79/256 61/77/256 1268 | f 47/56/257 48/58/257 63/78/257 1269 | f 49/59/258 64/80/258 63/78/258 1270 | f 50/60/259 65/82/259 64/80/259 1271 | f 50/60/260 51/61/260 66/81/260 1272 | f 51/61/261 52/63/261 67/83/261 1273 | f 53/66/262 68/85/262 67/83/262 1274 | f 53/66/263 54/86/263 69/84/263 1275 | f 55/70/264 70/87/264 69/84/264 1276 | f 56/71/265 71/89/265 70/87/265 1277 | f 56/71/266 57/72/266 72/88/266 1278 | f 57/72/267 58/73/267 73/90/267 1279 | f 59/30/268 74/92/268 73/90/268 1280 | f 59/30/269 60/54/269 75/91/269 1281 | f 62/79/270 77/94/270 76/93/270 1282 | f 63/78/271 78/95/271 77/94/271 1283 | f 64/80/272 79/96/272 78/95/272 1284 | f 65/82/273 80/98/273 79/96/273 1285 | f 65/82/274 66/81/274 81/97/274 1286 | f 66/81/275 67/83/275 82/99/275 1287 | f 67/83/276 68/85/276 83/100/276 1288 | f 69/84/277 84/101/277 83/100/277 1289 | f 70/87/278 85/102/278 84/101/278 1290 | f 71/89/279 86/104/279 85/102/279 1291 | f 71/89/280 72/88/280 87/103/280 1292 | f 72/88/281 73/90/281 88/105/281 1293 | f 73/90/282 74/92/282 89/106/282 1294 | f 74/92/283 75/91/283 90/107/283 1295 | f 76/93/284 77/94/284 92/108/284 1296 | f 78/95/285 93/110/285 92/108/285 1297 | f 79/96/286 94/111/286 93/110/286 1298 | f 80/98/287 95/112/287 94/111/287 1299 | f 81/97/288 96/114/288 95/112/288 1300 | f 81/97/289 82/99/289 97/113/289 1301 | f 82/99/290 83/100/290 98/115/290 1302 | f 84/101/291 99/116/291 98/115/291 1303 | f 85/102/292 100/118/292 99/116/292 1304 | f 85/102/293 86/104/293 101/117/293 1305 | f 86/104/294 87/103/294 102/119/294 1306 | f 87/103/295 88/105/295 103/120/295 1307 | f 88/105/296 89/106/296 104/121/296 1308 | f 90/107/297 105/136/297 104/121/297 1309 | f 91/109/298 92/108/298 107/122/298 1310 | f 93/110/299 108/124/299 107/122/299 1311 | f 94/111/300 109/125/300 108/124/300 1312 | f 95/112/301 110/127/301 109/125/301 1313 | f 95/112/302 96/114/302 111/126/302 1314 | f 96/114/303 97/113/303 112/128/303 1315 | f 97/113/304 98/115/304 113/129/304 1316 | f 99/116/305 114/130/305 113/129/305 1317 | f 100/118/306 115/131/306 114/130/306 1318 | f 101/117/307 116/133/307 115/131/307 1319 | f 101/117/308 102/119/308 117/132/308 1320 | f 102/119/309 103/120/309 118/134/309 1321 | f 103/120/310 104/121/310 119/135/310 1322 | f 105/136/311 120/285/311 119/135/311 1323 | f 107/122/312 122/138/312 121/137/312 1324 | f 108/124/313 123/139/313 122/138/313 1325 | f 109/125/314 124/141/314 123/139/314 1326 | f 109/125/315 110/127/315 125/140/315 1327 | f 110/127/316 111/126/316 126/142/316 1328 | f 111/126/317 112/128/317 127/143/317 1329 | f 112/128/318 113/129/318 128/144/318 1330 | f 114/130/319 129/145/319 128/144/319 1331 | f 115/131/320 130/146/320 129/145/320 1332 | f 116/133/321 131/147/321 130/146/321 1333 | f 117/132/322 132/149/322 131/147/322 1334 | f 117/132/323 118/134/323 133/148/323 1335 | f 118/134/324 119/135/324 134/150/324 1336 | f 119/135/325 120/285/325 135/151/325 1337 | f 122/138/326 137/154/326 136/152/326 1338 | f 122/138/327 123/139/327 138/153/327 1339 | f 123/139/328 124/141/328 139/155/328 1340 | f 124/141/329 125/140/329 140/156/329 1341 | f 125/140/330 126/142/330 141/157/330 1342 | f 127/143/331 142/159/331 141/157/331 1343 | f 127/143/332 128/144/332 143/158/332 1344 | f 129/145/333 144/161/333 143/158/333 1345 | f 129/145/334 130/146/334 145/160/334 1346 | f 131/147/335 146/162/335 145/160/335 1347 | f 132/149/336 147/163/336 146/162/336 1348 | f 133/148/337 148/164/337 147/163/337 1349 | f 134/150/338 149/166/338 148/164/338 1350 | f 134/150/339 135/151/339 150/165/339 1351 | f 137/154/340 152/169/340 151/167/340 1352 | f 137/154/341 138/153/341 153/168/341 1353 | f 138/153/342 139/155/342 154/170/342 1354 | f 139/155/343 140/156/343 155/171/343 1355 | f 140/156/344 141/157/344 156/172/344 1356 | f 142/159/345 157/174/345 156/172/345 1357 | f 142/159/346 143/158/346 158/173/346 1358 | f 144/161/347 159/176/347 158/173/347 1359 | f 144/161/348 145/160/348 160/175/348 1360 | f 146/162/349 161/177/349 160/175/349 1361 | f 147/163/350 162/178/350 161/177/350 1362 | f 148/164/351 163/179/351 162/178/351 1363 | f 149/166/352 164/181/352 163/179/352 1364 | f 149/166/353 150/165/353 165/180/353 1365 | f 152/169/354 167/184/354 166/182/354 1366 | f 152/169/355 153/168/355 168/183/355 1367 | f 154/170/356 169/185/356 168/183/356 1368 | f 155/171/357 170/187/357 169/185/357 1369 | f 155/171/358 156/172/358 171/186/358 1370 | f 156/172/359 157/174/359 172/188/359 1371 | f 157/174/360 158/173/360 173/189/360 1372 | f 159/176/361 174/190/361 173/189/361 1373 | f 160/175/362 175/191/362 174/190/362 1374 | f 161/177/363 176/193/363 175/191/363 1375 | f 161/177/364 162/178/364 177/192/364 1376 | f 162/178/365 163/179/365 178/194/365 1377 | f 164/181/366 179/196/366 178/194/366 1378 | f 164/181/367 165/180/367 180/195/367 1379 | f 167/184/368 182/199/368 181/197/368 1380 | f 167/184/369 168/183/369 183/198/369 1381 | f 168/183/370 169/185/370 184/200/370 1382 | f 169/185/371 170/187/371 185/201/371 1383 | f 171/186/372 186/202/372 185/201/372 1384 | f 172/188/373 187/203/373 186/202/373 1385 | f 173/189/374 188/205/374 187/203/374 1386 | f 173/189/375 174/190/375 189/204/375 1387 | f 174/190/376 175/191/376 190/206/376 1388 | f 175/191/377 176/193/377 191/207/377 1389 | f 177/192/378 192/208/378 191/207/378 1390 | f 178/194/379 193/209/379 192/208/379 1391 | f 179/196/380 194/211/380 193/209/380 1392 | f 179/196/381 180/195/381 195/210/381 1393 | f 181/197/382 182/199/382 197/212/382 1394 | f 182/199/383 183/198/383 198/214/383 1395 | f 184/200/384 199/216/384 198/214/384 1396 | f 184/200/385 185/201/385 200/215/385 1397 | f 185/201/386 186/202/386 201/217/386 1398 | f 186/202/387 187/203/387 202/218/387 1399 | f 187/203/388 188/205/388 203/219/388 1400 | f 189/204/389 204/220/389 203/219/389 1401 | f 190/206/390 205/221/390 204/220/390 1402 | f 191/207/391 206/222/391 205/221/391 1403 | f 192/208/392 207/224/392 206/222/392 1404 | f 192/208/393 193/209/393 208/223/393 1405 | f 194/211/394 209/225/394 208/223/394 1406 | f 195/210/395 210/239/395 209/225/395 1407 | f 196/213/396 197/212/396 212/226/396 1408 | f 197/212/397 198/214/397 213/228/397 1409 | f 198/214/398 199/216/398 214/229/398 1410 | f 199/216/399 200/215/399 215/230/399 1411 | f 201/217/400 216/232/400 215/230/400 1412 | f 201/217/401 202/218/401 217/231/401 1413 | f 202/218/402 203/219/402 218/233/402 1414 | f 204/220/403 219/234/403 218/233/403 1415 | f 205/221/404 220/236/404 219/234/404 1416 | f 205/221/405 206/222/405 221/235/405 1417 | f 207/224/406 222/237/406 221/235/406 1418 | f 208/223/407 223/238/407 222/237/407 1419 | f 209/225/408 224/240/408 223/238/408 1420 | f 210/239/409 225/286/409 224/240/409 1421 | f 236/67/192 254/257/192 255/241/192 1422 | f 228/44/193 246/258/193 244/242/193 1423 | f 24/20/194 23/22/194 240/243/194 1424 | f 237/18/195 255/241/195 252/48/195 1425 | f 227/244/196 226/248/196 244/245/196 1426 | f 54/86/197 39/17/197 240/243/197 1427 | f 54/86/7 53/66/7 236/67/7 1428 | f 37/62/7 22/41/7 227/244/7 1429 | f 22/41/7 7/12/7 226/248/7 1430 | f 24/20/7 39/17/7 234/19/7 1431 | f 38/21/6 238/263/6 239/249/6 1432 | f 23/22/410 239/249/410 241/69/410 1433 | f 240/243/411 241/69/411 243/68/411 1434 | f 246/250/412 247/251/412 245/246/412 1435 | f 246/250/201 248/262/201 249/49/201 1436 | f 247/251/413 251/255/413 250/252/413 1437 | f 249/49/204 252/48/204 257/253/204 1438 | f 251/255/414 254/257/414 253/256/414 1439 | f 251/255/415 252/48/415 255/241/415 1440 | f 25/25/207 40/51/207 241/69/207 1441 | f 54/86/208 242/247/208 243/68/208 1442 | f 230/47/193 248/287/193 246/258/193 1443 | f 235/65/209 232/64/209 250/252/209 1444 | f 10/259/193 238/288/193 38/260/193 1445 | f 231/15/210 249/49/210 248/262/210 1446 | f 25/25/211 239/249/211 238/263/211 1447 | f 236/67/212 235/65/212 253/256/212 1448 | f 227/244/213 245/246/213 250/252/213 1449 | f 229/264/416 233/254/416 257/253/416 1450 | f 251/255/215 247/251/215 229/264/215 1451 | f 249/49/216 233/254/216 229/264/216 1452 | f 251/255/217 256/265/217 257/253/217 1453 | f 258/34/417 260/268/417 261/266/417 1454 | f 262/267/418 263/32/418 261/266/418 1455 | f 264/269/419 265/270/419 263/32/419 1456 | f 265/270/420 267/272/420 266/271/420 1457 | f 267/272/421 269/55/421 268/29/421 1458 | f 30/273/223 45/76/223 267/75/223 1459 | f 27/27/224 259/35/224 261/266/224 1460 | f 14/275/225 15/282/225 264/276/225 1461 | f 13/278/226 14/275/226 262/277/226 1462 | f 12/280/227 13/278/227 260/279/227 1463 | f 29/33/228 263/32/228 266/271/228 1464 | f 15/282/229 30/273/229 265/274/229 1465 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest1/src/res/test: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk4. 12 | 13 | 73 | 74 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=ca27512f 2 | build.xml.script.CRC32=6522f0c1 3 | build.xml.stylesheet.CRC32=f85dc8f2@1.99.0.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=ca27512f 7 | nbproject/build-impl.xml.script.CRC32=bb910379 8 | nbproject/build-impl.xml.stylesheet.CRC32=d549e5cc@1.99.0.48 9 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | compile.on.save=true 2 | user.properties.file=C:\\Users\\Leo\\AppData\\Roaming\\NetBeans\\12.4\\build.properties 3 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/partition/Node.java 7 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Vec3.java 8 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Face.java 9 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Camera.java 10 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/MeshLoader.java 11 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/View.java 12 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Sphere.java 13 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Response.java 14 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Edge.java 15 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Player.java 16 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/partition/Octree.java 17 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/Input.java 18 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/partition/FaceBox.java 19 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/World.java 20 | file:/D:/java/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk2/src/test/partition/Box.java 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processor.options= 4 | annotation.processing.processors.list= 5 | annotation.processing.run.all.processors=true 6 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 7 | build.classes.dir=${build.dir}/classes 8 | build.classes.excludes=**/*.java,**/*.form 9 | # This directory is removed when the project is cleaned: 10 | build.dir=build 11 | build.generated.dir=${build.dir}/generated 12 | build.generated.sources.dir=${build.dir}/generated-sources 13 | # Only compile against the classpath explicitly listed here: 14 | build.sysclasspath=ignore 15 | build.test.classes.dir=${build.dir}/test/classes 16 | build.test.results.dir=${build.dir}/test/results 17 | # Uncomment to specify the preferred debugger connection transport: 18 | #debug.transport=dt_socket 19 | debug.classpath=\ 20 | ${run.classpath} 21 | debug.modulepath=\ 22 | ${run.modulepath} 23 | debug.test.classpath=\ 24 | ${run.test.classpath} 25 | debug.test.modulepath=\ 26 | ${run.test.modulepath} 27 | # Files in build.classes.dir which should be excluded from distribution jar 28 | dist.archive.excludes= 29 | # This directory is removed when the project is cleaned: 30 | dist.dir=dist 31 | dist.jar=${dist.dir}/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk4.jar 32 | dist.javadoc.dir=${dist.dir}/javadoc 33 | dist.jlink.dir=${dist.dir}/jlink 34 | dist.jlink.output=${dist.jlink.dir}/Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk4 35 | excludes= 36 | includes=** 37 | jar.compress=false 38 | javac.classpath= 39 | # Space-separated list of extra javac options 40 | javac.compilerargs= 41 | javac.deprecation=false 42 | javac.external.vm=true 43 | javac.modulepath= 44 | javac.processormodulepath= 45 | javac.processorpath=\ 46 | ${javac.classpath} 47 | javac.source=1.8 48 | javac.target=1.8 49 | javac.test.classpath=\ 50 | ${javac.classpath}:\ 51 | ${build.classes.dir} 52 | javac.test.modulepath=\ 53 | ${javac.modulepath} 54 | javac.test.processorpath=\ 55 | ${javac.test.classpath} 56 | javadoc.additionalparam= 57 | javadoc.author=false 58 | javadoc.encoding=${source.encoding} 59 | javadoc.html5=false 60 | javadoc.noindex=false 61 | javadoc.nonavbar=false 62 | javadoc.notree=false 63 | javadoc.private=false 64 | javadoc.splitindex=true 65 | javadoc.use=true 66 | javadoc.version=false 67 | javadoc.windowtitle= 68 | # The jlink additional root modules to resolve 69 | jlink.additionalmodules= 70 | # The jlink additional command line parameters 71 | jlink.additionalparam= 72 | jlink.launcher=true 73 | jlink.launcher.name=Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk4 74 | main.class=test.View 75 | manifest.file=manifest.mf 76 | meta.inf.dir=${src.dir}/META-INF 77 | mkdist.disabled=false 78 | platform.active=default_platform 79 | run.classpath=\ 80 | ${javac.classpath}:\ 81 | ${build.classes.dir} 82 | # Space-separated list of JVM arguments used when running the project. 83 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. 84 | # To set system properties for unit tests define test-sys-prop.name=value: 85 | run.jvmargs= 86 | run.modulepath=\ 87 | ${javac.modulepath} 88 | run.test.classpath=\ 89 | ${javac.test.classpath}:\ 90 | ${build.test.classes.dir} 91 | run.test.modulepath=\ 92 | ${javac.test.modulepath} 93 | source.encoding=UTF-8 94 | src.dir=src 95 | test.src.dir=test 96 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | Java3DMeshTerrainVsPlayerCollisionTest5_OctreeOk4 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/res/princess_peaches_castle_(outside).mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 16 3 | 4 | newmtl Material.095 5 | Ns 225.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.0 0.0 0.0 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl Material.096 15 | Ns 225.000000 16 | Ka 1.000000 1.000000 1.000000 17 | Kd 0.800000 0.800000 0.800000 18 | Ks 0.500000 0.500000 0.500000 19 | Ke 0.0 0.0 0.0 20 | Ni 1.450000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl Material.097 25 | Ns 225.000000 26 | Ka 1.000000 1.000000 1.000000 27 | Kd 0.800000 0.800000 0.800000 28 | Ks 0.500000 0.500000 0.500000 29 | Ke 0.0 0.0 0.0 30 | Ni 1.450000 31 | d 1.000000 32 | illum 2 33 | 34 | newmtl Material.098 35 | Ns 225.000000 36 | Ka 1.000000 1.000000 1.000000 37 | Kd 0.800000 0.800000 0.800000 38 | Ks 0.500000 0.500000 0.500000 39 | Ke 0.0 0.0 0.0 40 | Ni 1.450000 41 | d 1.000000 42 | illum 2 43 | 44 | newmtl Material.099 45 | Ns 225.000000 46 | Ka 1.000000 1.000000 1.000000 47 | Kd 0.800000 0.800000 0.800000 48 | Ks 0.500000 0.500000 0.500000 49 | Ke 0.0 0.0 0.0 50 | Ni 1.450000 51 | d 1.000000 52 | illum 2 53 | 54 | newmtl Material.100 55 | Ns 225.000000 56 | Ka 1.000000 1.000000 1.000000 57 | Kd 0.800000 0.800000 0.800000 58 | Ks 0.500000 0.500000 0.500000 59 | Ke 0.0 0.0 0.0 60 | Ni 1.450000 61 | d 1.000000 62 | illum 2 63 | 64 | newmtl Material.101_princess_peaches_cast 65 | Ns 225.000000 66 | Ka 1.000000 1.000000 1.000000 67 | Kd 0.800000 0.800000 0.800000 68 | Ks 0.500000 0.500000 0.500000 69 | Ke 0.0 0.0 0.0 70 | Ni 1.450000 71 | d 1.000000 72 | illum 2 73 | 74 | newmtl Material.102_princess_peaches_cast 75 | Ns 225.000000 76 | Ka 1.000000 1.000000 1.000000 77 | Kd 0.800000 0.800000 0.800000 78 | Ks 0.500000 0.500000 0.500000 79 | Ke 0.0 0.0 0.0 80 | Ni 1.450000 81 | d 1.000000 82 | illum 2 83 | 84 | newmtl Material.103_princess_peaches_cast 85 | Ns 225.000000 86 | Ka 1.000000 1.000000 1.000000 87 | Kd 0.800000 0.800000 0.800000 88 | Ks 0.500000 0.500000 0.500000 89 | Ke 0.0 0.0 0.0 90 | Ni 1.450000 91 | d 1.000000 92 | illum 2 93 | 94 | newmtl Material.104 95 | Ns 225.000000 96 | Ka 1.000000 1.000000 1.000000 97 | Kd 0.800000 0.800000 0.800000 98 | Ks 0.500000 0.500000 0.500000 99 | Ke 0.0 0.0 0.0 100 | Ni 1.450000 101 | d 1.000000 102 | illum 2 103 | 104 | newmtl Material.104_princess_peaches_cast 105 | Ns 225.000000 106 | Ka 1.000000 1.000000 1.000000 107 | Kd 0.800000 0.800000 0.800000 108 | Ks 0.500000 0.500000 0.500000 109 | Ke 0.0 0.0 0.0 110 | Ni 1.450000 111 | d 1.000000 112 | illum 2 113 | 114 | newmtl Material.105_princess_peaches_cast 115 | Ns 225.000000 116 | Ka 1.000000 1.000000 1.000000 117 | Kd 0.800000 0.800000 0.800000 118 | Ks 0.500000 0.500000 0.500000 119 | Ke 0.0 0.0 0.0 120 | Ni 1.450000 121 | d 1.000000 122 | illum 2 123 | 124 | newmtl Material.106_princess_peaches_cast 125 | Ns 225.000000 126 | Ka 1.000000 1.000000 1.000000 127 | Kd 0.800000 0.800000 0.800000 128 | Ks 0.500000 0.500000 0.500000 129 | Ke 0.0 0.0 0.0 130 | Ni 1.450000 131 | d 1.000000 132 | illum 2 133 | 134 | newmtl Material.126_princess_peaches_cast 135 | Ns 225.000000 136 | Ka 1.000000 1.000000 1.000000 137 | Kd 0.800000 0.800000 0.800000 138 | Ks 0.500000 0.500000 0.500000 139 | Ke 0.0 0.0 0.0 140 | Ni 1.450000 141 | d 1.000000 142 | illum 2 143 | 144 | newmtl Material.135_princess_peaches_cast 145 | Ns 225.000000 146 | Ka 1.000000 1.000000 1.000000 147 | Kd 0.800000 0.800000 0.800000 148 | Ks 0.500000 0.500000 0.500000 149 | Ke 0.0 0.0 0.0 150 | Ni 1.450000 151 | d 1.000000 152 | illum 2 153 | 154 | newmtl Material.136_princess_peaches_cast 155 | Ns 225.000000 156 | Ka 1.000000 1.000000 1.000000 157 | Kd 0.800000 0.800000 0.800000 158 | Ks 0.500000 0.500000 0.500000 159 | Ke 0.0 0.0 0.0 160 | Ni 1.450000 161 | d 1.000000 162 | illum 2 163 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/res/terrain.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/res/test: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Camera.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * Camera class. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Camera { 9 | 10 | public static final Vec3 DA = new Vec3(); 11 | public static final Vec3 DB = new Vec3(); 12 | public static final Vec3 DISTANCE = new Vec3(0, -50, -500); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Edge.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | 6 | /** 7 | * Edge class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Edge { 12 | 13 | private final Face face; 14 | private final Vec3 a; 15 | private final Vec3 b; 16 | private double length; 17 | 18 | // points to inside 19 | private final Vec3 normal = new Vec3(); 20 | 21 | private final Vec3 vTmp1 = new Vec3(); 22 | private final Vec3 vTmp2 = new Vec3(); 23 | private final Vec3 vTmp3 = new Vec3(); 24 | 25 | public Edge(Face face, Vec3 a, Vec3 b) { 26 | this.face = face; 27 | this.a = a; 28 | this.b = b; 29 | updateLengthAndNormal(); 30 | } 31 | 32 | private void updateLengthAndNormal() { 33 | normal.set(b); 34 | normal.sub(a); 35 | length = normal.getLength(); 36 | normal.cross(face.getNormal()); 37 | normal.normalize(); 38 | } 39 | 40 | public Vec3 getA() { 41 | return a; 42 | } 43 | 44 | public Vec3 getB() { 45 | return b; 46 | } 47 | 48 | public boolean isInside(Vec3 contactPoint) { 49 | vTmp1.set(contactPoint); 50 | vTmp1.sub(a); 51 | return vTmp1.dot(normal) >= 0; 52 | } 53 | 54 | public Response checkCollision(Vec3 contactPoint, Sphere sphere, Response response) { 55 | vTmp1.set(contactPoint); 56 | vTmp1.sub(a); 57 | double dot = vTmp1.dot(normal); 58 | vTmp1.set(normal); 59 | vTmp1.scale(-dot); 60 | vTmp1.add(contactPoint); 61 | 62 | // keep contact point inside edge 63 | vTmp3.set(b); 64 | vTmp3.sub(a); 65 | vTmp2.set(vTmp1); 66 | vTmp2.sub(a); 67 | double dot1 = vTmp3.dot(vTmp3); 68 | double dot2 = vTmp3.dot(vTmp2); 69 | if (dot2 < 0) { 70 | vTmp1.set(a); 71 | } 72 | else if (dot2 > dot1) { 73 | vTmp1.set(b); 74 | } 75 | 76 | vTmp2.set(sphere.getPosition()); 77 | vTmp2.sub(vTmp1); 78 | 79 | response.setCollides(vTmp2.getLength() <= sphere.getRadius()); 80 | response.getContactPoint().set(vTmp1); 81 | response.getContactNormal().set(vTmp2); 82 | response.getContactNormal().normalize(); 83 | response.getContactNormal().scale(sphere.getRadius() - vTmp2.getLength()); 84 | 85 | return response; 86 | } 87 | 88 | public void draw(Graphics2D g, double scale) { 89 | g.setColor(Color.BLACK); 90 | g.drawLine((int) (scale * a.x), (int) (scale * a.y), (int) (scale * b.x), (int) (scale * b.y)); 91 | } 92 | 93 | private final Vec3 da = new Vec3(); 94 | private final Vec3 db = new Vec3(); 95 | private final Vec3 camera = new Vec3(0, -50, -500); 96 | 97 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 98 | 99 | da.set(a); 100 | da.sub(translate); 101 | da.rotateY(-angle); 102 | da.scale(scale); 103 | da.add(camera); 104 | 105 | db.set(b); 106 | db.sub(translate); 107 | db.rotateY(-angle); 108 | db.scale(scale); 109 | db.add(camera); 110 | 111 | if (da.z >= -0.1) return; 112 | if (db.z >= -0.1) return; 113 | 114 | // double ax = (scale * (a.x + translate.x)); 115 | // double ay = (scale * (a.y + translate.y)); 116 | // double az = (scale * (a.z + translate.z)); 117 | // double bx = (scale * (b.x + translate.x)); 118 | // double by = (scale * (b.y + translate.y)); 119 | // double bz = (scale * (b.z + translate.z)); 120 | 121 | int sax = (int) (500 * (da.x / -da.z)); 122 | int say = (int) (500 * (da.y / -da.z)); 123 | int sbx = (int) (500 * (db.x / -db.z)); 124 | int sby = (int) (500 * (db.y / -db.z)); 125 | 126 | g.setColor(Color.RED); 127 | g.fillOval(sax - 3, say - 3, 6, 6); 128 | g.fillOval(sbx - 3, sby - 3, 6, 6); 129 | g.setColor(Color.BLACK); 130 | g.drawLine(sax, say, sbx, sby); 131 | 132 | } 133 | 134 | @Override 135 | public String toString() { 136 | return "Edge{" + "face=" + face + ", a=" + a + ", b=" + b 137 | + ", normal=" + normal + '}'; 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Face.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Face class. 10 | * 11 | * @author Leonardo Ono (ono.leo80@gmail.com) 12 | */ 13 | public class Face { 14 | 15 | private final Vec3 normal = new Vec3(); 16 | private final List points = new ArrayList<>(); 17 | private final List edges = new ArrayList<>(); 18 | private final Response response = new Response(); 19 | 20 | public Face() { 21 | } 22 | 23 | public Vec3 getNormal() { 24 | return normal; 25 | } 26 | 27 | public List getPoints() { 28 | return points; 29 | } 30 | 31 | public void addPoint(Vec3 point) { 32 | points.add(point); 33 | } 34 | 35 | public void addPoint(double x, double y, double z) { 36 | points.add(new Vec3(x, y, z)); 37 | } 38 | 39 | public void close() { 40 | Vec3 v1 = new Vec3(points.get(0)); 41 | v1.sub(points.get(1)); 42 | Vec3 v2 = new Vec3(points.get(2)); 43 | v2.sub(points.get(1)); 44 | normal.set(v1); 45 | normal.cross(v2); 46 | normal.normalize(); 47 | 48 | for (int i = 0; i < points.size(); i++) { 49 | Vec3 a = points.get(i); 50 | Vec3 b = points.get((i + 1) % points.size()); 51 | Edge edge = new Edge(this, a, b); 52 | edges.add(edge); 53 | //System.out.println("edge: " + edge); 54 | } 55 | } 56 | private final Vec3 vTmp = new Vec3(); 57 | 58 | public Response checkCollision(Sphere sphere) { 59 | vTmp.set(sphere.getPosition()); // contact point in the triangle plane 60 | vTmp.sub(points.get(0)); 61 | double dot = vTmp.dot(normal); 62 | 63 | vTmp.set(normal); 64 | vTmp.scale(-dot); 65 | vTmp.add(sphere.getPosition()); 66 | 67 | //System.out.println("contact point: " + vTmp); 68 | 69 | for (Edge edge : edges) { 70 | if (!edge.isInside(vTmp)) { 71 | return edge.checkCollision(vTmp, sphere, response); 72 | } 73 | } 74 | 75 | response.setCollides(Math.abs(dot) <= sphere.getRadius()); 76 | response.getContactPoint().set(vTmp); 77 | response.getContactNormal().set(normal); 78 | response.getContactNormal().scale(sphere.getRadius() - dot); 79 | 80 | return response; 81 | } 82 | 83 | public void draw(Graphics2D g, double scale) { 84 | for (Edge edge : edges) { 85 | edge.draw(g, scale); 86 | } 87 | } 88 | 89 | 90 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 91 | for (Edge edge : edges) { 92 | edge.draw3D(g, scale, angle, translate); 93 | } 94 | 95 | if (response.isCollides()) { 96 | 97 | Camera.DA.set(response.getContactPoint()); 98 | Camera.DA.sub(translate); 99 | Camera.DA.rotateY(-angle); 100 | Camera.DA.scale(scale); 101 | Camera.DA.add(Camera.DISTANCE); 102 | 103 | int cpx = (int) (500 * (Camera.DA.x / -Camera.DA.z)); 104 | int cpy = (int) (500 * (Camera.DA.y / -Camera.DA.z)); 105 | 106 | g.setColor(Color.ORANGE); 107 | g.fillOval(cpx - 5, cpy - 5, 10, 10); 108 | 109 | // double x1 = (scale * response.getContactPoint().x); 110 | // double y1 = (scale * response.getContactPoint().y); 111 | // double z1 = (scale * response.getContactPoint().z); 112 | // double x2 = (scale * (response.getContactPoint().x + response.getContactNormal().x)); 113 | // double y2 = (scale * (response.getContactPoint().y + response.getContactNormal().y)); 114 | // double z2 = (scale * (response.getContactPoint().z + response.getContactNormal().z)); 115 | // 116 | // int csx1 = (int) (500 * (x1 / -z1)); 117 | // int csy1 = (int) (500 * (y1 / -z1)); 118 | // int csx2 = (int) (500 * (x2 / -z2)); 119 | // int csy2 = (int) (500 * (y2 / -z2)); 120 | // g.drawLine(csx1, csy1, csx2, csy2); 121 | } 122 | 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Input.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.event.KeyAdapter; 4 | import java.awt.event.KeyEvent; 5 | 6 | /** 7 | * Input class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Input extends KeyAdapter { 12 | 13 | public static boolean[] keyPressed = new boolean[256]; 14 | 15 | public static boolean isKeyPressed(int keyCode) { 16 | return keyPressed[keyCode]; 17 | } 18 | 19 | @Override 20 | public void keyPressed(KeyEvent e) { 21 | keyPressed[e.getKeyCode()] = true; 22 | } 23 | 24 | @Override 25 | public void keyReleased(KeyEvent e) { 26 | keyPressed[e.getKeyCode()] = false; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/MeshLoader.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import java.io.BufferedReader; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import test.Face; 10 | import test.Vec3; 11 | 12 | /** 13 | * MeshLoader class. 14 | * 15 | * @author Leonardo Ono (ono.leo80@gmail.com) 16 | */ 17 | public class MeshLoader { 18 | 19 | private final List vertices = new ArrayList<>(); 20 | private final List faces = new ArrayList<>(); 21 | 22 | private double scaleFactor; 23 | private double translateX; 24 | private double translateY; 25 | private double translateZ; 26 | 27 | private Vec3 min = new Vec3(); 28 | private Vec3 max = new Vec3(); 29 | 30 | public MeshLoader() { 31 | min.set(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 32 | max.set(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE); 33 | } 34 | 35 | public List getVertices() { 36 | return vertices; 37 | } 38 | 39 | public List getFaces() { 40 | return faces; 41 | } 42 | 43 | public double getScaleFactor() { 44 | return scaleFactor; 45 | } 46 | 47 | public double getTranslateX() { 48 | return translateX; 49 | } 50 | 51 | public double getTranslateY() { 52 | return translateY; 53 | } 54 | 55 | public double getTranslateZ() { 56 | return translateZ; 57 | } 58 | 59 | public Vec3 getMin() { 60 | return min; 61 | } 62 | 63 | public void setMin(Vec3 min) { 64 | this.min = min; 65 | } 66 | 67 | public Vec3 getMax() { 68 | return max; 69 | } 70 | 71 | public void setMax(Vec3 max) { 72 | this.max = max; 73 | } 74 | 75 | public void load(String meshRes, double scaleFactor 76 | , double translateX, double translateY, double translateZ) throws Exception { 77 | 78 | vertices.clear(); 79 | faces.clear(); 80 | 81 | this.scaleFactor = scaleFactor; 82 | this.translateX = translateX; 83 | this.translateY = translateY; 84 | this.translateZ = translateZ; 85 | 86 | InputStream is = MeshLoader.class.getResourceAsStream(meshRes); 87 | InputStreamReader isr = new InputStreamReader(is); 88 | BufferedReader br = new BufferedReader(isr); 89 | String line; 90 | while ((line = br.readLine()) != null) { 91 | if (line.startsWith("v ")) { 92 | parseVertex(line); 93 | } 94 | else if (line.startsWith("f ")) { 95 | parseFace(line); 96 | } 97 | } 98 | br.close(); 99 | 100 | // Vec3 tMin = new Vec3(-1, -1, -1); 101 | // Vec3 tMax = new Vec3(1, 1, 1); 102 | // 103 | // min.add(tMin); 104 | // max.add(tMax); 105 | 106 | //min.set(-100, -100, -100); 107 | //max.set(100, 100, 100); 108 | } 109 | 110 | private void parseVertex(String line) { 111 | String[] data = line.split(" "); 112 | double x = Double.parseDouble(data[1]); 113 | double y = Double.parseDouble(data[2]); 114 | double z = Double.parseDouble(data[3]); 115 | double stx = x * scaleFactor + translateX; 116 | double sty = y * scaleFactor + translateY; 117 | double stz = z * scaleFactor + translateZ; 118 | Vec3 v = new Vec3(stx, sty, stz); 119 | vertices.add(v); 120 | updateMinMax(v); 121 | } 122 | 123 | private void parseFace(String line) { 124 | String[] data = line.split(" "); 125 | //List ps = new ArrayList<>(); 126 | Face face = new Face(); 127 | for (int i = 1; i < data.length; i++) { 128 | String[] data2 = data[i].split("/"); 129 | int index = Integer.parseInt(data2[0]); 130 | //ps.add(vertices.get(index - 1)); 131 | Vec3 p = vertices.get(index - 1); 132 | face.addPoint(p); 133 | } 134 | face.close(); 135 | faces.add(face); 136 | } 137 | 138 | private void updateMinMax(Vec3 p) { 139 | if (p.x < min.x) { 140 | min.x = p.x; 141 | } 142 | if (p.y < min.y) { 143 | min.y = p.y; 144 | } 145 | if (p.z < min.z) { 146 | min.z = p.z; 147 | } 148 | if (p.x > max.x) { 149 | max.x = p.x; 150 | } 151 | if (p.y > max.y) { 152 | max.y = p.y; 153 | } 154 | if (p.z > max.z) { 155 | max.z = p.z; 156 | } 157 | } 158 | 159 | @Override 160 | public String toString() { 161 | return "MeshLoader{" + "vertices=" + vertices + ", faces=" + faces 162 | + ", scaleFactor=" + scaleFactor + ", translateX=" + translateX 163 | + ", translateY=" + translateY + '}'; 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Player.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import java.awt.Graphics2D; 5 | import java.awt.event.KeyEvent; 6 | import test.Input; 7 | import test.Sphere; 8 | import test.Vec3; 9 | import test.partition.Box; 10 | 11 | /** 12 | * Player class. 13 | * 14 | * @author Leonardo Ono (ono.leo80@gmail.com) 15 | */ 16 | public class Player { 17 | 18 | private Sphere collider = new Sphere(); 19 | private double angle; 20 | private final Vec3 velocity = new Vec3(); 21 | private final Box box = new Box(); 22 | 23 | public Player() { 24 | collider = new Sphere(0.5, 0, 1, -1); 25 | } 26 | 27 | public Sphere getCollider() { 28 | return collider; 29 | } 30 | 31 | public double getAngle() { 32 | return angle; 33 | } 34 | 35 | public Vec3 getVelocity() { 36 | return velocity; 37 | } 38 | 39 | public void update() { 40 | if (Input.isKeyPressed(KeyEvent.VK_LEFT)) { 41 | //sphere.getPosition().x -= 0.03; 42 | angle -= 0.025; 43 | } 44 | else if (Input.isKeyPressed(KeyEvent.VK_RIGHT)) { 45 | //sphere.getPosition().x += 0.03; 46 | angle += 0.025; 47 | } 48 | double speed = 0; 49 | if (Input.isKeyPressed(KeyEvent.VK_UP)) { 50 | speed = -0.25; 51 | //sphere.getPosition().y += 0.03; 52 | } 53 | else if (Input.isKeyPressed(KeyEvent.VK_DOWN)) { 54 | speed = 0.25; 55 | //sphere.getPosition().y -= 0.03; 56 | } 57 | velocity.x = 0; 58 | velocity.z = 0; 59 | 60 | if (speed != 0) { 61 | double dx = speed * Math.cos(angle + Math.toRadians(90)); 62 | double dz = speed * Math.sin(angle + Math.toRadians(90)); 63 | velocity.x = dx; 64 | velocity.z = dz; 65 | } 66 | 67 | if (Input.isKeyPressed(KeyEvent.VK_A)) { 68 | speed = 0.25; 69 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 70 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 71 | velocity.x = dx; 72 | velocity.z = dz; 73 | } 74 | else if (Input.isKeyPressed(KeyEvent.VK_D)) { 75 | speed = -0.25; 76 | double dx = speed * Math.cos(angle - Math.toRadians(180)); 77 | double dz = speed * Math.sin(angle - Math.toRadians(180)); 78 | velocity.x = dx; 79 | velocity.z = dz; 80 | } 81 | 82 | if (Input.isKeyPressed(KeyEvent.VK_SPACE)) { 83 | velocity.y += 0.05; 84 | if (velocity.y > 0.2) { 85 | velocity.y = 0.2; 86 | } 87 | //sphere.getPosition().y -= 0.03; 88 | } 89 | 90 | // gravity 91 | velocity.y -= 0.005; 92 | 93 | 94 | 95 | // if (Input.isKeyPressed(KeyEvent.VK_Q)) { 96 | // collider.getPosition().y -= 0.025; 97 | // } 98 | // else if (Input.isKeyPressed(KeyEvent.VK_A)) { 99 | // collider.getPosition().y += 0.025; 100 | // } 101 | 102 | //System.out.println("player position: " + collider.getPosition()); 103 | 104 | } 105 | 106 | public void draw(Graphics2D g, double scale) { 107 | collider.draw(g, scale); 108 | } 109 | 110 | public void draw3D(Graphics2D g, double scale) { 111 | collider.draw3D(g, scale, angle, collider.getPosition()); 112 | } 113 | 114 | public Box getBox() { 115 | box.getMin().set(collider.getPosition()); 116 | box.getMin().x -= collider.getRadius(); 117 | box.getMin().y -= collider.getRadius(); 118 | box.getMin().z -= collider.getRadius(); 119 | box.getMax().set(collider.getPosition()); 120 | box.getMax().x += collider.getRadius(); 121 | box.getMax().y += collider.getRadius(); 122 | box.getMax().z += collider.getRadius(); 123 | box.updateLength(); 124 | return box; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Response.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * Response class. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Response { 9 | 10 | private boolean collides; 11 | private final Vec3 contactPoint = new Vec3(); 12 | private final Vec3 contactNormal = new Vec3(); 13 | 14 | public boolean isCollides() { 15 | return collides; 16 | } 17 | 18 | public void setCollides(boolean collides) { 19 | this.collides = collides; 20 | } 21 | 22 | public Vec3 getContactPoint() { 23 | return contactPoint; 24 | } 25 | 26 | public Vec3 getContactNormal() { 27 | return contactNormal; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "Response{" + "collides=" + collides 33 | + ", contactPoint=" + contactPoint 34 | + ", contactNormal=" + contactNormal + '}'; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Sphere.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | 6 | /** 7 | * Sphere class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class Sphere { 12 | 13 | private double radius; 14 | private Vec3 position = new Vec3(); 15 | 16 | public Sphere() { 17 | } 18 | 19 | public Sphere(double radius) { 20 | this.radius = radius; 21 | } 22 | 23 | public Sphere(double radius, double x, double y, double z) { 24 | this.radius = radius; 25 | this.position.set(x, y, z); 26 | } 27 | 28 | public double getRadius() { 29 | return radius; 30 | } 31 | 32 | public void setRadius(double radius) { 33 | this.radius = radius; 34 | } 35 | 36 | public Vec3 getPosition() { 37 | return position; 38 | } 39 | 40 | public void setPosition(Vec3 position) { 41 | this.position = position; 42 | } 43 | 44 | public void draw(Graphics2D g, double scale) { 45 | g.setColor(Color.BLACK); 46 | int diameter = (int) (2 * radius * scale); 47 | g.drawOval((int) (scale * (position.x - radius)), (int) (scale * (position.y - radius)), diameter, diameter); 48 | 49 | // if (response.isCollides()) { 50 | // g.setColor(Color.RED); 51 | // int x1 = (int) (scale * response.getContactPoint().x); 52 | // int y1 = (int) (scale * response.getContactPoint().y); 53 | // int x2 = (int) (scale * (response.getContactPoint().x + response.getContactNormal().x)); 54 | // int y2 = (int) (scale * (response.getContactPoint().y + response.getContactNormal().y)); 55 | // g.drawLine(x1, y1, x2, y2); 56 | // } 57 | } 58 | 59 | public void draw3D(Graphics2D g, double scale, double angle, Vec3 translate) { 60 | Camera.DA.set(position); 61 | Camera.DA.sub(translate); 62 | Camera.DA.rotateY(-angle); 63 | Camera.DA.scale(scale); 64 | Camera.DA.add(Camera.DISTANCE); 65 | 66 | Camera.DB.set(position); 67 | Camera.DB.sub(translate); 68 | Camera.DB.rotateY(-angle); 69 | Camera.DB.y -= radius; 70 | Camera.DB.scale(scale); 71 | Camera.DB.add(Camera.DISTANCE); 72 | 73 | 74 | // double ax = scale * (position.x - radius + translate.x); 75 | // double ay = scale * (position.y - radius + translate.y); 76 | // double ax2 = scale * (position.x + radius + translate.x); 77 | // double ay2 = scale * (position.y + radius + translate.y); 78 | // double az = scale * (position.z + translate.z); 79 | 80 | int sax = (int) (500 * (Camera.DA.x / -Camera.DA.z)); 81 | int say = (int) (500 * (Camera.DA.y / -Camera.DA.z)); 82 | int sax2 = (int) (500 * (Camera.DB.x / -Camera.DA.z)); 83 | int say2 = (int) (500 * (Camera.DB.y / -Camera.DA.z)); 84 | int sr = Math.abs(sax - sax2); // screen radius 85 | 86 | g.setColor(Color.BLACK); 87 | int radius = Math.abs(say - say2); 88 | int diameter = radius * 2; 89 | g.drawOval(sax - radius, say - radius, diameter, diameter); 90 | 91 | // draw contact point 92 | 93 | } 94 | 95 | @Override 96 | public String toString() { 97 | return "Sphere{" + "radius=" + radius + ", position=" + position + '}'; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/Vec3.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * Vec3 class. 5 | * 6 | * @author Leonardo Ono (ono.leo80@gmail.com) 7 | */ 8 | public class Vec3 { 9 | 10 | public double x; 11 | public double y; 12 | public double z; 13 | 14 | public Vec3() { 15 | } 16 | 17 | public Vec3(double x, double y, double z) { 18 | this.x = x; 19 | this.y = y; 20 | this.z = z; 21 | } 22 | 23 | public Vec3(Vec3 v) { 24 | this.x = v.x; 25 | this.y = v.y; 26 | this.z = v.z; 27 | } 28 | 29 | public Vec3(Vec3 a, Vec3 b) { 30 | this.x = b.x - a.x; 31 | this.y = b.y - a.y; 32 | this.z = b.z - a.z; 33 | } 34 | 35 | public void set(double x, double y, double z) { 36 | this.x = x; 37 | this.y = y; 38 | this.z = z; 39 | } 40 | 41 | public void set(Vec3 v) { 42 | this.x = v.x; 43 | this.y = v.y; 44 | this.z = v.z; 45 | } 46 | 47 | public void add(Vec3 v) { 48 | this.x += v.x; 49 | this.y += v.y; 50 | this.z += v.z; 51 | } 52 | 53 | public void sub(Vec3 v) { 54 | this.x -= v.x; 55 | this.y -= v.y; 56 | this.z -= v.z; 57 | } 58 | 59 | public void scale(double s) { 60 | scale(s, s, s); 61 | } 62 | 63 | public void scale(double sx, double sy, double sz) { 64 | this.x *= sx; 65 | this.y *= sy; 66 | this.z *= sz; 67 | } 68 | 69 | public double getLength() { 70 | return Math.sqrt(x * x + y * y + z * z); 71 | } 72 | 73 | public void normalize() { 74 | double length = getLength(); 75 | if (length != 0) { 76 | x /= length; 77 | y /= length; 78 | z /= length; 79 | } 80 | } 81 | 82 | public double dot(Vec3 v) { 83 | return x * v.x + y * v.y + z * v.z; 84 | } 85 | 86 | public double dot2D(Vec3 v) { 87 | return x * v.x + z * v.z; 88 | } 89 | 90 | public void cross(Vec3 v) { 91 | double cx = y * v.z - z * v.y; 92 | double cy = z * v.x - x * v.z; 93 | double cz = x * v.y - y * v.x; 94 | x = cx; 95 | y = cy; 96 | z = cz; 97 | } 98 | 99 | public double cross2D(Vec3 v) { 100 | return x * v.z - z * v.x; 101 | } 102 | 103 | public void rotateY(double angle) { 104 | double s = Math.sin(angle); 105 | double c = Math.cos(angle); 106 | double nx = x * c - z * s; 107 | double nz = x * s + z * c; 108 | set(nx, y, nz); 109 | } 110 | @Override 111 | public String toString() { 112 | return "Vec3{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/View.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import test.Input; 5 | import java.awt.Dimension; 6 | import java.awt.Graphics; 7 | import java.awt.Graphics2D; 8 | import javax.swing.JFrame; 9 | import javax.swing.JPanel; 10 | import javax.swing.SwingUtilities; 11 | 12 | /** 13 | * Java 3D Terrain Mesh vs Ball Player Collision Test 14 | * 15 | * @author Leonardo Ono (ono.leo80@gmail.com); 16 | */ 17 | public class View extends JPanel { 18 | 19 | private final World world = new World(); 20 | 21 | public View() { 22 | } 23 | 24 | public void start() { 25 | addKeyListener(new Input()); 26 | } 27 | 28 | @Override 29 | protected void paintComponent(Graphics g) { 30 | super.paintComponent(g); 31 | update(); 32 | draw((Graphics2D) g); 33 | try { 34 | Thread.sleep(1000 / 60); 35 | } catch (InterruptedException ex) { 36 | } 37 | repaint(); 38 | } 39 | 40 | private void update() { 41 | world.update(); 42 | 43 | } 44 | 45 | private void draw(Graphics2D g) { 46 | g.clearRect(0, 0, getWidth(), getHeight()); 47 | //g.drawLine(0, 0, getWidth(), getHeight()); 48 | 49 | g.translate(400, 300); 50 | g.scale(1, -1); 51 | 52 | world.draw(g); 53 | } 54 | 55 | public static void main(String[] args) { 56 | SwingUtilities.invokeLater(() -> { 57 | View view = new View(); 58 | view.setPreferredSize(new Dimension(800, 600)); 59 | JFrame frame = new JFrame(); 60 | frame.setTitle("Java 3D Terrain Mesh vs Ball Player Collision with Octree Spatial Partition"); 61 | frame.getContentPane().add(view); 62 | frame.setResizable(false); 63 | frame.pack(); 64 | frame.setLocationRelativeTo(null); 65 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 66 | frame.setVisible(true); 67 | view.requestFocus(); 68 | view.start(); 69 | }); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/World.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import java.awt.Graphics2D; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.logging.Level; 8 | import java.util.logging.Logger; 9 | import test.partition.Octree; 10 | 11 | /** 12 | * World class. 13 | * 14 | * @author Leonardo Ono (ono.leo80@gmail.com) 15 | */ 16 | public class World { 17 | 18 | private final List faces = new ArrayList<>(); 19 | private final Player player = new Player(); 20 | 21 | private final List collidedResponses = new ArrayList<>(); 22 | private final Vec3 resultPush = new Vec3(); 23 | 24 | private MeshLoader terrain; 25 | 26 | private Octree spatialPartition; 27 | private final List retrievedFaces = new ArrayList<>(); 28 | 29 | public World() { 30 | createTest2(); 31 | } 32 | 33 | private void createTest2() { 34 | terrain = new MeshLoader(); 35 | try { 36 | //terrain.load("/res/terrain.obj", 20, 0, -5, 0); 37 | terrain.load("/res/princess_peaches_castle_(outside).obj", 20, 0, -100, 150); 38 | //terrain.load("/res/cs.obj", 1, 0, -5, 7); 39 | 40 | } catch (Exception ex) { 41 | Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex); 42 | System.exit(1); 43 | } 44 | faces.addAll(terrain.getFaces()); 45 | spatialPartition = new Octree(terrain.getMin(), terrain.getMax()); 46 | spatialPartition.addFaces(terrain.getFaces()); 47 | 48 | //player.getCollider().getPosition().set(25, -13, -26); // test for cs.obj 49 | } 50 | 51 | private void createTest() { 52 | Face face = new Face(); 53 | face.addPoint(2, 0, 2); 54 | face.addPoint(-2, 0, -2); 55 | face.addPoint(2, 0, -2); 56 | face.close(); 57 | faces.add(face); 58 | 59 | Face face2 = new Face(); 60 | face2.addPoint(-2, 0, 2); 61 | face2.addPoint(-2, 0, -2); 62 | face2.addPoint(2, 0, 2); 63 | face2.close(); 64 | faces.add(face2); 65 | 66 | Face face3 = new Face(); 67 | face3.addPoint(-2, 0, -2); 68 | face3.addPoint(-2, 2, -20.0); 69 | face3.addPoint(2, 2, -20.0); 70 | face3.close(); 71 | faces.add(face3); 72 | 73 | Face face4 = new Face(); 74 | face4.addPoint(-2, 0, -2); 75 | face4.addPoint(2, 2, -20.0); 76 | face4.addPoint(2, 0, -2); 77 | face4.close(); 78 | faces.add(face4); 79 | 80 | } 81 | 82 | public void update() { 83 | player.update(); 84 | 85 | // detect collision with polygons retrieved from spatial partition 86 | collidedResponses.clear(); 87 | 88 | retrievedFaces.clear(); 89 | spatialPartition.retrieveFaces(player.getBox(), retrievedFaces); 90 | 91 | // System.out.println("total faces:" + faces.size() 92 | // + " / retrieved faces: " + retrievedFaces.size()); 93 | 94 | for (Face face : retrievedFaces) { 95 | Response response = face.checkCollision(player.getCollider()); 96 | if (response.isCollides()) { 97 | collidedResponses.add(response); 98 | } 99 | } 100 | 101 | resultPush.set(0, 0, 0); 102 | 103 | // collision response 104 | if (!collidedResponses.isEmpty()) { 105 | collidedResponses.forEach((response) -> { 106 | resultPush.add(response.getContactNormal()); 107 | }); 108 | //resultPush.scale(1.0 / collidedResponses.size()); 109 | player.getCollider().getPosition().add(resultPush); 110 | } 111 | 112 | // fix velocity so the player can slide when colliding with walls 113 | if (!collidedResponses.isEmpty()) { 114 | resultPush.normalize(); 115 | double dot = resultPush.dot(player.getVelocity()); 116 | resultPush.scale(dot); 117 | player.getVelocity().sub(resultPush); 118 | } 119 | 120 | // update player position 121 | player.getCollider().getPosition().add(player.getVelocity()); 122 | 123 | System.out.println("player position: " + player.getCollider().getPosition()); 124 | } 125 | 126 | public void draw(Graphics2D g) { 127 | double scale = 50; 128 | 129 | //player.draw(g, scale); 130 | //face.draw(g, scale); 131 | 132 | player.draw3D(g, scale); 133 | 134 | // for (int i = 0; i < 100; i++) { 135 | // Face face = faces.get(i); 136 | // face.draw3D(g, scale, player.getAngle(), player.getCollider().getPosition()); 137 | // } 138 | 139 | faces.forEach((face) -> { 140 | face.draw3D(g, scale, player.getAngle() 141 | , player.getCollider().getPosition()); 142 | }); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/partition/Box.java: -------------------------------------------------------------------------------- 1 | package test.partition; 2 | 3 | import test.Vec3; 4 | 5 | /** 6 | * Box class. 7 | * 8 | * @author Leonardo Ono (ono.leo80@gmail.com) 9 | */ 10 | public class Box { 11 | 12 | protected final Vec3 min = new Vec3(); 13 | protected final Vec3 max = new Vec3(); 14 | protected final Vec3 length = new Vec3(); 15 | 16 | public Box() { 17 | } 18 | 19 | 20 | public Box(Vec3 min, Vec3 max) { 21 | this.min.set(min); 22 | this.max.set(max); 23 | updateLengthInternal(); 24 | } 25 | 26 | public void updateLength() { 27 | updateLengthInternal(); 28 | } 29 | 30 | private void updateLengthInternal() { 31 | length.set(max); 32 | length.sub(min); 33 | length.x = Math.abs(length.x); 34 | length.y = Math.abs(length.y); 35 | length.z = Math.abs(length.z); 36 | } 37 | 38 | public Vec3 getMin() { 39 | return min; 40 | } 41 | 42 | public Vec3 getMax() { 43 | return max; 44 | } 45 | 46 | public Vec3 getLength() { 47 | return length; 48 | } 49 | 50 | public boolean intersects(Box box) { 51 | double xt1 = (box.length.x + length.x); 52 | double xt2 = Math.abs(Math.max(max.x, box.max.x) 53 | - Math.min(min.x, box.min.x)); 54 | 55 | if (xt2 > xt1) { 56 | return false; 57 | } 58 | 59 | double yt1 = (box.length.y + length.y); 60 | double yt2 = Math.abs(Math.max(max.y, box.max.y) 61 | - Math.min(min.y, box.min.y)); 62 | 63 | if (yt2 > yt1) { 64 | return false; 65 | } 66 | 67 | double zt1 = (box.length.z + length.z); 68 | double zt2 = Math.abs(Math.max(max.z, box.max.z) 69 | - Math.min(min.z, box.min.z)); 70 | 71 | return zt2 <= zt1; 72 | } 73 | 74 | public boolean isCompletelyInside(Box box) { 75 | return min.x >= box.min.x && min.x <= box.max.x 76 | && max.x >= box.min.x && max.x <= box.max.x 77 | && min.y >= box.min.y && min.y <= box.max.y 78 | && max.y >= box.min.y && max.y <= box.max.y 79 | && min.z >= box.min.z && min.z <= box.max.z 80 | && max.z >= box.min.z && max.z <= box.max.z; 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return "Box{" + "min=" + min + ", max=" + max + '}'; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/partition/FaceBox.java: -------------------------------------------------------------------------------- 1 | package test.partition; 2 | 3 | import test.Face; 4 | import test.Vec3; 5 | 6 | /** 7 | * FaceBox class. 8 | * 9 | * @author Leonardo Ono (ono.leo80@gmail.com) 10 | */ 11 | public class FaceBox extends Box { 12 | 13 | private Face face; 14 | 15 | public FaceBox() { 16 | } 17 | 18 | public FaceBox(Face face) { 19 | setFaceInternal(face); 20 | } 21 | 22 | public Face getFace() { 23 | return face; 24 | } 25 | 26 | public void setFace(Face face) { 27 | setFaceInternal(face); 28 | } 29 | 30 | private void setFaceInternal(Face face) { 31 | this.face = face; 32 | 33 | double minX = Double.MAX_VALUE; 34 | double minY = Double.MAX_VALUE; 35 | double minZ = Double.MAX_VALUE; 36 | double maxX = -Double.MAX_VALUE; 37 | double maxY = -Double.MAX_VALUE; 38 | double maxZ = -Double.MAX_VALUE; 39 | for (Vec3 point : face.getPoints()) { 40 | if (point.x < minX) { 41 | minX = point.x; 42 | } 43 | if (point.y < minY) { 44 | minY = point.y; 45 | } 46 | if (point.z < minZ) { 47 | minZ = point.z; 48 | } 49 | 50 | if (point.x > maxX) { 51 | maxX = point.x; 52 | } 53 | if (point.y > maxY) { 54 | maxY = point.y; 55 | } 56 | if (point.z > maxZ) { 57 | maxZ = point.z; 58 | } 59 | } 60 | min.set(minX, minY, minZ); 61 | max.set(maxX, maxY, maxZ); 62 | updateLength(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/partition/Node.java: -------------------------------------------------------------------------------- 1 | package test.partition; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import test.Face; 6 | import test.Vec3; 7 | 8 | /** 9 | * Node class. 10 | * 11 | * @author Leonardo Ono (ono.leo80@gmail.com) 12 | */ 13 | public class Node extends Box { 14 | 15 | protected List faces = new ArrayList<>(); 16 | protected Node[] children = new Node[8]; 17 | protected FaceBox boxTmp = new FaceBox(); 18 | protected boolean partitioned; 19 | 20 | public Node(Vec3 min, Vec3 max) { 21 | super(min, max); 22 | } 23 | 24 | protected void partition() { 25 | Vec3 b1Min = new Vec3(min.x, min.y, min.z); 26 | 27 | Vec3 b1Max = new Vec3(min.x + length.x / 2 28 | , min.y + length.y / 2, min.z + length.z / 2); 29 | 30 | Vec3 b2Min = new Vec3(min.x + length.x / 2, min.y, min.z); 31 | 32 | Vec3 b2Max = new Vec3(min.x + length.x 33 | , min.y + length.y / 2, min.z + length.z / 2); 34 | 35 | Vec3 b3Min = new Vec3(min.x, min.y, min.z + length.z / 2); 36 | 37 | Vec3 b3Max = new Vec3(min.x + length.x / 2 38 | , min.y + length.y / 2, min.z + length.z); 39 | 40 | Vec3 b4Min = new Vec3(min.x + length.x / 2 41 | , min.y, min.z + length.z / 2); 42 | 43 | Vec3 b4Max = new Vec3(min.x + length.x 44 | , min.y + length.y / 2, min.z + length.z); 45 | 46 | Vec3 b5Min = new Vec3(min.x, min.y + length.y / 2, min.z); 47 | 48 | Vec3 b5Max = new Vec3(min.x + length.x / 2 49 | , min.y + length.y, min.z + length.z / 2); 50 | 51 | Vec3 b6Min = new Vec3(min.x + length.x / 2 52 | , min.y + length.y / 2, min.z); 53 | 54 | Vec3 b6Max = new Vec3(min.x + length.x 55 | , min.y + length.y, min.z + length.z / 2); 56 | 57 | Vec3 b7Min = new Vec3(min.x 58 | , min.y + length.y / 2, min.z + length.z / 2); 59 | 60 | Vec3 b7Max = new Vec3(min.x + length.x / 2 61 | , min.y + length.y, min.z + length.z); 62 | 63 | Vec3 b8Min = new Vec3(min.x + length.x / 2 64 | , min.y + length.y / 2, min.z + length.z / 2); 65 | 66 | Vec3 b8Max = new Vec3(min.x + length.x 67 | , min.y + length.y, min.z + length.z); 68 | 69 | Vec3[][] minMax = { 70 | {b1Min, b1Max}, 71 | {b2Min, b2Max}, 72 | {b3Min, b3Max}, 73 | {b4Min, b4Max}, 74 | {b5Min, b5Max}, 75 | {b6Min, b6Max}, 76 | {b7Min, b7Max}, 77 | {b8Min, b8Max}, 78 | }; 79 | 80 | for (int i = 0; i < 8; i++) { 81 | children[i] = new Node(minMax[i][0], minMax[i][1]); 82 | } 83 | 84 | partitioned = true; 85 | } 86 | 87 | public void addFace(Face face) { 88 | if (!partitioned) { 89 | partition(); 90 | } 91 | 92 | boolean addFaceInThisNode = true; 93 | 94 | boxTmp.setFace(face); 95 | for (Node node : children) { 96 | if (boxTmp.isCompletelyInside(node)) { 97 | addFaceInThisNode = false; 98 | node.addFace(face); 99 | break; 100 | } 101 | } 102 | 103 | if (addFaceInThisNode) { 104 | faces.add(new FaceBox(face)); 105 | } 106 | } 107 | 108 | public void retrieveFaces(Box box, List result) { 109 | if (partitioned) { 110 | for (Node node : children) { 111 | if (node.intersects(box)) { 112 | node.retrieveFaces(box, result); 113 | } 114 | } 115 | } 116 | if (intersects(box)) { 117 | for (FaceBox faceBox : faces) { 118 | if (faceBox.intersects(box)) { 119 | result.add(faceBox.getFace()); 120 | } 121 | } 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /Java3DMeshVsSphereCollisionWithOctreeSpatialPartitionTest2/src/test/partition/Octree.java: -------------------------------------------------------------------------------- 1 | package test.partition; 2 | 3 | import java.util.List; 4 | import test.Face; 5 | import test.Vec3; 6 | 7 | /** 8 | * Octree class. 9 | * 10 | * @author Leonardo Ono (ono.leo80@gmail.com) 11 | */ 12 | public class Octree extends Node { 13 | 14 | public Octree(Vec3 min, Vec3 max) { 15 | super(min, max); 16 | } 17 | 18 | public void addFaces(List facesAdd) { 19 | facesAdd.forEach((faceAdd) -> { 20 | addFace(faceAdd); 21 | }); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java3DMeshVsSphereCollisionTest 2 | Java 3D Mesh vs Sphere Collision Test. Video: https://youtu.be/v1riwEd0BDA 3 | 4 | old vs new comparisson videos: 5 | https://youtu.be/E4jRmhJ0w5Q 6 | https://youtu.be/Sh8L4jSQftY 7 | --------------------------------------------------------------------------------