Tube projection support for objects containing many meshes.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8230 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent f9f25813d0
commit 76d9fd3a15
  1. 117
      engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

@ -101,8 +101,8 @@ public class UVCoordinatesGenerator {
VertexBuffer result = new VertexBuffer(VertexBuffer.Type.TexCoord); VertexBuffer result = new VertexBuffer(VertexBuffer.Type.TexCoord);
Mesh mesh = geometries.get(0).getMesh(); Mesh mesh = geometries.get(0).getMesh();
BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometries); BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometries);
float[] inputData = null;//positions, normals, reflection vectors, etc. float[] inputData = null;// positions, normals, reflection vectors, etc.
switch (texco) { switch (texco) {
case TEXCO_ORCO: case TEXCO_ORCO:
inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Position)); inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Position));
@ -118,7 +118,7 @@ public class UVCoordinatesGenerator {
} }
result.setupData(Usage.Static, textureDimension, Format.Float, uvCoordinatesBuffer); result.setupData(Usage.Static, textureDimension, Format.Float, uvCoordinatesBuffer);
} else { } else {
} }
break; break;
case TEXCO_NORM: case TEXCO_NORM:
@ -148,7 +148,7 @@ public class UVCoordinatesGenerator {
throw new IllegalStateException("Unknown texture coordinates value: " + texco); throw new IllegalStateException("Unknown texture coordinates value: " + texco);
} }
if(inputData!=null) {//make calculations if (inputData != null) {// make calculations
if (textureDimension == 2) { if (textureDimension == 2) {
switch (projection) { switch (projection) {
case PROJECTION_FLAT: case PROJECTION_FLAT:
@ -158,8 +158,8 @@ public class UVCoordinatesGenerator {
inputData = UVProjectionGenerator.cubeProjection(mesh, bb); inputData = UVProjectionGenerator.cubeProjection(mesh, bb);
break; break;
case PROJECTION_TUBE: case PROJECTION_TUBE:
BoundingTube bt = UVCoordinatesGenerator.getBoundingTube(mesh); BoundingTube bt = UVCoordinatesGenerator.getBoundingTube(geometries);
inputData = UVProjectionGenerator.tubeProjection(mesh, bt); inputData = UVProjectionGenerator.tubeProjection(mesh, bt);
break; break;
case PROJECTION_SPHERE: case PROJECTION_SPHERE:
BoundingSphere bs = UVCoordinatesGenerator.getBoundingSphere(geometries); BoundingSphere bs = UVCoordinatesGenerator.getBoundingSphere(geometries);
@ -182,7 +182,7 @@ public class UVCoordinatesGenerator {
} }
result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(inputData)); result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(inputData));
} }
// each mesh will have the same coordinates // each mesh will have the same coordinates
for (Geometry geometry : geometries) { for (Geometry geometry : geometries) {
mesh = geometry.getMesh(); mesh = geometry.getMesh();
@ -234,7 +234,7 @@ public class UVCoordinatesGenerator {
* This method returns the bounding sphere of the given geometries. * This method returns the bounding sphere of the given geometries.
* @param geometries * @param geometries
* the list of geometries * the list of geometries
* @return bounding spheres of the given geometries * @return bounding sphere of the given geometries
*/ */
/* package */static BoundingSphere getBoundingSphere(List<Geometry> geometries) { /* package */static BoundingSphere getBoundingSphere(List<Geometry> geometries) {
BoundingSphere result = null; BoundingSphere result = null;
@ -296,11 +296,30 @@ public class UVCoordinatesGenerator {
maxz = z > maxz ? z : maxz; maxz = z > maxz ? z : maxz;
minz = z < minz ? z : minz; minz = z < minz ? z : minz;
} }
center.divideLocal(limit/3); center.divideLocal(limit / 3);
float radius = Math.max(maxx - minx, maxy - miny) * 0.5f; float radius = Math.max(maxx - minx, maxy - miny) * 0.5f;
return new BoundingTube(radius, maxz - minz, center); return new BoundingTube(radius, maxz - minz, center);
} }
/**
* This method returns the bounding tube of the given geometries.
* @param geometries
* the list of geometries
* @return bounding tube of the given geometries
*/
/* package */static BoundingTube getBoundingTube(List<Geometry> geometries) {
BoundingTube result = null;
for (Geometry geometry : geometries) {
BoundingTube bt = UVCoordinatesGenerator.getBoundingTube(geometry.getMesh());
if (result == null) {
result = bt;
} else {
result.merge(bt);
}
}
return result;
}
/** /**
* A very simple bounding tube. Id holds only the basic data bout the bounding tube * A very simple bounding tube. Id holds only the basic data bout the bounding tube
@ -313,16 +332,31 @@ public class UVCoordinatesGenerator {
private float height; private float height;
private Vector3f center; private Vector3f center;
/**
* Constructor creates the tube with the given params.
* @param radius
* the radius of the tube
* @param height
* the height of the tube
* @param center
* the center of the tube
*/
public BoundingTube(float radius, float height, Vector3f center) { public BoundingTube(float radius, float height, Vector3f center) {
this.radius = radius; this.radius = radius;
this.height = height; this.height = height;
this.center = center; this.center = center;
} }
public void merge(BoundingTube boundingTube) { /**
//get tubes (tube1.radius >= tube2.radius) * This method merges two bounding tubes.
* @param boundingTube
* bounding tube to be merged woth the current one
* @return new instance of bounding tube representing the tubes' merge
*/
public BoundingTube merge(BoundingTube boundingTube) {
// get tubes (tube1.radius >= tube2.radius)
BoundingTube tube1, tube2; BoundingTube tube1, tube2;
if(this.radius>=boundingTube.radius) { if (this.radius >= boundingTube.radius) {
tube1 = this; tube1 = this;
tube2 = boundingTube; tube2 = boundingTube;
} else { } else {
@ -331,53 +365,40 @@ public class UVCoordinatesGenerator {
} }
float r1 = tube1.radius; float r1 = tube1.radius;
float r2 = tube2.radius; float r2 = tube2.radius;
//get the distance between tubes projected on XY plane float minZ = Math.min(tube1.center.z - tube1.height * 0.5f, tube2.center.z - tube2.height * 0.5f);
Vector3f distance = boundingTube.center.subtract(this.center); float maxZ = Math.max(tube1.center.z + tube1.height * 0.5f, tube2.center.z + tube2.height * 0.5f);
distance.z = 0; float height = maxZ - minZ;
Vector3f distance = tube2.center.subtract(tube1.center);
Vector3f center = tube1.center.add(distance.mult(0.5f));
distance.z = 0;// projecting this vector on XY plane
float d = distance.length(); float d = distance.length();
// d <= r1 - r2: tube2 is inside tube1 or touches tube1 from the inside
//calculate union depending on tubes location // d > r1 - r2: tube2 is outside or touches tube1 or crosses tube1
if(d>=r1+r2) {//tube2 is outside or touches tube1 float radius = d <= r1 - r2 ? tube1.radius : (d + r1 + r2) * 0.5f;
return new BoundingTube(radius, height, center);
} else if(d<r1+r2 && d>r1-r2) {//tube2 crosses tube1
} else {//tube2 is inside tube1
}
if(d >= this.radius + boundingTube.radius ||
(d < this.radius + boundingTube.radius && d > this.radius - boundingTube.radius)) {
}
float centerZ = distance.z;
float maxz = this.center.z + height*0.5f;
float minz = this.center.z - height*0.5f;
distance.z = this.center.z = 0;
Vector3f distanceNormal = distance.normalize();
Vector3f start = this.center.subtract(distanceNormal.multLocal(this.radius));
distanceNormal.normalizeLocal();
Vector3f stop = start.add(distance).addLocal(distanceNormal.multLocal(this.radius+boundingTube.radius));
this.center = start.add(stop.subtractLocal(start)).multLocal(0.5f);
this.center.z = centerZ;
this.radius = this.center.subtract(start).length();
maxz = Math.max(maxz, boundingTube.center.z + boundingTube.height*0.5f);
minz = Math.min(minz, boundingTube.center.z - boundingTube.height*0.5f);
this.height = maxz - minz;
} }
/**
* This method returns the radius of the tube.
* @return the radius of the tube
*/
public float getRadius() { public float getRadius() {
return radius; return radius;
} }
/**
* This method returns the height of the tube.
* @return the height of the tube
*/
public float getHeight() { public float getHeight() {
return height; return height;
} }
/**
* This method returns the center of the tube.
* @return the center of the tube
*/
public Vector3f getCenter() { public Vector3f getCenter() {
return center; return center;
} }

Loading…
Cancel
Save