Skip to main content

.obj loading in java3d...

8 replies [Last post]
jiapei100
Offline
Joined: 2006-12-04
Points: 0

Hi, all:

In java3d ObjFile.java , function "readVertex " tries to read the "v" nodes in a .obj file, which should probably contain the original cooridnates when producing this .obj file, rather than the normalized ones in "vt" nodes. A segment of my data is shown as:

g main
# 75972 vertices.
v -58.1117 -49.4189 -12.242
v -58.0527 -50.0355 -11.9883
v -58.1128 -50.6568 -11.8222
v -58.1629 -51.2563 -11.7768

v -58.2183 -51.8611 -11.7323
v -58.2231 -52.4784 -11.7214
v -58.259 -53.0993 -11.7188
v -58.3331 -53.7061 -11.7407
v -58.3663 -54.309 -11.7328
v -58.3955 -54.9136 -11.7015
v -58.4142 -55.526 -11.6696

v -58.4299 -56.1264 -11.6939
v -58.427 -56.7551 -11.8301
v -58.4213 -57.3728 -12.0565
v -58.8783 -29.3341 -12.3035
v -58.8634 -29.9544 -12.0902
v -58.8288 -30.5471 -11.949
v -58.7427 -31.1332 -11.886

v -58.6354 -31.7285 -11.9012
v -58.5571 -32.331 -11.9593
...
v 55.3262 -54.4387 -11.2943
v 55.3417 -55.068 -11.3683
v 55.3343 -55.6911 -11.5067
v 55.3041 -56.3406 -11.6606
mtllib /.../filename.mtl

usemtl default
vt 0 0.198847 0.0
vt 0 0.195965 0.0
vt 0 0.193084 0.0
vt 0 0.190202 0.0
vt 0 0.18732 0.0
vt 0 0.184438 0.0
vt 0 0.181556 0.0
vt 0 0.178674 0.0
...

And the "readVertex" is as follows:

void readVertex(ObjectFileParser st) throws ParsingErrorException {
Point3f p = new Point3f();

st.getNumber();
p.x = (float)st.nval;
st.getNumber();
p.y = (float)st.nval;
st.getNumber();
p.z = (float)st.nval;

if ((DEBUG & 32) != 0)
System.out.println(" (" + p.x + "," + p.y + "," + p.z + ")");

st.skipToNextLine();

// Add this vertex to the array
coordList.add(p);
} // End of readVertex

Obviously, variable "coordList" records all data in "v" nodes.
After calling load() to load the .obj file as:

ObjectFile f = new ObjectFile(flags, 0.0f);
m_S = null;
try {
m_S = f.load(fname);
} catch (FileNotFoundException e)

{
...
}
m_BGFace = m_S.getSceneGroup();
m_Object3d = (Shape3D)m_BGFace.getChild(0);

I used Eclipse to debug and watch the expression "f",
f.coordList shows all values as in nodes "vt", rather than "v" !!!!

It seems when loading .obj (ObjectFile), it automatically transform or neglect the original "v" values.
That must be a very serious bug in java3D !!

Because some times, the original data size is of great importance !!!!!

Is java3d still under maintain? If so, please do revise the bug !!!!

Cheers
JIA

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jiapei100
Offline
Joined: 2006-12-04
Points: 0

Finally, I retrieved to
/j3d-core-utils/src/classes/share/com/sun/j3d/loaders/ObjectFile.java
and found the following function:

private void resize() {
int i, j;
Point3f cur_vtx = new Point3f();
float biggest_dif;

Point3f[] limit = getLimits();

// Move object so it's centered on (0,0,0)
Vector3f offset = new Vector3f(-0.5f * (limit[0].x + limit[1].x),
-0.5f * (limit[0].y + limit[1].y),
-0.5f * (limit[0].z + limit[1].z));

if ((DEBUG & 64) != 0) {
System.out.println("Offset amount: (" +
offset.x + "," + offset.y + "," + offset.z + ")");
}

// Find the divide-by value for the normalization
biggest_dif = limit[1].x - limit[0].x;
if (biggest_dif < limit[1].y - limit[0].y)
biggest_dif = limit[1].y - limit[0].y;
if (biggest_dif < limit[1].z - limit[0].z)
biggest_dif = limit[1].z - limit[0].z;
biggest_dif /= 2.0f;

for (i = 0 ; i < coordList.size() ; i++) {

cur_vtx = (Point3f)coordList.get(i);

cur_vtx.add(cur_vtx, offset);

cur_vtx.x /= biggest_dif;
cur_vtx.y /= biggest_dif;
cur_vtx.z /= biggest_dif;

// coordList.setElementAt(cur_vtx, i);
}
} // End of resize

