/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2008, by :
* Corporate:
* EADS Astrium
* Individual:
* Claude Cazenave
*
* $Id: Geometries.java,v 1.1 2008/12/17 22:37:53 cazenave Exp $
*
* Changes
* -------
* 14 d�c. 2008 : Initial public release
*
*/
package jsynoptic.plugins.java3d.util;
import java.util.ArrayList;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.TriangleStripArray;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.geometry.Stripifier;
/**
*
*/
public class Geometries {
static class GeoData {
private ArrayList<Point3f> points;
private ArrayList<Vector3f> normals;
private ArrayList<TexCoord2f> texCoords;
GeoData(){
points=new ArrayList<Point3f>();
normals=new ArrayList<Vector3f>();
texCoords=new ArrayList<TexCoord2f>();
}
void addPoint(double x, double y, double z){
if(normals.size()==points.size()-1){
normals.add(null);
}
else if(normals.size()!=points.size()){
throw new RuntimeException("Inconsitent vertex normal data");
}
if(texCoords.size()==points.size()-1){
texCoords.add(null);
}
else if(texCoords.size()!=texCoords.size()){
throw new RuntimeException("Inconsitent vertex texture coordinate data");
}
points.add(new Point3f((float)x, (float)y, (float)z));
}
void setNormal(double x, double y, double z){
normals.add(new Vector3f((float)x, (float)y, (float)z));
}
void setTexCoord(double s, double t){
texCoords.add(new TexCoord2f((float)s, (float)t));
}
void fill(GeometryArray ga){
ga.setCoordinates(0, points.toArray(new Point3f[points.size()]));
ga.setNormals(0, normals.toArray(new Vector3f[normals.size()]));
if((ga.getVertexFormat()&GeometryArray.TEXTURE_COORDINATE_2)!=0){
ga.setTextureCoordinates(0, 0, texCoords.toArray(new TexCoord2f[texCoords.size()]));
}
}
int size(){
return points.size();
}
}
public static GeometryArray disc(double radius, int rDiv,boolean up, double yOffset){
return cone(radius,0.,rDiv,up,yOffset);
}
public static GeometryArray cone(double radius, double height, int rDiv, boolean up, double yOffset){
GeoData data=new GeoData();
data.addPoint(0., yOffset+height, 0.);
data.setNormal(0., up ? 1.0 : -1.0, 0.);
double dtheta = 2.0*Math.PI / (double)rDiv;
if(!up){
dtheta=-dtheta;
}
double a=Math.atan2(radius, height);
double ca=Math.cos(a);
double sa=Math.sin(a)* (up ? 1.0 : -1.0);
if(height==0.){
ca=0.;
sa=1.* (up ? 1.0 : -1.0);
}
for (int i=rDiv;i>=0;i--) {
double px = Math.cos(i*dtheta - Math.PI/2.0);
double pz = Math.sin(i*dtheta - Math.PI/2.0);
data.addPoint(px*radius, yOffset, pz*radius);
data.setNormal(ca*px, sa, ca*pz);
}
int texCoordSetMap[] = new int[1];
texCoordSetMap[0]=0;
int sc[]=new int [1];
sc[0]=data.size();
GeometryArray ga=new TriangleFanArray(data.size(),
GeometryArray.COORDINATES |
GeometryArray.NORMALS,
1, texCoordSetMap,sc);
data.fill(ga);
return ga;
}
public static GeometryArray cylinder(double radius, double height, int rDiv){
GeoData data=new GeoData();
double px, pz, qx, qz;
double py = 0.;
double qy = height;
double dtheta = 2.0*Math.PI / (double)rDiv;
px = Math.cos(rDiv*dtheta - Math.PI/2.0);
pz = Math.sin(rDiv*dtheta - Math.PI/2.0);
qx = Math.cos((rDiv-1)*dtheta - Math.PI/2.0);
qz = Math.sin((rDiv-1)*dtheta - Math.PI/2.0);
data.addPoint(px*radius, qy, pz*radius);
data.setNormal(px, 0.0, pz);
data.addPoint(px*radius, py, pz*radius);
data.setNormal(px, 0.0, pz);
data.addPoint(qx*radius, qy, qz*radius);
data.setNormal(qx, 0.0, qz);
data.addPoint(qx*radius, py, qz*radius);
data.setNormal(qx, 0.0, qz);
for (int j = rDiv-2; j >=0; j--) {
px = Math.cos(j*dtheta - Math.PI/2.0);
pz = Math.sin(j*dtheta - Math.PI/2.0);
data.addPoint(px*radius, qy, pz*radius);
data.setNormal(px, 0.0, pz);
data.addPoint(px*radius, py, pz*radius);
data.setNormal(px, 0.0, pz);
}
int texCoordSetMap[] = new int[1];
texCoordSetMap[0]=0;
int sc[]=new int [1];
sc[0]=data.size();
GeometryArray ga=new TriangleStripArray(data.size(),
GeometryArray.COORDINATES |
GeometryArray.NORMALS,
1, texCoordSetMap,sc);
data.fill(ga);
return ga;
}
public static GeometryArray polygon(double[] values){
GeometryInfo gi=new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
gi.setCoordinates(values);
int sc[]=new int [1];
sc[0]=values.length/3;
gi.setStripCounts(sc);
NormalGenerator ng = new NormalGenerator();
ng.generateNormals(gi);
Stripifier st = new Stripifier();
st.stripify(gi);
GeometryArray result = gi.getGeometryArray();
return result;
}
}