Skip to main content

Collada loader

29 replies [Last post]
mcneillk
Offline
Joined: 2005-02-03

In case anyone is interested, in the course of working on J3DWorkbench, I have adopted, and started to improve and fix the Collada loader, whose source code is in the Java 3D incubator (paulby) and which was already worked on by the person who writes this blog (http://shinoblogbyshiva.blogspot.com/search/label/Collada).

I will work with 'aces' to integrate these changes back into the incubator if there is sufficient interest...

The loader will be a part of the next release of J3DWorkbench for fast importing of 3D assets from google, etc.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
puybaret
Offline
Joined: 2004-12-04

Ken,

May I suggest you too to improve readImage method in Collada14LoaderUtils class with this code:

[code] public static BufferedImage readImage(URL url, String path)
{
URL resolvedUrl;
try {
resolvedUrl = new URL(url, path);
} catch (MalformedURLException ex) {
return null;
}

BufferedImage image = null;
try {
image = ImageIO.read(resolvedUrl);
} catch (IOException e) {
} catch (IllegalArgumentException e) {
}

if (image == null) {
try {
image = JimiImageReader.readImage(resolvedUrl);
} catch (NoClassDefFoundError e2) {
// No Jimi classes in classpath
}
}

return image;
}

// Use a separate class to access Jimi in case Jimi classes are not in classpath
private static class JimiImageReader {
public static BufferedImage readImage(URL url) {
try {
Logger.getLogger("global").log(Level.INFO,
"Trying to load image with Jimi : " + url);
JimiReader reader = Jimi.createJimiReader(url);
Dimension d = reader.getSize();
BufferedImage bi = new BufferedImage(d.width, d.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(reader.getImage(), 0, 0, null);
g.dispose();
return bi;
} catch (JimiException e) {
e.printStackTrace();
return null;
}
}
}
[/code]

I replaced too generic "catch (Exception e)" by more specific ones, added a call to Graphics#dispose (Graphics resources may be limited and should be disposed as soon as possible), and used a separate static class to access Jimi. This will allow the users of your lib to distribute your loader without Jimi and save 459 KB (= JimiProClasses.zip file size).
Since almost all Collada files probably include only images supported in JDK (JPEG, PNG, GIF or BMP), this shouldn't be a problem.

tmilard
Offline
Joined: 2004-03-25

Thank you Ken.

By the way Ken I also noticed that objects like trees (with multiple placemnt like a tree used the same leave 50 times) render with .... one leave.

I have tno time to understand that in April or may but I will try to see if I can correct this in June.

tmilard
Offline
Joined: 2004-03-25

> If you have any code to suggest, please post or attach...
> -Ken

***************************************************
* Maintenance of java3D Collada loader (http://eclectic3d.net/node/26)
*[b] Improved the [u]performance [/u]to load a bunch of Collada files. [/b] .
For 6 collada files, expect a perfromance improve of 60% or 80%.
****************************************************

1) Introduction:
This maintenance is quite importante because I have noticed a really slow loading as soon as you have 4 or 10 or 20 collada files you are trying to load.

2) A small bug corrected :
The correction is simple : The Collada Shema was [u]recalculated for each[/u] of collada files. Witch was not necessary.
- Now the Shema is calculated only once... for the first Collada files it sees.
- For the others collada files, it just reuses the same shema.

3) Code change Explanation:
The change Only are only in the classe Collada14Loader.
Changes are small, I am honnest (but result is great).

3a) I add a new method getJAXBContextForColladaschema() to get the JAXBContext.
It uses the singleton pattern : Only one instance once and for all.

3b) The method load(URL url) is a bit changed.
To get the JAXBContext :
- It now uses the getter getJAXBContextForColladaschema() and not anymore the the local variable JAXBContext jc.

4) code change source :
Here is the code (change takes place at line 141 of Collada14Loader.java ):

//----------------------------------
// THM 08/03/2010 To speed up process of loading many collada files in a row, it is better
// to create only and for all once the JAXBContext.
//
// New version of methods :
private JAXBContext linkJAXBContextForColladaschema = null;
private JAXBContext getJAXBContextForColladaschema() {
if (linkJAXBContextForColladaschema == null){
try {
System.out.println("Collada14Loader>>getJAXBContextForColladaschema() avant : linkJAXBContextForColladaschema = javax.xml.bind.JAXBContext.newInstance(\"org.collada.colladaschema\");");
linkJAXBContextForColladaschema = javax.xml.bind.JAXBContext.newInstance("org.collada.colladaschema");
System.out.println("Collada14Loader>>getJAXBContextForColladaschema() apres : linkJAXBContextForColladaschema = javax.xml.bind.JAXBContext.newInstance(\"org.collada.colladaschema\");");

} catch (JAXBException ex) {
Logger.getLogger(GLOBAL).log(Level.SEVERE, null, ex);
}

}
return linkJAXBContextForColladaschema;
}