Obviously, this function doesn't store anything in ObjectFile's member variables.
That is to say , If I set parameter ObjectFile.RESIZE, I will lose all the information about original size of the data.

Cheers
JIA

jiapei100
Offline
Joined: 2006-12-04
Points: 0

Finally, I retrieved to
/j3d-core-utils/src/classes/share/com/sun/j3d/loaders/ObjectFile.java
and found the following function:

private void resize() {
int i, j;
Point3f cur_vtx = new Point3f();
float biggest_dif;

Point3f[] limit = getLimits();

// Move object so it's centered on (0,0,0)
Vector3f offset = new Vector3f(-0.5f * (limit[0].x + limit[1].x),
-0.5f * (limit[0].y + limit[1].y),
-0.5f * (limit[0].z + limit[1].z));

if ((DEBUG & 64) != 0) {
System.out.println("Offset amount: (" +
offset.x + "," + offset.y + "," + offset.z + ")");
}

// Find the divide-by value for the normalization
biggest_dif = limit[1].x - limit[0].x;
if (biggest_dif < limit[1].y - limit[0].y)
biggest_dif = limit[1].y - limit[0].y;
if (biggest_dif < limit[1].z - limit[0].z)
biggest_dif = limit[1].z - limit[0].z;
biggest_dif /= 2.0f;

for (i = 0 ; i < coordList.size() ; i++) {

cur_vtx = (Point3f)coordList.get(i);

cur_vtx.add(cur_vtx, offset);

cur_vtx.x /= biggest_dif;
cur_vtx.y /= biggest_dif;
cur_vtx.z /= biggest_dif;

// coordList.setElementAt(cur_vtx, i);
}
} // End of resize

Obviously, this function doesn't store anything in ObjectFile's member variables.
That is to say , If I set parameter ObjectFile.RESIZE, I will lose all the information about original size of the data.

Cheers
JIA

aces
Offline
Joined: 2003-07-17
Points: 0

Hi

At Wavefront Object file specification vt stands for vertex texture data in u,v and optionally in w.
And the coordinates are given by v keyword.

Please check following links :
Wikipedia :
http://en.wikipedia.org/wiki/Obj

Specification :
http://local.wasp.uwa.edu.au/~pbourke/dataformats/obj/

So I guess Java3D's ObjectLoader is correct about this.

jiapei100
Offline
Joined: 2006-12-04
Points: 0

Hi, Thanks you very much aces !!!

yup. vt values are vertex texture, while v values stand for vertex coordinates.

Can you please tell me after .obj loading using

ObjectFile f = new ObjectFile(flags, 0.0f);
m_S = null;
try {
m_S = f.load(fname);
} catch (FileNotFoundException e)

{
...
}
m_BGFace = m_S.getSceneGroup();
m_Object3d = (Shape3D)m_BGFace.getChild(0);

how can I exactly retrieve those vertex coordinates please???

I tried

GeometryArray head = (GeometryArray)m_Object3d.getGeometry();
GeometryInfo gi = new GeometryInfo(head);
Point3f[] coords = gi.getCoordinates();

the variable "coords" shows the triangles vertexes' coordinates, but between -1.0 and 1.0 again !!!!!

Now, I repeat my problem once again:

1) v values
75972 vertexes(v values) in total (these are actually 75972 points on the object for representation.)
All these values are from -200 to +200, in float

2) vt values
correspondingly, there are 75972 vertex textures (vt values), each vt is corresponding to each v.
All these values are from -1.0 to +1.0, in float

3) f values
150958 triangles in total, vertexes of all triangles are among these 75972 vertexes.

It seems I'm able to get the vertex coordinates now, from these 150958 triangles.
However, variable "coords" show all values between -1.0 and 1.0

What's more, even all values in "coordArray" of loaded ObjectFile "f",
(see ObjectFile f = new ObjectFile(flags, 0.0f); )
are also from -1.0 to 1.0

What I expected are the v values, which should be from -200 to 200 !!!!!!!!!

Actually, I tried to watch all member variables of "ObjectFile f", but it seems none is corresponding to
those v values between -200 and 200 !!!

Can you please do help????
Or, it is just a shortcoming of Java3D that after loading .obj file, Java3D will never be able to retrieve it's original size????

Finally, thanks for your answering, but can you please show me the solution please !!!!

Best Regards
JIA Pei

alied
Offline
Joined: 2009-05-05
Points: 0

Ha!
You've been caught by the resize flag!! ;-)
Now serious:-|
try to add this flag ~ObjectFile.RESIZE.
Apparently it's enabled by default.

