├── .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 |
--------------------------------------------------------------------------------