public Scene load(URL url) throws FileNotFoundException,
IncorrectFormatException, ParsingErrorException {
try {
ElementCache.cache().setLoadingURL(url);
Unmarshaller unmarshaller = getJAXBContextForColladaschema().createUnmarshaller();
COLLADA collada =
(org.collada.colladaschema.COLLADA) unmarshaller
.unmarshal(url);

return doLoad(collada);
} catch (JAXBException ex) {
Logger.getLogger(GLOBAL).log(Level.SEVERE, null, ex);
}

return null;
}

// Old version of method :
/*
public Scene load(URL url) throws FileNotFoundException,
IncorrectFormatException, ParsingErrorException {
try {
ElementCache.cache().setLoadingURL(url);

JAXBContext jc =
javax.xml.bind.JAXBContext
.newInstance("org.collada.colladaschema");
Unmarshaller unmarshaller = jc.createUnmarshaller();
COLLADA collada =
(org.collada.colladaschema.COLLADA) unmarshaller
.unmarshal(url);

return doLoad(collada);
} catch (JAXBException ex) {
Logger.getLogger(GLOBAL).log(Level.SEVERE, null, ex);
}

return null;
}
*/
//----------------------------------

This is it.

4) Conclusion:
I successfully tested the code on a concrete example.
It really at least double the speed of the collada-loading process.
I think this small change should be added to the new version of this (by the way) wonderfull collada loader.

Thierry

Ps: Here is also a link to a post I made on my blog concerning the use I make from the Collada loader in my software.
http://www.free-visit.net/index.php?option=com_content&view=article&id=4...

tmilard
Offline
Joined: 2004-03-25

* Maintenance of java3D Collada loader (http://eclectic3d.net/node/26)
* Added "Lambert" node parser code

[b]1) Introduction:[/b]
this maintenance is quite importante as on "google 3D Warehouse" ( http://sketchup.google.com/3dwarehouse )many files are generated by Sketup... and sketup generates the technique "Lambert" instead of "Phong".
By the way it seems :
- "Lambert" rendering = Unpolished surface rendering (no reflexion)
- "Phong" rendering = Plastic looking surface (reflexion)

[b]2) a bug:[/b]
The "Lambert" rendering of Collada files that were imported in java3D scene did not work : The result 3D Object had :
- no colors (just white)
- no texture

The raison of this bug is simple : Lambert was not implemented.

[b]3) Code change [/b]:
[u]3a) a classe LambertProcessor.java is created. [/u]
It is a copy of the classe PhongProcessor with some updates.
Here is the code:

/*
* $RCSfile: LambertProcessor.java,v $
*/

package org.jdesktop.j3d.loaders.collada.xml_walker;

import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.List;

import javax.media.j3d.Appearance;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture2D;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Color3f;

import org.collada.colladaschema.CommonColorOrTextureType;
import org.collada.colladaschema.CommonFloatOrParamType;
import org.collada.colladaschema.CommonNewparamType;
import org.collada.colladaschema.Image;
import org.collada.colladaschema.CommonColorOrTextureType.Color;
import org.collada.colladaschema.CommonColorOrTextureType.Texture;
import org.collada.colladaschema.ProfileCOMMON.Technique.Lambert;
import org.jdesktop.j3d.loaders.collada.utils.Collada14LoaderUtils;

import com.sun.j3d.utils.image.TextureLoader;

