Shadernode editor: Cannot load material definition

That’s what I’m getting if I try to start the shadernode editor on a material definition that I worked on just last week.
Editing the file by hand, then saving, takes about four seconds. This was different before, too, I think.

Is this doing some network stuff that fails?
I see that the SDK’s update check fails, too. It tells me I should check my network connection, but that’s fine, I’m not behind a proxy or anything, so I guess the update site is (still) down.

I have no idea what problem the shadernode editor is having.
Maybe it should simply report the exception stack trace until some more extensive error checking can be added?

Meh. And I thought I could finally start real work on the voxel shader… with the shadernode editor being the one real reason why I finally installed the SDK, and now it doesn’t work. Life can be a bitch.

1 Like
@toolforger said: That's what I'm getting if I try to start the shadernode editor on a material definition that I worked on just last week. Editing the file by hand, then saving, takes about four seconds. This was different before, too, I think.

Is this doing some network stuff that fails?
I see that the SDK’s update check fails, too. It tells me I should check my network connection, but that’s fine, I’m not behind a proxy or anything, so I guess the update site is (still) down.

I have no idea what problem the shadernode editor is having.
Maybe it should simply report the exception stack trace until some more extensive error checking can be added?

Meh. And I thought I could finally start real work on the voxel shader… with the shadernode editor being the one real reason why I finally installed the SDK, and now it doesn’t work. Life can be a bitch.


Could you send me the file?
About the hanging when saving, there is a lock issue somewhere. I already got it, but it looks quite random.
I must do something wrong somewhere.
I’m sorry, the shader node editor is still quite unstable.
Thanks for your report nonetheless

1 Like

No problem with instability, that’s why I’m writing bug reports :slight_smile:

BTW the j3sn file loads without a hitch in the application, and I think it worked in the shadernode editor just last week.
I did rename the package and had to rename all references to the file name. I needed several rounds of testing until I got all places corrected. I suspect that an invalid filename is still cached somewhere.

I can’t use my JME machine right now, I’ll post the full sources later today.

BTW after posting I found that the SDK was complaining about some error in OpenGL. I couldn’t copy the full text before the popup closed - does have Netbeans an error log somewhere where such things are recorded? (Eclipse as an “Error Log” view for that, haven’t found the Netbeans equivalent yet.)

1 Like
<cite>@toolforger said:</cite> BTW after posting I found that the SDK was complaining about some error in OpenGL. I couldn't copy the full text before the popup closed - does have Netbeans an error log somewhere where such things are recorded? (Eclipse as an "Error Log" view for that, haven't found the Netbeans equivalent yet.)

It’s under the top menu named “view”->IDE Log

1 Like

Aaahh, got it, thanks.
Unfortunately, the shadernode editor logs nothing there either. @nehon, is there any place where I can find the exception trace? “Cannot load material definition” is simply not enough to find the actual source of error.

Here are the sources.
There are still almost identical to Nehon’s original test case, so I have no idea what might be causing this.
Put all files into the package named in the Java class to try it out.
Since we’re chasing something weird and elusive, so the more outlandish potential trouble spots:

  • Shader file names contain uppercase. Might cause behavioural differences between Windows and Linux machines that might derail the shadernode editor.
  • I routinely add an empty line to files. Not sure whether I modified the shader files in that fashion, but that could cause differences, too.

TestTexture3D.java:
[java]package org.toolforger.experiments.voxelsVia3dTextures;

import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.shape.Sphere;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture3D;
import com.jme3.util.BufferUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;

public class TestTexture3D extends SimpleApplication {

public static void main(String[] args) {
    TestTexture3D app = new TestTexture3D();
    app.start();
}

// FIXME add shader resources
@Override
public void simpleInitApp() {
    //mouseInput.setCursorVisible(true);
    flyCam.setMoveSpeed(10);
    //creating a sphere
    Sphere sphere = new Sphere(32, 32, 1);
    //getting the boundingbox
    sphere.updateBound();
    BoundingBox bb = (BoundingBox) sphere.getBound();
    Vector3f min = bb.getMin(null);
    float[] ext = new float[]{bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2};
    //we need to change the UV coordinates (the sphere is assumet to be inside the 3D image box)
    sphere.clearBuffer(Type.TexCoord);
    VertexBuffer vb = sphere.getBuffer(Type.Position);
    FloatBuffer fb = (FloatBuffer) vb.getData();
    float[] uvCoordinates = BufferUtils.getFloatArray(fb);
    //now transform the coordinates so that they are in the range of &lt;0; 1&gt;
    for (int i = 0; i &lt; uvCoordinates.length; i += 3) {
        uvCoordinates[i] = (uvCoordinates[i] - min.x) / ext[0];
        uvCoordinates[i + 1] = (uvCoordinates[i + 1] - min.y) / ext[1];
        uvCoordinates[i + 2] = (uvCoordinates[i + 2] - min.z) / ext[2];
    }
    //apply new texture coordinates
    VertexBuffer uvCoordsBuffer = new VertexBuffer(Type.TexCoord);
    uvCoordsBuffer.setupData(Usage.Static, 3, com.jme3.scene.VertexBuffer.Format.Float,
            BufferUtils.createFloatBuffer(uvCoordinates));
    sphere.setBuffer(uvCoordsBuffer);
    //create geometry, and apply material and our 3D texture
    Geometry g = new Geometry("sphere", sphere);
    Material material = new Material(assetManager, "org/toolforger/experiments/voxelsVia3dTextures/tex3D.j3md");
    try {
        Texture texture = this.getTexture();
        material.setTexture("Texture", texture);
    } catch (IOException e) {
        e.printStackTrace();
    }
    material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha); ///
    g.setMaterial(material);
    g.setQueueBucket(RenderQueue.Bucket.Transparent); ///
    rootNode.attachChild(g);
    //add some light so that it is visible
    PointLight light = new PointLight();
    light.setColor(ColorRGBA.White);
    light.setPosition(new Vector3f(5, 5, 5));
    light.setRadius(20);
    rootNode.addLight(light);
    light = new PointLight();
    light.setColor(ColorRGBA.White);
    light.setPosition(new Vector3f(-5, -5, -5));
    light.setRadius(20);
    rootNode.addLight(light);
}

