ASKER
package testvrmlrotations;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
public class Main {
public static void main(String[] args) throws IOException {
FileWriter fos = new FileWriter("B:/x.wrl");
BufferedWriter out = new BufferedWriter(fos);
out.write( "#VRML V2.0 utf8");
out.write( "\r Background { skyColor [ 0.0 0.0 0.0 ] }");
// works when in XY plane
out.write(doit( -2.0, 1.0 , 0.0, 2.0, -3.0, 0.0 ));
// doesn't work when out of XY plane : something wrong with R2
out.write(doit( -2.0, 1.0 , 0.0, 5.0, -1.0, -5.0 ));
out.close();
}
/**
* returns VMRL declarations for
* - 2 spheres at (x1,y1,z1) and (x2,y2,z2)
* - a cylinder connecting the spheres
*/
public static String doit(double x1, double y1, double z1 ,
double x2, double y2, double z2) {
String s=""; // the output
DecimalFormat df = new DecimalFormat(" 0.000");
// add spheres
s += getSpheres(x1,y1,z1);
s += getSpheres(x2,y2,z2);
// **** draw cylinder ****
// get barycenter: this is (0,0,0) for the cylinder
double x=(x1+x2)/2;
double y=(y1+y2)/2;
double z=(z1+z2)/2;
// get height
double h=Math.sqrt( Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2) + Math.pow((z1-z2), 2) ) ;
// vector: barycenter->point2
double vx = (x2-x)/2;
double vy = (y2-y)/2;
double vz = (z2-z)/2;
// Z angle for XY plane : this angle seems OK
double r1 = - Math.atan2(vx, vy);
// vector from XY plane to point2 : something wrong here!!!!
double wx = vy * Math.sin(r1) + vx * Math.cos(r1);
double wy = vx * Math.sin(r1) + vy * Math.cos(r1);
double wz = vz;
// Y angle for new XZ plane
double r2 = - Math.atan2(wx, wz);
// output VRML declarations - nested rotations
s += "\r Transform {";
s += "\r translation " + df.format(x) + df.format(y) + df.format(z);
s += "\r rotation 0 0 1" + df.format(r1);
s += "\r children Transform {";
s += "\r translation 0 0 0 " ;
s += "\r rotation 0 1 0" + df.format(r2);
s += "\r children Shape {";
s += "\r appearance Appearance {";
s += "\r material Material { diffuseColor 1.0 0.0 1.0 }";
s += "\r }";
s += "\r geometry Cylinder {";
s += "\r radius 0.1";
s += "\r height " + df.format(h);
s += "\r }";
s += "\r }";
s += "\r }";
s += "\r }";
return s;
}
public static String getSpheres(double x , double y, double z) {
String s=""; // the output
DecimalFormat df = new DecimalFormat(" 0.000");
s += "\r Transform {";
s += "\r translation " + df.format(x) + df.format(y) + df.format(z);
s += "\r children Shape {";
s += "\r appearance Appearance {";
s += "\r material Material { diffuseColor 1.0 1.0 1.0 }";
s += "\r }";
s += "\r geometry Sphere { radius 0.2 }";
s += "\r }";
s += "\r }";
return s;
}
}
ASKER
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Java3Dthing;
/*
* CylinderTransformer.java
*
* http://forums.sun.com/thread.jspa?threadID=433772&messageID=1943374
*
* Created on 25 July 2003, 11:04
*/
import javax.vecmath.*;
/** A class to calculate the length and transformations necessary to produce a
* cylinder to connect two points. Useful for Java3D and VRML where a cylinder
* object is created aligned along the y-axis.
* @author Alastair Hill
*/
public class CylinderTransformer {
/** point A */
private final Point3f pointA;
/** point B */
private final Point3f pointB;
/** the angle through which to rotate the cylinder */
private float angle;
/** the axis around which to rotate the cylinder */
private Vector3f axis;
/** The translation required to translate the cylinder to the midpoint of the two
* points
*/
private Vector3f translation;
/** The length of the cylinder required to join the two points */
private float length;
/** Creates a new instance of CylinderTransformer
* @param a point a
* @param b point b
*/
public CylinderTransformer(Point3f a, Point3f b) {
pointA = a;
pointB = b;
//carry out the calculations
doCalculations();
}
/** Carries out the necessary calculations so that values may be returned */
private void doCalculations() {
length = pointA.distance(pointB);
float[] arrayA = new float[3];
pointA.get(arrayA);
float[] arrayB = new float[3];
pointB.get(arrayB);
float[] arrayMid = new float[3];
for (int i=0;i<arrayA.length;i++){
arrayMid[i] = (arrayA[i] + arrayB[i]) / 2f;
}
//the translation needed is
translation = new Vector3f(arrayMid);
//the initial orientation of the bond is in the y axis
Vector3f init = new Vector3f(0.0f,1.0f,0.0f);
//the vector needed is the same as that from a to b
Vector3f needed = new Vector3f(pointB.x-pointA.x, pointB.y-pointA.y, pointB.z-pointA.z);
//so the angle to rotate the bond by is:
angle = needed.angle(init);
//and the axis to rotate by is the cross product of the initial and
//needed vectors - ie the vector orthogonal to them both
axis = new Vector3f();
axis.cross(init, needed);
}
/** Returns the angle (in radians) through which to rotate the cylinder
* @return the angle.
*/
public float getAngle() {
return angle;
}
/** The axis around which the cylinder must be rotated
* @return the axis
*/
public javax.vecmath.Vector3f getAxis() {
return axis;
}
/** The length required for the cylinder to join the two points
* @return the length
*/
public float getLength() {
return length;
}
/** The translation required to move the cylinder to the midpoint of the two points
* @return the translation
*/
public javax.vecmath.Vector3f getTranslation() {
return translation;
}
/** Generates a (pretty) string representation of the the CylinderTransformer
* @return the string representation
*/
public String toString(){
return "tr: " + translation + ", ax: " + axis + ", an: " + angle + ", le: " + length;
}
/** Generates the required axis and angle combined into an AxisAngle4f object
* @return the axis and angle
*/
public javax.vecmath.AxisAngle4f getAxisAngle() {
return new AxisAngle4f(axis.x,axis.y,axis.z,angle);
}
}
-------------------------
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Java3Dthing;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
/**
*
* @author olivier
*/
public class runme {
public void go() throws IOException {
FileWriter fos = new FileWriter("B:/xxx.wrl");
BufferedWriter out = new BufferedWriter(fos);
out.write( "#VRML V2.0 utf8");
out.write( "\r Background { skyColor [ 0.0 0.0 0.0 ] }");
out.write(doit( -2.0, 1.0 , 0.0, 2.0, -3.0, 0.0 ));
out.write(doit( -2.0, 1.0 , 0.0, 5.0, -1.0, -5.0 ));
out.close();
}
/**
* returns VMRL declarations for
* - 2 spheres at (x1,y1,z1) and (x2,y2,z2)
* - a cylinder connecting the spheres
*/
public static String doit(double x1, double y1, double z1 ,
double x2, double y2, double z2) {
String s=""; // the output
DecimalFormat df = new DecimalFormat("0.000");
// add spheres
s += getSpheres(x1,y1,z1);
s += getSpheres(x2,y2,z2);
// **** draw cylinder ****
Point3f a = new Point3f();
a.x = (float) x1;
a.y = (float) y1;
a.z = (float) z1;
Point3f b = new Point3f();
b.x = (float) x2;
b.y = (float) y2;
b.z = (float) z2;
CylinderTransformer ct = new CylinderTransformer(a,b);
Vector3f vt = ct.getTranslation();
Vector3f va = ct.getAxis();
s += "\r Transform {";
s += "\r translation " + df.format(vt.x) + " " + df.format(vt.y) + " " + df.format(vt.z);
s += "\r rotation " + df.format(va.x) + " " + df.format(va.y) + " " + df.format(va.z) + " " + df.format(ct.getAngle());
s += "\r children Shape {";
s += "\r appearance Appearance {";
s += "\r material Material { diffuseColor 1.0 0.0 1.0 }";
s += "\r }";
s += "\r geometry Cylinder {";
s += "\r radius 0.1";
s += "\r height " + df.format(ct.getLength());
s += "\r }";
s += "\r }";
s += "\r }";
return s;
}
public static String getSpheres(double x , double y, double z) {
String s=""; // the output
DecimalFormat df = new DecimalFormat("0.000");
s += "\r Transform {";
s += "\r translation " + df.format(x) + " " + df.format(y) + " " + df.format(z);
s += "\r children Shape {";
s += "\r appearance Appearance {";
s += "\r material Material { diffuseColor 1.0 1.0 1.0 }";
s += "\r }";
s += "\r geometry Sphere { radius 0.2 }";
s += "\r }";
s += "\r }";
return s;
}
public static void main(String[] args) throws IOException {
runme demo = new runme();
demo.go();
}
}
The Math / Science topic primarily includes discussions of mathematics, physics, statistics and economic analysis, but also biology, chemistry and other sciences.
TRUSTED BY
ASKER
So, for now, your solution is:
translate x1 y1 z1
rotation 1 0 0 R1 {
rotation 0 0 1 R2 {
cylinder blah
Is there a way to combine the 2 rotations into a single rotation? This would be more efficient on the 'client' side.