/**
*
* @author Thierry (copied-and modified from classe PhongProcessor of Paulby)
*/
public class LambertProcessor extends Processor {

private Appearance app = null;

//private Phong phong;
private Lambert lambert;

private enum Type {
AMBIENT, EMISSION, DIFFUSE, SPECULAR
}

public LambertProcessor(Lambert lambert, Processor parent) {
super(lambert, parent);
//System.out.println("LambertProcessor>>constructor(Lambert, Processor) Begin ");
this.lambert = lambert;
//System.out.println("LambertProcessor>>constructor(Lambert, Processor) End ");
}

@Override
public void create(Node parent) {
//System.out.println("LambertProcessor>>create(Node) begin ");
if (app != null) {
((Shape3D) parent).setAppearance(app);
return;
}

if (parent instanceof Shape3D) {
Shape3D s3d = (Shape3D) parent;
app = s3d.getAppearance();
}

if (app == null) {
app = new Appearance();
}

if (lambert != null) {
app.setMaterial(new Material());

CommonColorOrTextureType fccott = lambert.getAmbient();
if (fccott != null) {
processColorOrTexture(fccott, app, Type.AMBIENT);
}

fccott = lambert.getDiffuse();
if (fccott != null) {
processColorOrTexture(fccott, app, Type.DIFFUSE);
}

fccott = lambert.getEmission();
if (fccott != null) {
processColorOrTexture(fccott, app, Type.EMISSION);
}

// THM 23/02/2010 No 'Specular' in Lambert
/*
fccott = lambert.getSpecular();
if (fccott != null) {
processColorOrTexture(fccott, app, Type.SPECULAR);
}
*/

// CommonTransparentType transType = phong.getTransparent();
CommonFloatOrParamType transparency = lambert.getTransparency();
if (transparency != null) {
CommonFloatOrParamType.Float f = transparency
.getFloat();
if (f != null) {
float fl = (float) f.getValue();
if (fl == 1.0f) {
fl = 0.0f;
}
if (fl > 0.0f) {
TransparencyAttributes ta = app
.getTransparencyAttributes();
if (ta == null) {
ta = new TransparencyAttributes();
app.setTransparencyAttributes(ta);
}
ta.setTransparency(fl);
ta.setTransparencyMode(TransparencyAttributes.NICEST);
ta.setTransparencyMode(TransparencyAttributes.BLENDED);
}
}
}

// THM 23/02/2010 No 'Shininess' in Lambert
/*
CommonFloatOrParamType shininess = lambert.getShininess();
if (shininess != null) {
CommonFloatOrParamType.Float f = shininess
.getFloat();
if (f != null && f.getValue() > 0.0f) {
app.getMaterial().setShininess((float) f.getValue());
}
}
*/

}

((Shape3D) parent).setAppearance(app);
//System.out.println("LambertProcessor>>create(Node) End ");

}

/**
* Create a color3f from the supplied color
*/
private void processColorOrTexture(CommonColorOrTextureType colorOrTexture,
Appearance app, Type t) {
//System.out.println("LambertProcessor>>processColorOrTexture(CommonColorOrTextureType, Appearance, Type) begin ");

Color color = colorOrTexture.getColor();
if (color != null) {
Material mat = app.getMaterial();

List c = color.getValues();

float[] result = new float[c.size()];
int i = 0;
for (Double d : c) {
result[i++] = d.floatValue();
}
switch (t) {
case AMBIENT:
mat.setAmbientColor(new Color3f(result));
break;
case DIFFUSE:
if (result.length == 3) {
mat.setDiffuseColor(new Color3f(result));
} else {
mat.setDiffuseColor(result[0], result[1], result[2],
result[3]);
}
break;
case EMISSION:
mat.setEmissiveColor(new Color3f(result));
break;
case SPECULAR:
mat.setSpecularColor(new Color3f(result));
break;
}
} else {
Texture te = colorOrTexture.getTexture();
String tex = te.getTexture();
ElementCache ec = ElementCache.cache();
CommonNewparamType cnt = ec.getNewParam(tex);
tex = cnt.getSampler2D().getSource();
cnt = ec.getNewParam(tex);
Image im = (Image) cnt.getSurface().getInitFroms().get(0)
.getValue();
tex = im.getId();

String path = ElementCache.cache().getImage(tex);
URL url = ElementCache.cache().getLoadingURL();
BufferedImage image = Collada14LoaderUtils.readImage(url, path);
if (image != null) {
Texture2D tex2d = (Texture2D) new TextureLoader(image)
.getTexture();
app.setTexture(tex2d);
}

}
//System.out.println("LambertProcessor>>processColorOrTexture(CommonColorOrTextureType, Appearance, Type) end ");

}
}

[u]3b) the classe ProfileCOMMONProcessor.java is updated. [/u]
Just go on line 117 [just before "if (tech.getBlinn() != null) " ] and as these lines:

//---------------------------------------------------------------
// THM 23/02/2010 Added to be able to sumport Lambert type surfaces
if (tech.getLambert() != null) {
Processor p = (Processor) ProcessorFactory.createProcessor(tech
.getLambert(), this);
if (p != null) {
children.add(p);
}
}
//---------------------------------------------------------------

This is it.

[b]4) Conclusion:[/b]
I successfully tested the code on about 15 files with surface.
It worked fine.
I do suppose it does now work with all Collada files generated by Sketshup.

Thierry

ylliac
Offline
Joined: 2009-06-19

Now you can do the same for "constant" type which is just a simple color if I remember.

Here is the code I wrote to do it :

