ah great, then you should be able to make some good use of that.
Batman: So you’ve coded BSP trees and BSPnodes already?
A single Vector3f takes 23 bytes (it contains 3 floats of 4 bytes each, which leaves 11 bytes for the class data itself). A quaternion takes 23 bytes, too. A Vector3f array of 10 takes 53 bytes, an arry of 20 takes 95 bytes. So it is 4 bytes per array entry + 11 bytes for the array itself, maybe with an additional (alignment) overhead every x entries.
I will try to profile the creation of a single TriMesh, may I'll find something interesting. I let you know.
A quat and vector3f shouldn’t take the same amount of memory(?)
I can give it all to you.
Correction btw. If I comment out the creation of the DisplaySystem, which I do not need for Vector3f and Quaternion, both are said to be 24 bytes long. Remember the Sizeof class is guessing the size by inspecting garbage collector output.
Just the BSP node would be nice.
OK, here we go
package com.jme.scene;
import com.jme.math.Plane;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.Renderer;
public class BSPNode extends Node {
// attributes
protected Plane modelPlane;
protected Plane worldPlane;
// constructors
/**
* Empty Constructor to be used internally only.
*/
public BSPNode() {
}
/**
* Constructor instantiates a new <code>BSPNode</code>.
*
* @param name
* the name of the scene element. This is required for identification and comparision
* purposes.
*/
public BSPNode(String name) {
super(name);
}
// public methods
/**
* BSP is a binary tree. Use this method to attach the left child.
*
* @param child
* The new left child.
* @return The old child at the index.
*/
public Spatial attachLeftChild(Spatial child) {
return setChild(0, child);
}
/**
* BSP is a binary tree. Use this method to attach the right child.
*
* @param child
* The new right child.
* @return The old child at the index.
*/
public Spatial attachRightChild(Spatial child) {
return setChild(2, child);
}
/**
* Detach the left child.
*
* @return The child at the left position.
*/
public Spatial detachLeftChild() {
return detachChildAt(0);
}
/**
* Detach the right child.
*
* @return The child at the right position.
*/
public Spatial detachRightChild() {
return detachChildAt(2);
}
/**
* Getter for the left child.
*
* @return The left child.
*/
public Spatial getLeftChild() {
return getChild(0);
}
/**
* Getter for the right child.
*
* @return The right child.
*/
public Spatial getRightChild() {
return getChild(2);
}
/**
* Determine the bsp node whose represented region contains the point.
*
* @param point
* The point which is requested.
* @return The BSP node referencing the requested region.
*/
public BSPNode getContainingNode(Vector3f point) {
BSPNode reply = null;
Spatial left = getLeftChild();
Spatial right = getRightChild();
if (worldPlane.whichSide(point) == Plane.NEGATIVE_SIDE) {
if (right != null && right instanceof BSPNode) {
reply = ((BSPNode)right).getContainingNode(point);
}
} else {
if (left != null && left instanceof BSPNode) {
reply = ((BSPNode)left).getContainingNode(point);
}
}
return reply;
}
/**
* <code>draw</code> renders the whole bsp subtree.
*
* @see com.jme.scene.Spatial#draw(com.jme.renderer.Renderer)
* @param r
* the renderer to draw to.
*/
public void draw(Renderer r) {
// draw children in back-to-front order
Spatial left = getLeftChild();
Spatial right = getRightChild();
Camera cam = r.getCamera();
float sgnDist = worldPlane.pseudoDistance(cam.getLocation());
float ndD = worldPlane.getNormal().dot(cam.getDirection());
// float cosSqr = cam.getMaxCosSqrFrustumAngle();
//
// // decide depending on relative position of camera to the world plane
// if (sgnDist > 0f) {
// if (-ndD >= cosSqr) {
// if (right != null) {
// right.onDraw(r);
// // callback?
// }
// }
// if (left != null) {
// left.onDraw(r);
// }
// } else if (sgnDist < 0f) {
// if (ndD >= cosSqr) {
// if (left != null) {
// left.onDraw(r);
// // callback?
// }
// if (right != null) {
// right.onDraw(r);
// }
// }
// if (left != null) {
// left.onDraw(r);
// }
// } else if (ndD >= 0f) {
// if (-ndD >= cosSqr) {
// if (right != null) {
// right.onDraw(r);
// // callback?
// }
// }
// if (left != null) {
// left.onDraw(r);
// }
// } else {
// if (ndD >= cosSqr) {
// if (left != null) {
// left.onDraw(r);
// }
// // callback?
// }
// if (right != null) {
// right.onDraw(r);
// }
// }
}
/**
* <code>updateWorldData</code> updates all the children maintained by
* this node.
*
* @param time
* the frame time.
*/
public void updateWorldData(float time) {
super.updateWorldData(time);
// let X represent points in model space and Y = s*R*X+T represent
// points in world space where s is the world scale, R is the world
// rotation, and T is the world translation. The inverse transform is
// X = (1/s)*R^t*(Y-T). The model plane is Dot(N0,X) = C0. Replacing
// the formula for X in it and applying some algebra leads to the world
// plane Dot(N1,Y) = C1 where N1 = R*N0 and C1 = s*C0+Dot(N1,T).
Vector3f normal = worldRotation.mult(modelPlane.getNormal());
float constant = worldScale.length() * modelPlane.getConstant() + normal.dot(worldTranslation);
worldPlane.setNormal(normal);
worldPlane.setConstant(constant);
}
/**
* Getter for the model plane.
* @return The current model plane.
*/
public Plane getModelPlane() {
return modelPlane;
}
/**
* Getter for the world plane.
* @return The current world plane.
*/
public Plane getWorldPlane() {
return worldPlane;
}
} // public class BSPNode extends Node
To use the commented out region, you need the following in AbstractCamera:
public float getMaxCosSqrFrustumAngle() {
// Compute (cos(A))^2 where A is the largest angle between the frustum
// axis direction D and the four edges of the frustum that lie along the
// rays from the frustum origin.
float nearSqr = frustumNear * frustumNear;
float denom = nearSqr;
if (Math.abs(frustumLeft) >= Math.abs(frustumRight)) {
denom += frustumLeft * frustumLeft;
if (Math.abs(frustumBottom) >= Math.abs(frustumTop)) {
denom += frustumBottom * frustumBottom;
} else {
denom += frustumTop * frustumTop;
}
} else {
denom += frustumRight * frustumRight;
if (Math.abs(frustumBottom) >= Math.abs(frustumTop)) {
denom += frustumBottom * frustumBottom;
} else {
denom += frustumTop * frustumTop;
}
}
return nearSqr / denom;
}