OMHO it should not be the default behaviour (yet it can be quite usefull in some scenarios)
My suggestion is to change the default RESIZE behaviour to not enabled.

jiapei100
Offline
Joined: 2006-12-04
Points: 0

Hi, Thank you so much " alied".

Yes, As you said, I used parameter "ObjectFile.RESIZE".

The thing is:

Without using this parameter, after loading, I can't see my object at all.
It might be too huge to display on the screen !!!!!

In fact, it's OK for Java3D to load the .obj with "RESIZE",
but, it should be able to tell that
"if using ObjectFile.RESIZE parameter, what is the resize(scaling) times? "

How much would that be?
Say, if java3D automatically resize 1.obj around 95.86 times smaller
and resize 2.obj around 32.98 times smaller.
java3D should and must be able to tell what is the exact number: 95.86 and 32.98 .

Otherwise, it's just able to load the data into a 3D view, but will never tell
the relationship between what has been shown and the original object's scaling relationship.

I just wonder, is there a way out that:

even after loading with ObjectFile.RESIZE parameter,
is there any parameter to remember
how much has the object been resized??
This should be a reasonable requirement when using Java3D.

So, can you give me a clue?

Best Regards
JIA

lamer77
Offline
Joined: 2006-12-22
Points: 0

Instead of scaling the model you should move the view further away from it. You can use getBounds() to find the size of the model. Also remember to increase the far clipping plane (View.setBackClipDistance(...)).

Or you could normalize the model youself by adding the model to a TransformGroup containing a scale transform. Again, use getBounds() to find the size of the model and set the scale to (1/size).

jiapei100
Offline
Joined: 2006-12-04
Points: 0

Hi, Thanks lamer77:

Yes, I knew getBounds() and tried already.

If I loaded with flag: ObjectFile.RESIZE;
my getBounds() returns value from -1.0 to 1.0,
rather than those original vertex coordinates.

The original data is as:

# 75972 vertices.
v -58.1117 -49.4189 -12.242
v -58.0527 -50.0355 -11.9883
v -58.1128 -50.6568 -11.8222
v -58.1629 -51.2563 -11.7768
v -58.2183 -51.8611 -11.7323
v -58.2231 -52.4784 -11.7214
v -58.259 -53.0993 -11.7188
v -58.3331 -53.7061 -11.7407
v -58.3663 -54.309 -11.7328
v -58.3955 -54.9136 -11.7015
v -58.4142 -55.526 -11.6696
v -58.4299 -56.1264 -11.6939
v -58.427 -56.7551 -11.8301
v -58.4213 -57.3728 -12.0565
v -58.8783 -29.3341 -12.3035
v -58.8634 -29.9544 -12.0902
v -58.8288 -30.5471 -11.949
v -58.7427 -31.1332 -11.886
v -58.6354 -31.7285 -11.9012
v -58.5571 -32.331 -11.9593
...
v 55.3262 -54.4387 -11.2943
v 55.3417 -55.068 -11.3683
v 55.3343 -55.6911 -11.5067
v 55.3041 -56.3406 -11.6606
mtllib /.../filename.mtl
usemtl default
vt 0 0.198847 0.0
vt 0 0.195965 0.0
vt 0 0.193084 0.0
vt 0 0.190202 0.0
vt 0 0.18732 0.0
vt 0 0.184438 0.0
vt 0 0.181556 0.0
vt 0 0.178674 0.0
...

My code to load this .obj is as (with getBounds() )

int flags = ObjectFile.TRIANGULATE | ObjectFile.STRIPIFY | ObjectFile.RESIZE;
ObjectFile f = new ObjectFile(flags, 0.0f);
m_S = null;
try {
m_S = f.load(fname);
} catch (FileNotFoundException e)
{
...
}
m_BGFace = m_S.getSceneGroup();
m_Object3d = (Shape3D)m_BGFace.getChild(0);
Bounds m_ObjBounds = m_Object3d.getBounds();

However, after a serious debugging with Eclipse,
m_ObjBounds shows the value as:

lower=Point3d
x=-0.88
y=-1.0
z=-0.67
upper=Point3d
x=0.88
y=1.0
z=0.67

Somebody gave me the suggestion of "getBounds()", please refer to
http://www.javagaming.org/index.php/topic,21734.0.html

So, that is to say,
m_S = f.load(fname);
will resize the original data first, and then load it into the canvas view.

Well, anyway, I'll try to avoid ObjectFile.RESIZE and scale it 200 times and have a try first.
That's exactly what you suggest --- to change the view !!!

I'll show you whether it will work for me or not later.

Cheers
JIA