public class ConstantProcessor extends Processor {

private Appearance app = null;

private Constant constant;

private enum Type {
AMBIENT, EMISSION, DIFFUSE, SPECULAR
}

public ConstantProcessor(Constant constant, Processor parent) {
super(constant, parent);

this.constant = constant;

}

@Override
public void create(Node parent) {

if (app != null) {
((Shape3D) parent).setAppearance(app);
return;
}

if (parent instanceof Shape3D) {
Shape3D s3d = (Shape3D) parent;
app = s3d.getAppearance();
}

if (app == null) {
app = new Appearance();
}

if (constant != null) {
app.setMaterial(new Material());

CommonColorOrTextureType fccott = constant.getEmission();
if (fccott != null) {
processColorOrTexture(fccott, app, Type.EMISSION);
}

// CommonTransparentType transType = phong.getTransparent();
CommonFloatOrParamType transparency = constant.getTransparency();
if (transparency != null) {
com.ipsis.ij3d.modeling.io.collada.colladaschema.CommonFloatOrParamType.Float f = transparency
.getFloat();
if (f != null) {
float fl = (float) f.getValue();
if (fl == 1.0f) {
fl = 0.0f;
}
if (fl > 0.0f) {
TransparencyAttributes ta = app.getTransparencyAttributes();
if (ta == null) {
ta = new TransparencyAttributes();
app.setTransparencyAttributes(ta);
}
ta.setTransparency(fl);
ta.setTransparencyMode(TransparencyAttributes.NICEST);
ta.setTransparencyMode(TransparencyAttributes.BLENDED);
}
}
}

// CommonFloatOrParamType reflectivity = phong.getReflectivity();
// if (reflectivity != null) {
// org.collada.colladaschema.CommonFloatOrParamType.Float f =
// reflectivity
// .getFloat();
// if (f != null) {
//
// }
// }

}

((Shape3D) parent).setAppearance(app);
}

/**
* Create a color3f from the supplied color
*/
private void processColorOrTexture(CommonColorOrTextureType colorOrTexture,
Appearance app, Type t) {

Color color = colorOrTexture.getColor();
if (color != null) {
Material mat = app.getMaterial();

List c = color.getValues();

float[] result = new float[c.size()];
int i = 0;
for (Double d : c) {
result[i++] = d.floatValue();
}
switch (t) {
case AMBIENT:
mat.setAmbientColor(new Color3f(result));
break;
case DIFFUSE:
if (result.length == 3) {
mat.setDiffuseColor(new Color3f(result));
}
else {
mat.setDiffuseColor(result[0], result[1], result[2], result[3]);
}
break;
case EMISSION:
mat.setEmissiveColor(new Color3f(result));
break;
case SPECULAR:
mat.setSpecularColor(new Color3f(result));
break;
}
}
else {
Texture te = colorOrTexture.getTexture();
String tex = te.getTexture();
ElementCache ec = ElementCache.cache();
CommonNewparamType cnt = ec.getNewParam(tex);
tex = cnt.getSampler2D().getSource();
cnt = ec.getNewParam(tex);
Image im = (Image) cnt.getSurface().getInitFroms().get(0).getValue();
tex = im.getId();

String path = ElementCache.cache().getImage(tex);
URL url = ElementCache.cache().getLoadingURL();
BufferedImage image = Collada14LoaderUtils.readImage(url, path);
if (image != null) {
Texture2D tex2d = (Texture2D) new TextureLoader(image).getTexture();
app.setTexture(tex2d);
}

}
}
}

