remove 8 octree optimization files from trunk
per discussion at http://hub.jmonkeyengine.org/forum/topic/proposed-removal-of-octree-and-related-files git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@11093 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
f5ccf45aed
commit
5eb5f0d2cc
@ -1,163 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3test.tools;
|
|
||||||
|
|
||||||
import com.jme3.app.SimpleApplication;
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
|
||||||
import com.jme3.light.DirectionalLight;
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.material.MaterialList;
|
|
||||||
import com.jme3.math.ColorRGBA;
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.post.SceneProcessor;
|
|
||||||
import com.jme3.renderer.RenderManager;
|
|
||||||
import com.jme3.renderer.ViewPort;
|
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.scene.debug.WireBox;
|
|
||||||
import com.jme3.scene.plugins.ogre.MeshLoader;
|
|
||||||
import com.jme3.scene.plugins.ogre.OgreMeshKey;
|
|
||||||
import com.jme3.texture.FrameBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import jme3tools.optimize.FastOctnode;
|
|
||||||
import jme3tools.optimize.Octree;
|
|
||||||
|
|
||||||
|
|
||||||
public class TestOctree extends SimpleApplication implements SceneProcessor {
|
|
||||||
|
|
||||||
private Octree tree;
|
|
||||||
private FastOctnode fastRoot;
|
|
||||||
private Geometry[] globalGeoms;
|
|
||||||
private BoundingBox octBox;
|
|
||||||
|
|
||||||
private Set<Geometry> renderSet = new HashSet<Geometry>(300);
|
|
||||||
private Material mat, mat2;
|
|
||||||
private WireBox box = new WireBox(1,1,1);
|
|
||||||
|
|
||||||
public static void main(String[] args){
|
|
||||||
TestOctree app = new TestOctree();
|
|
||||||
app.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void simpleInitApp() {
|
|
||||||
// this.flyCam.setMoveSpeed(2000);
|
|
||||||
// this.cam.setFrustumFar(10000);
|
|
||||||
// mat = new Material(assetManager, "Common/MatDefs/Misc/WireColor.j3md");
|
|
||||||
// mat.setColor("Color", ColorRGBA.White);
|
|
||||||
|
|
||||||
// mat2 = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
|
|
||||||
|
|
||||||
assetManager.registerLocator("quake3level.zip", com.jme3.asset.plugins.ZipLocator.class);
|
|
||||||
MaterialList matList = (MaterialList) assetManager.loadAsset("Scene.material");
|
|
||||||
OgreMeshKey key = new OgreMeshKey("main.meshxml", matList);
|
|
||||||
Spatial scene = assetManager.loadModel(key);
|
|
||||||
|
|
||||||
// Spatial scene = assetManager.loadModel("Models/Teapot/teapot.obj");
|
|
||||||
// scene.scale(3);
|
|
||||||
|
|
||||||
DirectionalLight dl = new DirectionalLight();
|
|
||||||
dl.setColor(ColorRGBA.White);
|
|
||||||
dl.setDirection(new Vector3f(-1, -1, -1).normalize());
|
|
||||||
rootNode.addLight(dl);
|
|
||||||
|
|
||||||
DirectionalLight dl2 = new DirectionalLight();
|
|
||||||
dl2.setColor(ColorRGBA.White);
|
|
||||||
dl2.setDirection(new Vector3f(1, -1, 1).normalize());
|
|
||||||
rootNode.addLight(dl2);
|
|
||||||
|
|
||||||
// generate octree
|
|
||||||
// tree = new Octree(scene, 20000);
|
|
||||||
tree = new Octree(scene);
|
|
||||||
tree.construct(50, 0.01f, 50);
|
|
||||||
|
|
||||||
ArrayList<Geometry> globalGeomList = new ArrayList<Geometry>();
|
|
||||||
tree.createFastOctnodes(globalGeomList);
|
|
||||||
tree.generateFastOctnodeLinks();
|
|
||||||
|
|
||||||
for (Geometry geom : globalGeomList){
|
|
||||||
geom.addLight(dl);
|
|
||||||
geom.addLight(dl2);
|
|
||||||
geom.updateGeometricState();
|
|
||||||
}
|
|
||||||
|
|
||||||
globalGeoms = globalGeomList.toArray(new Geometry[0]);
|
|
||||||
fastRoot = tree.getFastRoot();
|
|
||||||
octBox = tree.getBound();
|
|
||||||
|
|
||||||
viewPort.addProcessor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initialize(RenderManager rm, ViewPort vp) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reshape(ViewPort vp, int w, int h) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInitialized() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void preFrame(float tpf) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postQueue(RenderQueue rq) {
|
|
||||||
renderSet.clear();
|
|
||||||
//tree.generateRenderSet(renderSet, cam);
|
|
||||||
fastRoot.generateRenderSet(globalGeoms, renderSet, cam, octBox, true);
|
|
||||||
// System.out.println("Geoms: "+renderSet.size());
|
|
||||||
int tris = 0;
|
|
||||||
|
|
||||||
for (Geometry geom : renderSet){
|
|
||||||
tris += geom.getTriangleCount();
|
|
||||||
// geom.setMaterial(mat2);
|
|
||||||
rq.addToQueue(geom, geom.getQueueBucket());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matrix4f transform = new Matrix4f();
|
|
||||||
// transform.setScale(0.2f, 0.2f, 0.2f);
|
|
||||||
// System.out.println("Tris: "+tris);
|
|
||||||
|
|
||||||
// tree.renderBounds(rq, transform, box, mat);
|
|
||||||
|
|
||||||
// renderManager.flushQueue(viewPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postFrame(FrameBuffer out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanup() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,169 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
|
||||||
import com.jme3.renderer.Camera;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class FastOctnode {
|
|
||||||
|
|
||||||
int offset;
|
|
||||||
int length;
|
|
||||||
FastOctnode child;
|
|
||||||
FastOctnode next;
|
|
||||||
|
|
||||||
private static final BoundingBox tempBox = new BoundingBox();
|
|
||||||
|
|
||||||
public int getSide(){
|
|
||||||
return ((offset & 0xE0000000) >> 29) & 0x7;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSide(int side){
|
|
||||||
offset &= 0x1FFFFFFF;
|
|
||||||
offset |= (side << 29);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffset(int offset){
|
|
||||||
if (offset < 0 || offset > 20000000){
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.offset &= 0xE0000000;
|
|
||||||
this.offset |= offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOffset(){
|
|
||||||
return this.offset & 0x1FFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateRenderSetNoCheck(Geometry[] globalGeomList, Set<Geometry> renderSet, Camera cam){
|
|
||||||
if (length != 0){
|
|
||||||
int start = getOffset();
|
|
||||||
int end = start + length;
|
|
||||||
for (int i = start; i < end; i++){
|
|
||||||
renderSet.add(globalGeomList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FastOctnode node = child;
|
|
||||||
while (node != null){
|
|
||||||
node.generateRenderSetNoCheck(globalGeomList, renderSet, cam);
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void findChildBound(BoundingBox bbox, int side){
|
|
||||||
float extent = bbox.getXExtent() * 0.5f;
|
|
||||||
bbox.getCenter().set(bbox.getCenter().x + extent * Octnode.extentMult[side].x,
|
|
||||||
bbox.getCenter().y + extent * Octnode.extentMult[side].y,
|
|
||||||
bbox.getCenter().z + extent * Octnode.extentMult[side].z);
|
|
||||||
bbox.setXExtent(extent);
|
|
||||||
bbox.setYExtent(extent);
|
|
||||||
bbox.setZExtent(extent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateRenderSet(Geometry[] globalGeomList, Set<Geometry> renderSet, Camera cam, BoundingBox parentBox, boolean isRoot){
|
|
||||||
tempBox.setCenter(parentBox.getCenter());
|
|
||||||
tempBox.setXExtent(parentBox.getXExtent());
|
|
||||||
tempBox.setYExtent(parentBox.getYExtent());
|
|
||||||
tempBox.setZExtent(parentBox.getZExtent());
|
|
||||||
|
|
||||||
if (!isRoot){
|
|
||||||
findChildBound(tempBox, getSide());
|
|
||||||
}
|
|
||||||
|
|
||||||
tempBox.setCheckPlane(0);
|
|
||||||
cam.setPlaneState(0);
|
|
||||||
Camera.FrustumIntersect result = cam.contains(tempBox);
|
|
||||||
if (result != Camera.FrustumIntersect.Outside){
|
|
||||||
if (length != 0){
|
|
||||||
int start = getOffset();
|
|
||||||
int end = start + length;
|
|
||||||
for (int i = start; i < end; i++){
|
|
||||||
renderSet.add(globalGeomList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FastOctnode node = child;
|
|
||||||
|
|
||||||
float x = tempBox.getCenter().x;
|
|
||||||
float y = tempBox.getCenter().y;
|
|
||||||
float z = tempBox.getCenter().z;
|
|
||||||
float ext = tempBox.getXExtent();
|
|
||||||
|
|
||||||
while (node != null){
|
|
||||||
if (result == Camera.FrustumIntersect.Inside){
|
|
||||||
node.generateRenderSetNoCheck(globalGeomList, renderSet, cam);
|
|
||||||
}else{
|
|
||||||
node.generateRenderSet(globalGeomList, renderSet, cam, tempBox, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempBox.getCenter().set(x,y,z);
|
|
||||||
tempBox.setXExtent(ext);
|
|
||||||
tempBox.setYExtent(ext);
|
|
||||||
tempBox.setZExtent(ext);
|
|
||||||
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
return "OCTNode[O=" + getOffset() + ", L=" + length +
|
|
||||||
", S=" + getSide() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toStringVerbose(int indent){
|
|
||||||
String str = "------------------".substring(0,indent) + toString() + "\n";
|
|
||||||
if (child == null)
|
|
||||||
return str;
|
|
||||||
|
|
||||||
FastOctnode children = child;
|
|
||||||
while (children != null){
|
|
||||||
str += children.toStringVerbose(indent+1);
|
|
||||||
children = children.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
|
|
||||||
public final class OCTTriangle {
|
|
||||||
|
|
||||||
private final Vector3f pointa = new Vector3f();
|
|
||||||
private final Vector3f pointb = new Vector3f();
|
|
||||||
private final Vector3f pointc = new Vector3f();
|
|
||||||
private final int index;
|
|
||||||
private final int geomIndex;
|
|
||||||
|
|
||||||
public OCTTriangle(Vector3f p1, Vector3f p2, Vector3f p3, int index, int geomIndex) {
|
|
||||||
pointa.set(p1);
|
|
||||||
pointb.set(p2);
|
|
||||||
pointc.set(p3);
|
|
||||||
this.index = index;
|
|
||||||
this.geomIndex = geomIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGeometryIndex() {
|
|
||||||
return geomIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTriangleIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3f get1(){
|
|
||||||
return pointa;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3f get2(){
|
|
||||||
return pointb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3f get3(){
|
|
||||||
return pointc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3f getNormal(){
|
|
||||||
Vector3f normal = new Vector3f(pointb);
|
|
||||||
normal.subtractLocal(pointa).crossLocal(pointc.x-pointa.x, pointc.y-pointa.y, pointc.z-pointa.z);
|
|
||||||
normal.normalizeLocal();
|
|
||||||
return normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,317 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
|
||||||
import com.jme3.collision.CollisionResult;
|
|
||||||
import com.jme3.collision.CollisionResults;
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.math.Matrix4f;
|
|
||||||
import com.jme3.math.Ray;
|
|
||||||
import com.jme3.math.Triangle;
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.renderer.Camera;
|
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
|
||||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.debug.WireBox;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class Octnode {
|
|
||||||
|
|
||||||
static final Vector3f[] extentMult = new Vector3f[]
|
|
||||||
{
|
|
||||||
new Vector3f( 1, 1, 1), // right top forw
|
|
||||||
new Vector3f(-1, 1, 1), // left top forw
|
|
||||||
new Vector3f( 1,-1, 1), // right bot forw
|
|
||||||
new Vector3f(-1,-1, 1), // left bot forw
|
|
||||||
new Vector3f( 1, 1,-1), // right top back
|
|
||||||
new Vector3f(-1, 1,-1), // left top back
|
|
||||||
new Vector3f( 1,-1,-1), // right bot back
|
|
||||||
new Vector3f(-1,-1,-1) // left bot back
|
|
||||||
};
|
|
||||||
|
|
||||||
final BoundingBox bbox;
|
|
||||||
final ArrayList<OCTTriangle> tris;
|
|
||||||
Geometry[] geoms;
|
|
||||||
final Octnode[] children = new Octnode[8];
|
|
||||||
boolean leaf = false;
|
|
||||||
FastOctnode fastNode;
|
|
||||||
|
|
||||||
public Octnode(BoundingBox bbox, ArrayList<OCTTriangle> tris){
|
|
||||||
this.bbox = bbox;
|
|
||||||
this.tris = tris;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BoundingBox getChildBound(int side){
|
|
||||||
float extent = bbox.getXExtent() * 0.5f;
|
|
||||||
Vector3f center = new Vector3f(bbox.getCenter().x + extent * extentMult[side].x,
|
|
||||||
bbox.getCenter().y + extent * extentMult[side].y,
|
|
||||||
bbox.getCenter().z + extent * extentMult[side].z);
|
|
||||||
return new BoundingBox(center, extent, extent, extent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float getAdditionCost(BoundingBox bbox, OCTTriangle t){
|
|
||||||
if (bbox.intersects(t.get1(), t.get2(), t.get3())){
|
|
||||||
float d1 = bbox.distanceToEdge(t.get1());
|
|
||||||
float d2 = bbox.distanceToEdge(t.get2());
|
|
||||||
float d3 = bbox.distanceToEdge(t.get3());
|
|
||||||
return d1 + d2 + d3;
|
|
||||||
}
|
|
||||||
return Float.POSITIVE_INFINITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expandBoxToContainTri(BoundingBox bbox, OCTTriangle t){
|
|
||||||
Vector3f min = bbox.getMin(null);
|
|
||||||
Vector3f max = bbox.getMax(null);
|
|
||||||
BoundingBox.checkMinMax(min, max, t.get1());
|
|
||||||
BoundingBox.checkMinMax(min, max, t.get2());
|
|
||||||
BoundingBox.checkMinMax(min, max, t.get3());
|
|
||||||
bbox.setMinMax(min, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean contains(BoundingBox bbox, OCTTriangle t){
|
|
||||||
if (bbox.contains(t.get1()) &&
|
|
||||||
bbox.contains(t.get2()) &&
|
|
||||||
bbox.contains(t.get3())){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void subdivide(int depth, int maxDepth, float maxVolume, int minTrisPerNode){
|
|
||||||
if (tris == null || depth > maxDepth || bbox.getVolume() < maxVolume || tris.size() < minTrisPerNode){
|
|
||||||
// no need to subdivide anymore
|
|
||||||
leaf = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<OCTTriangle> keepTris = new ArrayList<OCTTriangle>();
|
|
||||||
ArrayList[] trisForChild = new ArrayList[8];
|
|
||||||
BoundingBox[] boxForChild = new BoundingBox[8];
|
|
||||||
// create boxes for children
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
boxForChild[i] = getChildBound(i);
|
|
||||||
trisForChild[i] = new ArrayList<Triangle>();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OCTTriangle t : tris){
|
|
||||||
float lowestCost = Float.POSITIVE_INFINITY;
|
|
||||||
int lowestIndex = -1;
|
|
||||||
int numIntersecting = 0;
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
BoundingBox childBox = boxForChild[i];
|
|
||||||
float cost = getAdditionCost(childBox, t);
|
|
||||||
if (cost < lowestCost){
|
|
||||||
lowestCost = cost;
|
|
||||||
lowestIndex = i;
|
|
||||||
numIntersecting++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numIntersecting < 8 && lowestIndex > -1){
|
|
||||||
trisForChild[lowestIndex].add(t);
|
|
||||||
expandBoxToContainTri(boxForChild[lowestIndex], t);
|
|
||||||
}else{
|
|
||||||
keepTris.add(t);
|
|
||||||
}
|
|
||||||
// boolean wasAdded = false;
|
|
||||||
// for (int i = 0; i < 8; i++){
|
|
||||||
// BoundingBox childBox = boxForChild[i];
|
|
||||||
// if (contains(childBox, t)){
|
|
||||||
// trisForChild[i].add(t);
|
|
||||||
// wasAdded = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (!wasAdded){
|
|
||||||
// keepTris.add(t);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
tris.retainAll(keepTris);
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (trisForChild[i].size() > 0){
|
|
||||||
children[i] = new Octnode(boxForChild[i], trisForChild[i]);
|
|
||||||
children[i].subdivide(depth + 1, maxDepth, maxVolume, minTrisPerNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void subdivide(int maxDepth, float maxVolume, int minTrisPerNode){
|
|
||||||
subdivide(0, maxDepth, maxVolume, minTrisPerNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createFastOctnode(List<Geometry> globalGeomList){
|
|
||||||
fastNode = new FastOctnode();
|
|
||||||
|
|
||||||
if (geoms != null){
|
|
||||||
Collection<Geometry> geomsColl = Arrays.asList(geoms);
|
|
||||||
List<Geometry> myOptimizedList = GeometryBatchFactory.makeBatches(geomsColl);
|
|
||||||
|
|
||||||
int startIndex = globalGeomList.size();
|
|
||||||
globalGeomList.addAll(myOptimizedList);
|
|
||||||
|
|
||||||
fastNode.setOffset(startIndex);
|
|
||||||
fastNode.length = myOptimizedList.size();
|
|
||||||
}else{
|
|
||||||
fastNode.setOffset(0);
|
|
||||||
fastNode.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
children[i].createFastOctnode(globalGeomList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateFastOctnodeLinks(Octnode parent, Octnode nextSibling, int side){
|
|
||||||
fastNode.setSide(side);
|
|
||||||
fastNode.next = nextSibling != null ? nextSibling.fastNode : null;
|
|
||||||
|
|
||||||
// We set the next sibling property by going in reverse order
|
|
||||||
Octnode prev = null;
|
|
||||||
for (int i = 7; i >= 0; i--){
|
|
||||||
if (children[i] != null){
|
|
||||||
children[i].generateFastOctnodeLinks(this, prev, i);
|
|
||||||
prev = children[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fastNode.child = prev != null ? prev.fastNode : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateRenderSetNoCheck(Set<Geometry> renderSet, Camera cam){
|
|
||||||
if (geoms != null){
|
|
||||||
renderSet.addAll(Arrays.asList(geoms));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
children[i].generateRenderSetNoCheck(renderSet, cam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateRenderSet(Set<Geometry> renderSet, Camera cam){
|
|
||||||
// generateRenderSetNoCheck(renderSet, cam);
|
|
||||||
|
|
||||||
bbox.setCheckPlane(0);
|
|
||||||
cam.setPlaneState(0);
|
|
||||||
Camera.FrustumIntersect result = cam.contains(bbox);
|
|
||||||
if (result != Camera.FrustumIntersect.Outside){
|
|
||||||
if (geoms != null){
|
|
||||||
renderSet.addAll(Arrays.asList(geoms));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
if (result == Camera.FrustumIntersect.Inside){
|
|
||||||
children[i].generateRenderSetNoCheck(renderSet, cam);
|
|
||||||
}else{
|
|
||||||
children[i].generateRenderSet(renderSet, cam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void collectTriangles(Geometry[] inGeoms){
|
|
||||||
if (tris.size() > 0){
|
|
||||||
List<Geometry> geomsList = TriangleCollector.gatherTris(inGeoms, tris);
|
|
||||||
geoms = new Geometry[geomsList.size()];
|
|
||||||
geomsList.toArray(geoms);
|
|
||||||
}else{
|
|
||||||
geoms = null;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
children[i].collectTriangles(inGeoms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderBounds(RenderQueue rq, Matrix4f transform, WireBox box, Material mat){
|
|
||||||
int numChilds = 0;
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
numChilds ++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (geoms != null && numChilds == 0){
|
|
||||||
BoundingBox bbox2 = new BoundingBox(bbox);
|
|
||||||
bbox.transform(transform, bbox2);
|
|
||||||
// WireBox box = new WireBox(bbox2.getXExtent(), bbox2.getYExtent(),
|
|
||||||
// bbox2.getZExtent());
|
|
||||||
// WireBox box = new WireBox(1,1,1);
|
|
||||||
|
|
||||||
Geometry geom = new Geometry("bound", box);
|
|
||||||
geom.setLocalTranslation(bbox2.getCenter());
|
|
||||||
geom.setLocalScale(bbox2.getXExtent(), bbox2.getYExtent(),
|
|
||||||
bbox2.getZExtent());
|
|
||||||
geom.updateGeometricState();
|
|
||||||
geom.setMaterial(mat);
|
|
||||||
rq.addToQueue(geom, Bucket.Opaque);
|
|
||||||
box = null;
|
|
||||||
geom = null;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
if (children[i] != null){
|
|
||||||
children[i].renderBounds(rq, transform, box, mat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void intersectWhere(Ray r, Geometry[] geoms, float sceneMin, float sceneMax,
|
|
||||||
CollisionResults results){
|
|
||||||
for (OCTTriangle t : tris){
|
|
||||||
float d = r.intersects(t.get1(), t.get2(), t.get3());
|
|
||||||
if (Float.isInfinite(d))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Vector3f contactPoint = new Vector3f(r.getDirection()).multLocal(d).addLocal(r.getOrigin());
|
|
||||||
CollisionResult result = new CollisionResult(geoms[t.getGeometryIndex()],
|
|
||||||
contactPoint,
|
|
||||||
d,
|
|
||||||
t.getTriangleIndex());
|
|
||||||
results.addCollision(result);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 8; i++){
|
|
||||||
Octnode child = children[i];
|
|
||||||
if (child == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (child.bbox.intersects(r)){
|
|
||||||
child.intersectWhere(r, geoms, sceneMin, sceneMax, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
|
||||||
import com.jme3.bounding.BoundingVolume;
|
|
||||||
import com.jme3.collision.CollisionResults;
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.math.Matrix4f;
|
|
||||||
import com.jme3.math.Ray;
|
|
||||||
import com.jme3.math.Triangle;
|
|
||||||
import com.jme3.renderer.Camera;
|
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.Mesh;
|
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.scene.debug.WireBox;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class Octree {
|
|
||||||
|
|
||||||
private final ArrayList<OCTTriangle> allTris = new ArrayList<OCTTriangle>();
|
|
||||||
private final Geometry[] geoms;
|
|
||||||
private final BoundingBox bbox;
|
|
||||||
private Octnode root;
|
|
||||||
|
|
||||||
private CollisionResults boundResults = new CollisionResults();
|
|
||||||
|
|
||||||
private static List<Geometry> getGeometries(Spatial scene){
|
|
||||||
if (scene instanceof Geometry){
|
|
||||||
List<Geometry> geomList = new ArrayList<Geometry>(1);
|
|
||||||
geomList.add((Geometry) scene);
|
|
||||||
return geomList;
|
|
||||||
}else if (scene instanceof Node){
|
|
||||||
Node n = (Node) scene;
|
|
||||||
List<Geometry> geoms = new ArrayList<Geometry>();
|
|
||||||
for (Spatial child : n.getChildren()){
|
|
||||||
geoms.addAll(getGeometries(child));
|
|
||||||
}
|
|
||||||
return geoms;
|
|
||||||
}else{
|
|
||||||
throw new UnsupportedOperationException("Unsupported scene element class");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Octree(Spatial scene){
|
|
||||||
scene.updateGeometricState();
|
|
||||||
|
|
||||||
List<Geometry> geomsList = getGeometries(scene);
|
|
||||||
geoms = new Geometry[geomsList.size()];
|
|
||||||
geomsList.toArray(geoms);
|
|
||||||
// generate bound box for all geom
|
|
||||||
bbox = new BoundingBox();
|
|
||||||
for (Geometry geom : geoms){
|
|
||||||
BoundingVolume bv = geom.getWorldBound();
|
|
||||||
bbox.mergeLocal(bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set largest extent
|
|
||||||
float extent = Math.max(bbox.getXExtent(), Math.max(bbox.getYExtent(), bbox.getZExtent()));
|
|
||||||
bbox.setXExtent(extent);
|
|
||||||
bbox.setYExtent(extent);
|
|
||||||
bbox.setZExtent(extent);
|
|
||||||
|
|
||||||
Triangle t = new Triangle();
|
|
||||||
for (int g = 0; g < geoms.length; g++){
|
|
||||||
Mesh m = geoms[g].getMesh();
|
|
||||||
for (int i = 0; i < m.getTriangleCount(); i++){
|
|
||||||
m.getTriangle(i, t);
|
|
||||||
OCTTriangle ot = new OCTTriangle(t.get1(), t.get2(), t.get3(), i, g);
|
|
||||||
allTris.add(ot);
|
|
||||||
// convert triangle to world space
|
|
||||||
// geom.getWorldTransform().transformVector(t.get1(), t.get1());
|
|
||||||
// geom.getWorldTransform().transformVector(t.get2(), t.get2());
|
|
||||||
// geom.getWorldTransform().transformVector(t.get3(), t.get3());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void construct(int maxDepth, float maxVolume, int minTrisPerNode){
|
|
||||||
root = new Octnode(bbox, allTris);
|
|
||||||
root.subdivide(maxDepth, maxVolume, minTrisPerNode);
|
|
||||||
root.collectTriangles(geoms);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createFastOctnodes(List<Geometry> globalGeomList){
|
|
||||||
root.createFastOctnode(globalGeomList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BoundingBox getBound(){
|
|
||||||
return bbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FastOctnode getFastRoot(){
|
|
||||||
return root.fastNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateFastOctnodeLinks(){
|
|
||||||
root.generateFastOctnodeLinks(null, null, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateRenderSet(Set<Geometry> renderSet, Camera cam){
|
|
||||||
root.generateRenderSet(renderSet, cam);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderBounds(RenderQueue rq, Matrix4f transform, WireBox box, Material mat){
|
|
||||||
root.renderBounds(rq, transform, box, mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void intersect(Ray r, float farPlane, Geometry[] geoms, CollisionResults results){
|
|
||||||
boundResults.clear();
|
|
||||||
bbox.collideWith(r, boundResults);
|
|
||||||
if (boundResults.size() > 0){
|
|
||||||
float tMin = boundResults.getClosestCollision().getDistance();
|
|
||||||
float tMax = boundResults.getFarthestCollision().getDistance();
|
|
||||||
|
|
||||||
tMin = Math.max(tMin, 0);
|
|
||||||
tMax = Math.min(tMax, farPlane);
|
|
||||||
|
|
||||||
root.intersectWhere(r, geoms, tMin, tMax, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.shape.Quad;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TestCollector {
|
|
||||||
|
|
||||||
public static void main(String[] args){
|
|
||||||
Vector3f z = Vector3f.ZERO;
|
|
||||||
Geometry g = new Geometry("quad", new Quad(2,2));
|
|
||||||
Geometry g2 = new Geometry("quad", new Quad(2,2));
|
|
||||||
List<OCTTriangle> tris = new ArrayList<OCTTriangle>();
|
|
||||||
tris.add(new OCTTriangle(z, z, z, 1, 0));
|
|
||||||
tris.add(new OCTTriangle(z, z, z, 0, 1));
|
|
||||||
List<Geometry> firstOne = TriangleCollector.gatherTris(new Geometry[]{ g, g2 }, tris);
|
|
||||||
System.out.println(firstOne.get(0).getMesh());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,248 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jme3tools.optimize;
|
|
||||||
|
|
||||||
import com.jme3.light.Light;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.Mesh;
|
|
||||||
import com.jme3.scene.VertexBuffer;
|
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
|
||||||
import com.jme3.util.BufferUtils;
|
|
||||||
import com.jme3.util.IntMap;
|
|
||||||
import com.jme3.util.IntMap.Entry;
|
|
||||||
import java.nio.Buffer;
|
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class TriangleCollector {
|
|
||||||
|
|
||||||
private static final GeomTriComparator comparator = new GeomTriComparator();
|
|
||||||
|
|
||||||
private static class GeomTriComparator implements Comparator<OCTTriangle> {
|
|
||||||
public int compare(OCTTriangle a, OCTTriangle b) {
|
|
||||||
if (a.getGeometryIndex() < b.getGeometryIndex()){
|
|
||||||
return -1;
|
|
||||||
}else if (a.getGeometryIndex() > b.getGeometryIndex()){
|
|
||||||
return 1;
|
|
||||||
}else{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Range {
|
|
||||||
|
|
||||||
private int start, length;
|
|
||||||
|
|
||||||
public Range(int start, int length) {
|
|
||||||
this.start = start;
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(int length) {
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStart() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStart(int start) {
|
|
||||||
this.start = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grabs all the triangles specified in <code>tris</code> from the input array
|
|
||||||
* (using the indices OCTTriangle.getGeometryIndex() & OCTTriangle.getTriangleIndex())
|
|
||||||
* then organizes them into output geometry.
|
|
||||||
*
|
|
||||||
* @param inGeoms
|
|
||||||
* @param tris
|
|
||||||
* @return The optimized geometries
|
|
||||||
*/
|
|
||||||
public static final List<Geometry> gatherTris(Geometry[] inGeoms, List<OCTTriangle> tris){
|
|
||||||
Collections.sort(tris, comparator);
|
|
||||||
HashMap<Integer, Range> ranges = new HashMap<Integer, Range>();
|
|
||||||
|
|
||||||
for (int i = 0; i < tris.size(); i++){
|
|
||||||
Range r = ranges.get(tris.get(i).getGeometryIndex());
|
|
||||||
if (r != null){
|
|
||||||
// incremenet length
|
|
||||||
r.setLength(r.getLength()+1);
|
|
||||||
}else{
|
|
||||||
// set offset, length is 1
|
|
||||||
ranges.put(tris.get(i).getGeometryIndex(), new Range(i, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Geometry> newGeoms = new ArrayList<Geometry>();
|
|
||||||
int[] vertIndicies = new int[3];
|
|
||||||
int[] newIndices = new int[3];
|
|
||||||
boolean[] vertexCreated = new boolean[3];
|
|
||||||
HashMap<Integer, Integer> indexCache = new HashMap<Integer, Integer>();
|
|
||||||
for (Map.Entry<Integer, Range> entry : ranges.entrySet()){
|
|
||||||
int inGeomIndex = entry.getKey().intValue();
|
|
||||||
int outOffset = entry.getValue().start;
|
|
||||||
int outLength = entry.getValue().length;
|
|
||||||
|
|
||||||
Geometry inGeom = inGeoms[inGeomIndex];
|
|
||||||
Mesh in = inGeom.getMesh();
|
|
||||||
Mesh out = new Mesh();
|
|
||||||
|
|
||||||
int outElementCount = outLength * 3;
|
|
||||||
ShortBuffer ib = BufferUtils.createShortBuffer(outElementCount);
|
|
||||||
out.setBuffer(Type.Index, 3, ib);
|
|
||||||
|
|
||||||
// generate output buffers based on input buffers
|
|
||||||
IntMap<VertexBuffer> bufs = in.getBuffers();
|
|
||||||
for (Entry<VertexBuffer> ent : bufs){
|
|
||||||
VertexBuffer vb = ent.getValue();
|
|
||||||
if (vb.getBufferType() == Type.Index)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// NOTE: we are not actually sure
|
|
||||||
// how many elements will be in this buffer.
|
|
||||||
// It will be compacted later.
|
|
||||||
Buffer b = VertexBuffer.createBuffer(vb.getFormat(),
|
|
||||||
vb.getNumComponents(),
|
|
||||||
outElementCount);
|
|
||||||
|
|
||||||
VertexBuffer outVb = new VertexBuffer(vb.getBufferType());
|
|
||||||
outVb.setNormalized(vb.isNormalized());
|
|
||||||
outVb.setupData(vb.getUsage(), vb.getNumComponents(), vb.getFormat(), b);
|
|
||||||
out.setBuffer(outVb);
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentVertex = 0;
|
|
||||||
for (int i = outOffset; i < outOffset + outLength; i++){
|
|
||||||
OCTTriangle t = tris.get(i);
|
|
||||||
|
|
||||||
// find vertex indices for triangle t
|
|
||||||
in.getTriangle(t.getTriangleIndex(), vertIndicies);
|
|
||||||
|
|
||||||
// find indices in new buf
|
|
||||||
Integer i0 = indexCache.get(vertIndicies[0]);
|
|
||||||
Integer i1 = indexCache.get(vertIndicies[1]);
|
|
||||||
Integer i2 = indexCache.get(vertIndicies[2]);
|
|
||||||
|
|
||||||
// check which ones were not created
|
|
||||||
// if not created in new IB, create them
|
|
||||||
if (i0 == null){
|
|
||||||
vertexCreated[0] = true;
|
|
||||||
newIndices[0] = currentVertex++;
|
|
||||||
indexCache.put(vertIndicies[0], newIndices[0]);
|
|
||||||
}else{
|
|
||||||
newIndices[0] = i0.intValue();
|
|
||||||
vertexCreated[0] = false;
|
|
||||||
}
|
|
||||||
if (i1 == null){
|
|
||||||
vertexCreated[1] = true;
|
|
||||||
newIndices[1] = currentVertex++;
|
|
||||||
indexCache.put(vertIndicies[1], newIndices[1]);
|
|
||||||
}else{
|
|
||||||
newIndices[1] = i1.intValue();
|
|
||||||
vertexCreated[1] = false;
|
|
||||||
}
|
|
||||||
if (i2 == null){
|
|
||||||
vertexCreated[2] = true;
|
|
||||||
newIndices[2] = currentVertex++;
|
|
||||||
indexCache.put(vertIndicies[2], newIndices[2]);
|
|
||||||
}else{
|
|
||||||
newIndices[2] = i2.intValue();
|
|
||||||
vertexCreated[2] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if any verticies were created for this triangle
|
|
||||||
// copy them to the output mesh
|
|
||||||
IntMap<VertexBuffer> inbufs = in.getBuffers();
|
|
||||||
for (Entry<VertexBuffer> ent : inbufs){
|
|
||||||
VertexBuffer vb = ent.getValue();
|
|
||||||
if (vb.getBufferType() == Type.Index)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VertexBuffer outVb = out.getBuffer(vb.getBufferType());
|
|
||||||
// copy verticies that were created for this triangle
|
|
||||||
for (int v = 0; v < 3; v++){
|
|
||||||
if (!vertexCreated[v])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// copy triangle's attribute from one
|
|
||||||
// buffer to another
|
|
||||||
vb.copyElement(vertIndicies[v], outVb, newIndices[v]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the indices onto the output index buffer
|
|
||||||
ib.put((short)newIndices[0])
|
|
||||||
.put((short)newIndices[1])
|
|
||||||
.put((short)newIndices[2]);
|
|
||||||
}
|
|
||||||
ib.clear();
|
|
||||||
indexCache.clear();
|
|
||||||
|
|
||||||
// since some verticies were cached, it means there's
|
|
||||||
// extra data in some buffers
|
|
||||||
IntMap<VertexBuffer> outbufs = out.getBuffers();
|
|
||||||
for (Entry<VertexBuffer> ent : outbufs){
|
|
||||||
VertexBuffer vb = ent.getValue();
|
|
||||||
if (vb.getBufferType() == Type.Index)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
vb.compact(currentVertex);
|
|
||||||
}
|
|
||||||
|
|
||||||
out.updateBound();
|
|
||||||
out.updateCounts();
|
|
||||||
out.setStatic();
|
|
||||||
//out.setInterleaved();
|
|
||||||
Geometry outGeom = new Geometry("Geom"+entry.getKey(), out);
|
|
||||||
outGeom.setLocalTransform(inGeom.getWorldTransform());
|
|
||||||
outGeom.setMaterial(inGeom.getMaterial());
|
|
||||||
for (Light light : inGeom.getWorldLightList()){
|
|
||||||
outGeom.addLight(light);
|
|
||||||
}
|
|
||||||
|
|
||||||
outGeom.updateGeometricState();
|
|
||||||
newGeoms.add(outGeom);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newGeoms;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
convert all leafs in octree to PvsNode, add to list pvsNodes
|
|
||||||
|
|
||||||
for (every nodeX in pvsNodes):
|
|
||||||
for (every nodeY in pvsNodes):
|
|
||||||
if (nodeX == nodeY or nodeX adjecent or intersecting nodeY):
|
|
||||||
continue
|
|
||||||
|
|
||||||
setup camera for (nodeX, nodeY)
|
|
||||||
draw every node except nodeX & nodeY
|
|
||||||
|
|
||||||
turn on occlusion query
|
|
||||||
draw nodeY as bounding box
|
|
||||||
turn off occlusion query
|
|
||||||
|
|
||||||
if (numSamples > 0): // node is visible
|
|
||||||
add nodeY to nodeX's potentially visible set
|
|
||||||
|
|
||||||
|
|
||||||
setup camera for node, sideI:
|
|
||||||
|
|
||||||
float width, height, near;
|
|
||||||
|
|
||||||
switch (sideI):
|
|
||||||
case X+
|
|
||||||
case X-
|
|
||||||
width = x extent
|
|
||||||
height = y extent
|
|
||||||
near = z extent / 2
|
|
||||||
case Y+
|
|
||||||
case Y-
|
|
||||||
width = x extent
|
|
||||||
height = z extent
|
|
||||||
near = y extent / 2
|
|
||||||
case Z+
|
|
||||||
case Z-
|
|
||||||
width = z extent
|
|
||||||
height = y extent
|
|
||||||
near = x extent / 2
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user