Surfaces from Generated Points
Posted: Tue 9. Dec 2008, 09:39
Hi,
I have been trying to render surfaces from a set of data points generated from another program, instead of using equations. I was able to write an application - a jReality program that works by using ParametricSurfaceFactory. This is similar to one of the tutorial examples on the jReality web site. I added my code at the end of this message.
I have three problems in extending the code.
1. In my code, I have generated u and v parameter values and stored them in a data structure along with the (x, y, z) coordinates. As I understand, the ParametricSurfaceFactory calls evaluate method of Immersion by generating u and v values. If the parameter values I generate are different from those of ParSurFactory (even in decimal points), the points are not recognized. This is very constraining as in my data generation I would like to have the freedom to choose increments in parametric values (some times non-uniform) and precision as dictated by my problem. Is there a solution to this problem?
2. I have problem setting up various appearance attributes for the surface. I realize that I have to create scene graph node to attach the appearance node and give colors. But I did not have success. Do you have an example program that illustrates this point for surfaces? I have looked at the tutorial examples. I would like to render surfaces that are smooth (filled) and mesh, as in OpenGL.
3. I have tried to use ParametricTriangularSurfaceFactory but without much success. I have set Immersion and then added the following code.
psf.setUVTriangle(new double[][]{{0.0,0.0}, {0.05, 0.0}, {0.0, 0.05}});
psf.setUVTriangle(points);
I do not know how to coordinate my parameter bounds and increments with those of the Factory class. How can I do this?
Here is my code for the ParSurFactory class.
public class SurfaceMyPointsTest {
private double[][] points;
private int uCount = 0;
private int vCount = 0;
public static void main(String[] args) {
SurfaceMyPointsTest test = new SurfaceMyPointsTest();
}
public SurfaceMyPointsTest() {
uCount = 20;
vCount = 20;
generate3DPoints(-0.5, 0.5, -0.5, 0.5);
ParametricSurfaceFactory psf = new ParametricSurfaceFactory(new B_SplineSurface(), 1);
psf.setClosedInUDirection(true);
psf.setClosedInVDirection(true);
psf.setGenerateVertexNormals(true);
//set parameters
psf.setUMin(-0.5);
psf.setUMax(0.5);
psf.setVMin(-0.5);
psf.setVMax(0.5);
psf.setULineCount(uCount);
psf.setVLineCount(vCount);
psf.setGenerateEdgesFromFaces(true);
psf.setGenerateVertexNormals(true);
psf.update();
ViewerApp va = ViewerApp.display(psf.getIndexedFaceSet());
CameraUtility.encompass(va.getCurrentViewer());
}
public double[][] generate3DPoints(double minU, double maxU, double minV, double maxV) {
double quarterU = (maxU - minU) / 4.0;
double quarterV = (maxV - minV) / 4.0;
double threeQuartU = (maxU - minU) * 3.0 / 4.0;
double threeQuartV = (maxV - minV) * 3.0 / 4.0;
double midPointU = (maxU - minU) / 2.0;
double midPointV = (maxV - minV) / 2.0;
points = new double[uCount * vCount][5];
double u = minU;
double v = minV;
double incU = (double) (maxU - minU) / (double) uCount;
double incV = (double) (maxV - minV) / (double) vCount;
int k = 0;
for (int i = 0; i < uCount; i++) {
for (int j = 0; j < vCount; j++) {
double[] point = new double[3];
if ((u > threeQuartU) || (v > threeQuartV) || (u < quarterU) || (v < quarterV)) {
point[0] = u;
point[1] = v;
point[2] = 0.0f;
}
else if (u < midPointU) {
point[0] = u;
point[1] = v;
point[2] = u;
}
else if (v < midPointV) {
point[0] = u;
point[1] = v;
point[2] = v;
}
else if (u > midPointU) {
point[0] = u;
point[1] = v;
point[2] = (maxU - minU) - u;
}
else if (v > midPointV) {
point[0] = u;
point[1] = v;
point[2] = (maxV - minV) - v;
}
else if ((u == midPointU) || (v == midPointV)) {
point[0] = u;
point[1] = v;
point[2] = u;
}
double[] uvPoint = new double[]{u, v, point[0], point[1], point[2]};
System.out.println("Point " + k + "=> u: " + uvPoint[0] + ", v: " + uvPoint[1] + ", x: " + uvPoint[2] + ", y: " + uvPoint[3] + ", z: " + uvPoint[4]);
points[k] = uvPoint;
k++;
v = roundTwoDecimals(v + incV);
}
v = minV;
u = roundTwoDecimals(u + incU);
}
return points;
}
public double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
public class B_SplineSurface implements Immersion {
int l = 0;
public void evaluate(double u, double v, double[] xyz, int index) {
double u1 = roundTwoDecimals(u);
double v1 = roundTwoDecimals(v);
double[] uvPoint = getElement(u1, v1);
if (uvPoint != null){
xyz[index] = uvPoint[2];
xyz[index + 1] = uvPoint[3];
xyz[index + 2] = uvPoint[4];
System.out.println("Point-" + (l++) + ": X= " + xyz[index] + ", Y= " + xyz[index + 1] + ", Z= " + xyz[index + 2]);
}
else
System.out.println("Cannot find: u=" + u1 + ", v=" + v1);
}
private double[] getElement(double u, double v) {
for (int i = 0; i < points.length; i++){
double[] point = points[i];
if (u == point[0] && v == point[1])
return point;
}
System.out.println("Failed to find in points the values: u=" + u + ", v=" + v);
return null;
}
public int getDimensionOfAmbientSpace() {
return 3;
}
public boolean isImmutable() {
return true;
}
}
}
Thank you very much!
Karuna
I have been trying to render surfaces from a set of data points generated from another program, instead of using equations. I was able to write an application - a jReality program that works by using ParametricSurfaceFactory. This is similar to one of the tutorial examples on the jReality web site. I added my code at the end of this message.
I have three problems in extending the code.
1. In my code, I have generated u and v parameter values and stored them in a data structure along with the (x, y, z) coordinates. As I understand, the ParametricSurfaceFactory calls evaluate method of Immersion by generating u and v values. If the parameter values I generate are different from those of ParSurFactory (even in decimal points), the points are not recognized. This is very constraining as in my data generation I would like to have the freedom to choose increments in parametric values (some times non-uniform) and precision as dictated by my problem. Is there a solution to this problem?
2. I have problem setting up various appearance attributes for the surface. I realize that I have to create scene graph node to attach the appearance node and give colors. But I did not have success. Do you have an example program that illustrates this point for surfaces? I have looked at the tutorial examples. I would like to render surfaces that are smooth (filled) and mesh, as in OpenGL.
3. I have tried to use ParametricTriangularSurfaceFactory but without much success. I have set Immersion and then added the following code.
psf.setUVTriangle(new double[][]{{0.0,0.0}, {0.05, 0.0}, {0.0, 0.05}});
psf.setUVTriangle(points);
I do not know how to coordinate my parameter bounds and increments with those of the Factory class. How can I do this?
Here is my code for the ParSurFactory class.
public class SurfaceMyPointsTest {
private double[][] points;
private int uCount = 0;
private int vCount = 0;
public static void main(String[] args) {
SurfaceMyPointsTest test = new SurfaceMyPointsTest();
}
public SurfaceMyPointsTest() {
uCount = 20;
vCount = 20;
generate3DPoints(-0.5, 0.5, -0.5, 0.5);
ParametricSurfaceFactory psf = new ParametricSurfaceFactory(new B_SplineSurface(), 1);
psf.setClosedInUDirection(true);
psf.setClosedInVDirection(true);
psf.setGenerateVertexNormals(true);
//set parameters
psf.setUMin(-0.5);
psf.setUMax(0.5);
psf.setVMin(-0.5);
psf.setVMax(0.5);
psf.setULineCount(uCount);
psf.setVLineCount(vCount);
psf.setGenerateEdgesFromFaces(true);
psf.setGenerateVertexNormals(true);
psf.update();
ViewerApp va = ViewerApp.display(psf.getIndexedFaceSet());
CameraUtility.encompass(va.getCurrentViewer());
}
public double[][] generate3DPoints(double minU, double maxU, double minV, double maxV) {
double quarterU = (maxU - minU) / 4.0;
double quarterV = (maxV - minV) / 4.0;
double threeQuartU = (maxU - minU) * 3.0 / 4.0;
double threeQuartV = (maxV - minV) * 3.0 / 4.0;
double midPointU = (maxU - minU) / 2.0;
double midPointV = (maxV - minV) / 2.0;
points = new double[uCount * vCount][5];
double u = minU;
double v = minV;
double incU = (double) (maxU - minU) / (double) uCount;
double incV = (double) (maxV - minV) / (double) vCount;
int k = 0;
for (int i = 0; i < uCount; i++) {
for (int j = 0; j < vCount; j++) {
double[] point = new double[3];
if ((u > threeQuartU) || (v > threeQuartV) || (u < quarterU) || (v < quarterV)) {
point[0] = u;
point[1] = v;
point[2] = 0.0f;
}
else if (u < midPointU) {
point[0] = u;
point[1] = v;
point[2] = u;
}
else if (v < midPointV) {
point[0] = u;
point[1] = v;
point[2] = v;
}
else if (u > midPointU) {
point[0] = u;
point[1] = v;
point[2] = (maxU - minU) - u;
}
else if (v > midPointV) {
point[0] = u;
point[1] = v;
point[2] = (maxV - minV) - v;
}
else if ((u == midPointU) || (v == midPointV)) {
point[0] = u;
point[1] = v;
point[2] = u;
}
double[] uvPoint = new double[]{u, v, point[0], point[1], point[2]};
System.out.println("Point " + k + "=> u: " + uvPoint[0] + ", v: " + uvPoint[1] + ", x: " + uvPoint[2] + ", y: " + uvPoint[3] + ", z: " + uvPoint[4]);
points[k] = uvPoint;
k++;
v = roundTwoDecimals(v + incV);
}
v = minV;
u = roundTwoDecimals(u + incU);
}
return points;
}
public double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
public class B_SplineSurface implements Immersion {
int l = 0;
public void evaluate(double u, double v, double[] xyz, int index) {
double u1 = roundTwoDecimals(u);
double v1 = roundTwoDecimals(v);
double[] uvPoint = getElement(u1, v1);
if (uvPoint != null){
xyz[index] = uvPoint[2];
xyz[index + 1] = uvPoint[3];
xyz[index + 2] = uvPoint[4];
System.out.println("Point-" + (l++) + ": X= " + xyz[index] + ", Y= " + xyz[index + 1] + ", Z= " + xyz[index + 2]);
}
else
System.out.println("Cannot find: u=" + u1 + ", v=" + v1);
}
private double[] getElement(double u, double v) {
for (int i = 0; i < points.length; i++){
double[] point = points[i];
if (u == point[0] && v == point[1])
return point;
}
System.out.println("Failed to find in points the values: u=" + u + ", v=" + v);
return null;
}
public int getDimensionOfAmbientSpace() {
return 3;
}
public boolean isImmutable() {
return true;
}
}
}
Thank you very much!
Karuna