And here the code for "lines" geometry (you have to modify PrimitiveProcessor and copy TrianglesProcessor


public class PrimitiveProcessor extends Processor {

/**
* Type de géométrie.
*/
enum Type {
TRIANGLES, LINES, POLYLIST
};

public PrimitiveProcessor(Object colladaSchema, Processor parent) {
super(colladaSchema, parent);
}

// private int[] vertexCount = null;
private int[] prim = null;

// private ArrayList vertices=null;
// private ArrayList normals=null;

private int[] coordinateIndices = null;
private float[] coordinates = null;
private int[] normalIndices = null;
private float[] normals = null;
private int[] texCoordinateIndices = null;
private float[] texCoordinates = null;

private String materialId = null;

protected void initiate(List inputs,
List pList, String matId) {
if (pList != null) {
prim = new int[pList.size()];
int i = 0;
for (BigInteger p : pList)
prim[i++] = p.intValue();
}

int maxOffset = 0;
for (InputLocalOffset in : inputs) {
maxOffset = Math.max(in.getOffset().intValue(), maxOffset);
}

for (InputLocalOffset in : inputs) {
logger.info("Inputs " + in.getSemantic() + " source " + in.getSource()
+ " offset " + in.getOffset());

if (in.getSemantic().equalsIgnoreCase("VERTEX")) {
processVertices(in, maxOffset);
}
else if (in.getSemantic().equalsIgnoreCase("NORMAL")) {
processNormals(in, maxOffset);
}
else if (in.getSemantic().equalsIgnoreCase("TEXCOORD")) {
processTexCoordinates(in, maxOffset);
}
else {
logger.warning("UNIMPLEMENTED SEMANTIC " + in.getSemantic());
}
}
materialId = matId;
}

private void processVertices(InputLocalOffset in, int maxOffset) {
VerticesProcessor source = ElementCache.cache().getVertices(in.getSource());
int offset = in.getOffset().intValue();

if (source == null) {
logger.warning("Failed to get Vertices " + in.getSource());
}
else {
// POSITION
coordinates = source.getFloatArray();

ArrayList coordInd = new ArrayList();
for (int i = offset; i < prim.length; i += maxOffset + 1) {
coordInd.add(prim[i]);
}

coordinateIndices = new int[coordInd.size()];
int i = 0;
for (int index : coordInd) {
coordinateIndices[i++] = index;
}

// NORMAL
if (source.normalDefined()) {
normals = source.getNormalFloatArray();
ArrayList normInd = new ArrayList();
for (i = offset; i < prim.length; i += maxOffset + 1) {
normInd.add(prim[i]);
}

normalIndices = new int[normInd.size()];
i = 0;
for (int index : normInd) {
normalIndices[i++] = index;
}
}
}
}

private void processTexCoordinates(InputLocalOffset in, int maxOffset) {
SourceProcessor source = ElementCache.cache().getSource(in.getSource());
int offset = in.getOffset().intValue();

if (source == null) {
logger.warning("Failed to get texcoords " + in.getSource());
}
else {
texCoordinates = source.getFloatArray();

ArrayList coordInd = new ArrayList();
for (int i = offset; i < prim.length; i += maxOffset + 1) {
coordInd.add(prim[i]);
}

texCoordinateIndices = new int[coordInd.size()];
int i = 0;
for (int index : coordInd) {
texCoordinateIndices[i++] = index;
}
}
}

private void processNormals(InputLocalOffset in, int maxOffset) {
SourceProcessor source = ElementCache.cache().getSource(in.getSource());

int offset = in.getOffset().intValue();

if (source == null) {
logger.warning("Failed to get Normals " + in.getSource());
}
else {
normals = source.getFloatArray();
ArrayList normInd = new ArrayList();
for (int i = offset; i < prim.length; i += maxOffset + 1) {
normInd.add(prim[i]);
}

normalIndices = new int[normInd.size()];
int i = 0;
for (int index : normInd)
normalIndices[i++] = index;
}
}

protected Shape3D getShape3D(Type type) {
logger.info("TrianglesTypeProcessor#getShape3D");

Shape3D s3d = new Shape3D();
s3d.setAppearance(new Appearance());

// On met la couleur par défaut à noir pour visualiser les
// lignes
ColoringAttributes ca = new ColoringAttributes(new Color3f(Color.BLACK),
ColoringAttributes.FASTEST);
s3d.getAppearance().setColoringAttributes(ca);

// Création de la géométrie

switch (type) {

case TRIANGLES:
case POLYLIST:
int geometryType = GeometryInfo.TRIANGLE_ARRAY;
if (Type.TRIANGLES.equals(type)) {
geometryType = GeometryInfo.TRIANGLE_ARRAY;
}
else if (Type.POLYLIST.equals(type)) {
geometryType = GeometryInfo.QUAD_ARRAY;
}

GeometryInfo gi = new GeometryInfo(geometryType);
gi.setCoordinates(coordinates);
gi.setCoordinateIndices(coordinateIndices);

if (texCoordinates != null) {
gi.setTextureCoordinateParams(1, 2);
gi.setTextureCoordinates(0, texCoordinates);
gi.setTextureCoordinateIndices(0, texCoordinateIndices);
}

if (normals != null) {
gi.setNormals(normals);
gi.setNormalIndices(normalIndices);
}

Stripifier strip = new Stripifier();
strip.stripify(gi);
// StripifierStats stats = strip.getStripifierStats();

s3d.addGeometry(gi.getGeometryArray());
break;

case LINES:

IndexedLineArray geom = null;

if (texCoordinates == null) {
geom = new IndexedLineArray(coordinates.length,
GeometryArray.COORDINATES, coordinateIndices.length);
}
else {
int[] texCoordSetMap = { 0 };
geom = new IndexedLineArray(coordinates.length,
GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2, 1,
texCoordSetMap, coordinateIndices.length);
geom.setTextureCoordinates(0, 0, texCoordinates);
geom.setTextureCoordinateIndices(0, 0, texCoordinateIndices);
}

geom.setCoordinates(0, coordinates);
geom.setCoordinateIndices(0, coordinateIndices);

s3d.addGeometry(geom);
break;
}

// Création du matériau

String s = ElementCache.cache().getMaterial(materialId);
MaterialProcessor matProc = (MaterialProcessor) ElementCache.cache().get(s);
if (matProc != null) {
matProc.create(s3d);
}

if (Collada14LoaderOptions.getInstance().isColored()) {
Appearance ap = new Appearance();
ap.setColoringAttributes(new ColoringAttributes(new Color3f((float) Math
.random(), (float) Math.random(), (float) Math.random()),
ColoringAttributes.NICEST));
s3d.setAppearance(ap);
}

return s3d;
}
}

and ...


public class TrianglesProcessor extends PrimitiveProcessor implements Primitive {

private Logger logger = Logger.getLogger(Collada14Loader.COLLADA_PROCESSOR);

/** Creates a new instance of PolylistProcessor */
public TrianglesProcessor(Triangles triangles, Processor parent) {
super(triangles, parent);
logger.info("Triangles " + triangles.getName());

List inputs = triangles.getInputs();
List pList = triangles.getP();
initiate(inputs, pList, triangles.getMaterial());

}

public Shape3D getShape3D() {
logger.info("TrianglesTypeProcessor#getShape3D");

return super.getShape3D(PrimitiveProcessor.Type.TRIANGLES);
}
}

Hope this helps. Hopefully with that you will really load all sketchup model ;)