/**
 * This method creates a RGB8 texture with the sizes of 10x10x10 pixels.
 */
private Texture getTexture() throws IOException {
    ArrayList&lt;ByteBuffer&gt; data = new ArrayList&lt;ByteBuffer&gt;(1);
    ByteBuffer bb = BufferUtils.createByteBuffer(10 * 10 * 10 * 4);//all data must be inside one buffer

// for (int i = 0; i < 10; ++i) {
// for (int j = 0; j < 10 * 10; ++j) {
// bb.put((byte) (255f * i / 10f));
// bb.put((byte) (255f * j / 10f));
// bb.put((byte) (255f));
// }
// }
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k= 0; k < 10; k++) {
bb.put((byte) (255f * i / 10f));
bb.put((byte) (255f * j / 10f));
bb.put((byte) (255f * k / 10f));
bb.put((byte) 127); ///
}
}
}
bb.rewind();
data.add(bb);
return new Texture3D(new Image(Format.RGBA8, 10, 10, 10, data));
}
}
[/java]

tex3D.j3md:
[java]
MaterialDef My MaterialDef {

MaterialParameters {
    Texture3D Texture
}

Technique {
    VertexShader GLSL100: org/toolforger/experiments/voxelsVia3dTextures/tex3D.vert
    FragmentShader GLSL100: org/toolforger/experiments/voxelsVia3dTextures/tex3D.frag

    WorldParameters {
        WorldViewProjectionMatrix
    }
}

}
[/java]

tex3D.vert:
[java]uniform mat4 g_WorldViewProjectionMatrix;

attribute vec3 inTexCoord;
attribute vec3 inPosition;

varying vec3 texCoord;

void main(){
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition,1.0);
texCoord=inTexCoord;
}
[/java]

tex3D.frag:
[java]uniform sampler3D m_Texture;

varying vec3 texCoord;

void main(){
gl_FragColor= texture3D(m_Texture,texCoord);
}
[/java]

@nehon To trigger the FileAlreadyLockedException, I need to edit the jm3d file, then save it. The save works but the file’s “modified” status is not cleared (the file name remains bold). After that, switching from text editing to shadernode editing do I get a FileAlreadyLockedException. Seems like the save operation or something in its vicinity does not properly unlock the file if something fails.

Is your matdef in the assets folder? It has to be.

No it isn’t.
That might be the reason - I had the test case copied over, then tried to use the shaders inside the shadernode editor.

Is there a reason why the plugin insists on doing that? After all, the resources are inside the package here.
mmm well, it wouldn’t work for an absolute path. j3md files should really offer a way to specify a relative path, it’s quite often that stuff is simply in the same directory, wherever that is.
Now my source tree will have to look like this:
[java]src
assets
MatDefs
test1
someShader.j3md
someShader.vert
someShader.frag
test2
otherShader.j3md
otherShader.vert
otherShader.frag
org
toolforger
test1
Test1.java
test2
Test2.java
[/java]
It’s separating stuff that belongs together all over the place.
I could split out each test into a separate project, but that seems overkill.
(Oh the hierarchy seems wrong, I’m typing this from memory - I hope you get what I mean.)

The assetmanager and all data in jme works with absolute paths. Thats how it is. I guess you can imagine how many implications that means by now :slight_smile:

The ProjectAssetManager can handle data from all over the classpath of the project but it really only allows full r/w access for the assets folder. If you load files from “somewhere” then it might not be possible to get a reference to an assetmanager that has access to this file or it has to instantiate a “dummy” assetmanager which in turn can lead to other problems. The way it works is basically also an implication as mentioned in the first paragraph :wink:

Well, ProjectAssetManager can’t know how the application is going to structure the search path at runtime, so this can’t work too well.