tmilard
Offline
Joined: 2004-03-25

Hello yliac, thanks for the help. Open source is really cool.
I tryed this morning to implement "constant type like you said.
perhaps because I am not to much aware of importer things, I must admit I do have an issue.
Heer it goes :
1) I created ConstantProcessor lie you said --> No problem.

2) I tryed to modify class [b]PrimitiveProcessor [/b]but I am having compiling issues (and shame on me ...understanding issues) on function processVertices(InputLocalOffset in, int maxOffset):

This is the original function (from Ken's Eclectic source). It does complile.
My question is is there someting missing or is the code complete from your point of Vue ?

private void processVerticesOld(InputLocalOffset in, int maxOffset) {
VerticesProcessor source = ElementCache.cache().getVertices(
in.getSource());
int offset = in.getOffset().intValue();

if (source == null) {
logger.warning("Failed to get Vertices " + in.getSource());
} else {
coordinates = source.getFloatArray();

ArrayList coordInd = new ArrayList();
for (int i = offset; i < prim.length; i += maxOffset + 1) {
//coordInd.add(prim[i]);
coordInd.add(prim);

}

coordinateIndices = new int[coordInd.size()];
int i = 0;
for (int index : coordInd)
coordinateIndices[i++] = index;
}
}

Thanks again yliac.
Thierry

Message was edited by: tmilard

ylliac
Offline
Joined: 2009-06-19

I don't remember very well what I changed and I forgot I had modified VerticesProcessor too.

It's because normals can be defined in two differents nodes and the loader was only able to load one possibility (don't remember in detail and honestly doesn't have much time to search :D).

So I modified VerticesProcessor class this way :

public class VerticesProcessor extends Processor {

private Logger logger = Logger.getLogger(Collada14Loader.COLLADA_PROCESSOR);

private SourceProcessor positionSource = null;

private SourceProcessor normalSource = null;

/** Creates a new instance of VerticesProcessor */
public VerticesProcessor(Vertices vert, Processor parent) {
super(vert, parent);
logger.info("Processing Vertices");
ElementCache.cache().putVertices(vert.getId(), this);
List inputs = vert.getInputs();
for (InputLocal input : inputs) {
logger.info("Semantic " + input.getSemantic() + " source "
+ input.getSource());
if (input.getSemantic().equals("POSITION")) {
positionSource = ElementCache.cache().getSource(input.getSource());
}
else if (input.getSemantic().equals("NORMAL")) {
normalSource = ElementCache.cache().getSource(input.getSource());
}
else {
logger.warning("Ignoring vertices semantic " + input.getSemantic());
}
}
}

Tuple3f getTuple3f(Tuple3f result, int index) {
return positionSource.getTuple3f(result, index);
}

float[] getFloatArray() {
return positionSource.getFloatArray();
}

boolean normalDefined() {
return normalSource != null;
}

Tuple3f getNormalTuple3f(Tuple3f result, int index) {
result = null;

if (normalDefined()) {
normalSource.getTuple3f(result, index);
}

return result;
}

float[] getNormalFloatArray() {
float[] result = null;

if (normalDefined()) {
result = normalSource.getFloatArray();
}

return result;
}

}

If it doesn't compile, it is probably because I forgot another thing ... just tell me where is the error and I'll try to find out what is missing.

Antoine

tmilard
Offline
Joined: 2004-03-25

-- Bizare import issue when import .dae file into java3D scene
--> Just white without colors or Textures

Hello java3d colleagues.

I have been using Ken's Collada impoorter for java3D ( http://eclectic3d.net/node/26 ).

Now I am facing an issue I can't manage to debug myself.. It's not a bug since there is no Exception Thrown... and I do see the 3D Objetct in my java3d scene.... but completely white
It does this "only on" about 80% of the collada files I am using on google 3D warehouse ( http://sketchup.google.com/3dwarehouse ).

I am not an expert of 3d formats and really not an I do not know too much about collada.

[b]So if someone has an idea (even idiot one ) of why a collada .dae files sometimes is ok and why some others just do not show there color or Texture.
[/b]
Cheers and vive java3D
Thierry

ylliac
Offline
Joined: 2009-06-19

I think it's because the loader doesn't support some specifications. For your problem it's because the "lambert" node is not parsed I think. You can add it copying the code used for the "phong" node. Same thing for "lines" geometry, you have to copy and adapt the code used for "triangles" geometry.

This problem can be annoying when you export from sketchup to kmz/dae because it seems to use "lambert" nodes every time :D

I managed to resolve theses problems easily (max 2hours) doing what I said before. Unfortunately I don't have the time nor the rights to upload that ...

Regards,
Antoine

tmilard
Offline
Joined: 2004-03-25

> For your problem it's because the
> "lambert" node is not parsed I think. You can add it
> copying the code used for the "phong" node.
> This problem can be annoying when you export from
> sketchup to kmz/dae because it seems to use "lambert"
> nodes every time :D
> Antoine
===> big thank you Antoine for this tip. I must say "Lambert" sounds to me more like my neigbourg than anything else ;-)) but it is a good opotunity to google this and dive in Collada specification. I will give you feedback.
Thierry

mcneillk
Offline
Joined: 2005-02-03

I have noticed this as well--I will add a Node for this for the next maintenance of the loader; if you have any code to suggest, please post or attach...

-Ken

tmilard
Offline
Joined: 2004-03-25

Yes. I think I almost got it !
Just way a few hours so I can do more test. But it seems to work now.

But it was true : The Phong classe was there ... But not the [b]Lambert[/b].
I send the code after the tests.
Thierry

tmilard
Offline
Joined: 2004-03-25

> I have attached a source zip to a post found at
> http://eclectic3d.net. However, the best way to see
> the loader in action is to try out J3DWorkbench,
> version 3.0...

Hello Ken, I did unzip the file and immort the classes in my java tool.

I do have a few questions if it is possible:

- Question 1) I have a full package named "org.collada.colladaschema" with wird classes that do not compile : Accessor, ....., ..., ..., VisualScene
For example I have this many @XmlElement and this error goes "Anotations are not supported at this langage level.
What can I do to be able to compile ? what should/must I import ?

- Question 2) There is a classe called Collada14Loader (in package org.jdesktop.j3d.loaders.collada).
- Is it the one classe I should use ?
- I suppose the method named load(Url or Reader or file) is the methose that triggers the collada fiel. Right ?

Thanl you again Ken.
I will try to write a "level 0" tutorial for java3D developers that want to use the collada loader, because I think it can be a usefull piece of the java3D plateform.
Thierry

tmilard
Offline
Joined: 2004-03-25

> For example I have this many @XmlElement and this
> error goes "Anotations are not supported at this
> langage level.
> What can I do to be able to compile ?
===> Answer, easy I only had to put my tool to "java1.5 compliant".

puybaret
Offline
Joined: 2004-12-04

Thank you for providing this nice update.
I tried it successfully in Sweet Home 3D with many Collada models. :)

I have some questions:
- under which license are available the classes of this loader (some source files have no header, and some cites a BSD like license) ?
- is there a way to lighten the 2 MB Jar files this loader requires under Java 1.5? Why Jimi is required since JPEG, PNG, GIF and BMP formats are supported by the JDK?

mcneillk
Offline
Joined: 2005-02-03

Hi E,

I have had no answers from the original author before I decided to adopt these files. However, there were placed in the contrib-utils project, so normally, they would inherit the accompanying java3d license...

The original author used JIMI, and I have not had the time to refactor the code in order to remove this dependency, but I have scheduled a big block of time in the coming days to do this maintenance and other improvements (handling of different shading keywords, see earlier posts in this thread), and then check back into contrib-utils.

Stay tuned therefore...

puybaret
Offline
Joined: 2004-12-04

> I have had no answers from the original author before
> I decided to adopt these files. However, there were
> placed in the contrib-utils project, so normally,
> they would inherit the accompanying java3d
> license...

[url=https://j3d-contrib-utils.dev.java.net/]j3d-contrib-utils project[/url] and [url=https://j3d-incubator.dev.java.net/]j3d-incubator project[/url] are available under BSD license, so any file posted in these projects should be available under that license.
Please, update the headers of the source files accordingly, next time you change them...

The only class that uses JIMI is org.jdesktop.j3d.loaders.collada.utils.Collada14LoaderUtils and the readImage of this class tries first to read an image with ImageIO then with JIMI if it failed.
As JIMI supports more image file formats than ImageIO, it may be the reason why...
Therefore, you should check which image file formats Collada is supposed to support.

By the way, you'll probably be able to simplify the first part of the readImage method, because I'm quite sure that:
[code] String str = url.toString();
str = str.substring(0, str.lastIndexOf("/"));
String[] strs = path.split("/");
for (String string : strs) {
if (string.equals("..")) {
str = str.substring(0, str.lastIndexOf("/"));
} else if (string.equals(".")) {

} else {
str += "/" + string;
}
}
URL url = new URL(str);
[/code]

can be replaced by :

[code] URL url = new URL(url, str);
[/code]

mcneillk
Offline
Joined: 2005-02-03

Just a quick note: I have integrated several of the above suggestions, including dealing with 'Lambert' colors, optimized JAXBContext handling, and puybaret's URL suggestion, as well as dropping jimi.jar from the dependencies.

I am updating the .java headers (licensing) and testing, before committing to the contrib-utils section. I will post again when it is done. Thanks to everyone who contributed.

2 things which did NOT make it in include :

'Constant' color handling & Lines handling (provided code was unclear, but I will put this on the menu for the next iteration).

Feel free to comment and test soon...

Ken

Message was edited by: mcneillk

puybaret
Offline
Joined: 2004-12-04

Ken,

Thank you for your contribution :)
I will probably integrate this Collada loader in Sweet Home 3D, as your implementation isn't too heavy.