Anyway. Moving the assets to MatDefs helped, in a sense: I’m getting a different exception now.
[java]SEVERE [com.jme3.gde.core.scene.SceneApplication]: Uncaught exception thrown in Thread[AWT-EventQueue-1,6,IDE Main]
java.lang.NullPointerException
at com.jme3.gde.materialdefinition.fileStructure.TechniqueBlock.getShaderNodes(TechniqueBlock.java:178)
at com.jme3.gde.materialdefinition.editor.MatDefEditorlElement.initData(MatDefEditorlElement.java:494)
at com.jme3.gde.materialdefinition.editor.MatDefEditorlElement.initDiagram(MatDefEditorlElement.java:124)
at com.jme3.gde.materialdefinition.editor.MatDefEditorlElement.reload(MatDefEditorlElement.java:579)
at com.jme3.gde.materialdefinition.editor.MatDefEditorlElement.<init>(MatDefEditorlElement.java:105)
Caused: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at org.netbeans.core.spi.multiview.MultiViewFactory$MapMVD.createElement(MultiViewFactory.java:436)
Caused: java.lang.NoSuchMethodException: com.jme3.gde.materialdefinition.editor.MatDefEditorlElement.<init>()
at java.lang.Class.getConstructor0(Class.java:2733)
at java.lang.Class.getConstructor(Class.java:1676)
at org.netbeans.core.spi.multiview.MultiViewFactory$MapMVD.createElement(MultiViewFactory.java:439)
Caused: java.lang.IllegalStateException: Cannot instantiate com.jme3.gde.materialdefinition.editor.MatDefEditorlElement
at org.netbeans.core.spi.multiview.MultiViewFactory$MapMVD.createElement(MultiViewFactory.java:453)
at org.netbeans.core.multiview.MultiViewModel.getElementForDescription(MultiViewModel.java:209)
at org.netbeans.core.multiview.MultiViewModel.getActiveElement(MultiViewModel.java:130)
at org.netbeans.core.multiview.MultiViewModel.getActiveElement(MultiViewModel.java:126)
at org.netbeans.core.multiview.MultiViewPeer.showCurrentElement(MultiViewPeer.java:354)
at org.netbeans.core.multiview.MultiViewPeer.showCurrentElement(MultiViewPeer.java:346)
at org.netbeans.core.multiview.MultiViewPeer$SelectionListener.selectionChanged(MultiViewPeer.java:750)
at org.netbeans.core.multiview.MultiViewModel.fireSelectionChanged(MultiViewModel.java:246)
at org.netbeans.core.multiview.MultiViewModel.setActiveDescription(MultiViewModel.java:118)
at org.netbeans.core.multiview.MultiViewModel$BtnGroup.setSelected(MultiViewModel.java:296)
at javax.swing.JToggleButton$ToggleButtonModel.setSelected(JToggleButton.java:254)
at javax.swing.ButtonGroup.setSelected(ButtonGroup.java:164)
at org.netbeans.core.multiview.MultiViewModel$BtnGroup.setSelected(MultiViewModel.java:292)
at org.netbeans.core.multiview.TabsComponent$ButtonMouseListener.mousePressed(TabsComponent.java:449)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:280)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:279)
at java.awt.Component.processMouseEvent(Component.java:6285)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6053)
at java.awt.Container.processEvent(Container.java:2045)
at java.awt.Component.dispatchEventImpl(Component.java:4649)
at java.awt.Container.dispatchEventImpl(Container.java:2103)
at java.awt.Component.dispatchEvent(Component.java:4475)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4633)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4294)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4227)
at java.awt.Container.dispatchEventImpl(Container.java:2089)
at java.awt.Window.dispatchEventImpl(Window.java:2587)
at java.awt.Component.dispatchEvent(Component.java:4475)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:675)
at java.awt.EventQueue.access$300(EventQueue.java:96)
at java.awt.EventQueue$2.run(EventQueue.java:634)
at java.awt.EventQueue$2.run(EventQueue.java:632)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
at java.awt.EventQueue$3.run(EventQueue.java:648)
at java.awt.EventQueue$3.run(EventQueue.java:646)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:645)
at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:158)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
[catch] at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)

[/java]

@toolforger said: Well, ProjectAssetManager can't know how the application is going to structure the search path at runtime, so this can't work too well.

Sure it can, you configure that in the project settings…? If you didn’t the main jar couldn’t contain the manifest info that references the other jar files. I know this might seem like magic to an Eclipse user :wink:

The plugin can’t know what paths are added while the program runs :stuck_out_tongue:

@toolforger said: The plugin can't know what paths are added while the program runs :-P

But if you can edit the file while you write the app its not something thats generated during runtime and you can (and should) just as well put it in the assets folder or put that folder on the classpath.

Edit: e.g. on iOS you won’t have any filesystem access, your assets.jar is being converted to a binary file that you access via the classpath/assetmanager. And you have to configure that before deployment so the conversion can pick that up properly.

I suspect the real problem I’m having is that the shadernode editor simply chokes on .frag and .vert files, it wants .j3sn files.
Or maybe it chokes on .frag and .vert files being included in a very different fashion than .j3sn.

Funny how nobody noticed that, Yours Truly not being an exception. 8)
I guess that’s going to happen to more people who’re getting hold of classic shader definitions and want to use the shadernode editor, so a warning in the docs and a check in the plugin would probably be in order.