I was wondering if you could set JAXBContext as a static field...
But reading [url=http://ws.apache.org/jaxme/release-0.3/apidocs/javax/xml/bind/JAXBContext.html] JAXBContext[/url], I discovered that an [url=http://ws.apache.org/jaxme/release-0.3/apidocs/javax/xml/bind/JAXBContext.html#createUnmarshaller()]Unmarshaller instance[/url] is reusable but not reentrant. :(
So if you program Thierry's suggestion, you should at least mention this limitation in the javadoc of the load method.
A nice way to make it reentrant, would be to store JAXBContext instances in a static WeakHashMap with Thread keys (I would love that solution for Sweet Home 3D).

tmilard
Offline
Joined: 2004-03-25

> In case anyone is interested, I have adopted, and started
> to improve and fix the Collada loader ....
> I will work with 'aces' to integrate these changes
> back into the incubator if there is sufficient
> interest...

===> Wonderfull news !
I am more than interested... ;)

I also think a Collada importer is an important thing today for java3d API.
In my application I use a 3DS importer but now the BIG thing over the Internet (google warehouse, 3dvia, ...) is the Collada objects.

I am ready for help.
At least testing help. More if I am able.
Thierry,free-visit.net

yena
Offline
Joined: 2009-03-31

I'm interested too. Is the improved version available somewhere?

mcneillk
Offline
Joined: 2005-02-03

I have finished the first round of code cleaning and a few important bugfixes. So far, I can load just about every Collada file I have found on Google 3D warehouse.

Also, I added some utility methods to inquire about which way is Up (often Z), and a scale factor to apply to get to Java 3D 'normalized' meters.

I will be releasing the improved code with the upcoming major J3DWorkbench release (within 5 days). I will build a collada jar and make in available on sourceforge (http://sourceforge.net/projects/j3dworkbench/).

I would be happy to update the sourcecode in contrib-utils (original author, 'paulby': I would assume that is ok?).

-Ken

tmilard
Offline
Joined: 2004-03-25

Hello "mcneillk" ,
I am ready to try using the Shiva_improved-by-you-collada-loader .

Unfortunatly I can not manage to get a zip with class files or java source.
- Have you put it somewhere ?
- Is there an url with the latest collada importer ?

Thank you,
Thierry

> I have finished the first round of code cleaning and
> a few important bugfixes. So far, I can load just
> about every Collada file I have found on Google 3D
> warehouse.
>
>
> I will be releasing the improved code with the
> upcoming major J3DWorkbench release (within 5 days).
> I will build a collada jar and make in available on
> sourceforge
> (http://sourceforge.net/projects/j3dworkbench/).
>
> I would be happy to update the sourcecode in
> contrib-utils (original author, 'paulby': I would
> assume that is ok?).
>
>
> -Ken

mcneillk
Offline
Joined: 2005-02-03

I have attached a source zip to a post found at http://eclectic3d.net. However, the best way to see the loader in action is to try out J3DWorkbench, version 3.0...

Cheers,

-Ken

tmilard
Offline
Joined: 2004-03-25

Ken, thank you for the url.
I will give you feedback.
Thierry

> I have attached a source zip to a post found at
> http://eclectic3d.net. However, the best way to see
> the loader in action is to try out J3DWorkbench,
> version 3.0...

>
> Cheers,
>
> -Ken

yena
Offline
Joined: 2009-03-31

I've been testing the new loader and it works well, even for large files. However, I have one problem. I have named nodes (components, and in the future possibly other nodes as well), but they never appear in the scene graph. I have checked the Collada file and they appear there. The loader seems to simply ignore this information (named chunk?) instead of updating the name property of the J3D node. I've also tried converting to 3Ds format and importing with Inspector3Ds and Microcrowd 3Ds loader with the same bad result. Would it be possible to add named nodes in Collada loader, or does anyone know of another loader that can handle this?

mcneillk
Offline
Joined: 2005-02-03

I should be able to add this feature in the very near future--perhaps you could send an example file attachment to mail@eclectic3d.net.

BTW, have you tried J3DWorkbench?

Cheers.

yena
Offline
Joined: 2009-03-31

> I should be able to add this feature in the very near
> future--perhaps you could send an example file
> attachment to mail@eclectic3d.net.

That would be great indeed. I've sent an example file by email.

> BTW, have you tried J3DWorkbench?
Yes, I gave it a spin. Looks nice, performs well, and loaded everything I tried it with.

weiland
Offline
Joined: 2005-08-05

I, for one, am interested. Thanks for taking this on. Can we help?

Bill