Uniform Vector4f ClassCastException

Could you tell my why my application throws ClassCastException (com.jme3.math.Vector4f ) - Android 2.3 (HTC Desire Z). It works correctly on a computer. I can change Vector4 to Vector3 but I’d like to know how to solved it.

E/AndroidHarness(17777): Exception thrown in Thread[GLThread 10,5,main] E/AndroidHarness(17777): java.lang.ClassCastException: com.jme3.math.Vector4f E/AndroidHarness(17777): at com.jme3.renderer.android.OGLESShaderRenderer.updateUniform(OGLESShaderRenderer.java:657) E/AndroidHarness(17777): at com.jme3.renderer.android.OGLESShaderRenderer.updateShaderUniforms(OGLESShaderRenderer.java:709) E/AndroidHarness(17777): at com.jme3.renderer.android.OGLESShaderRenderer.setShader(OGLESShaderRenderer.java:890) E/AndroidHarness(17777): at com.jme3.material.Material.render(Material.java:1058) E/AndroidHarness(17777): at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:525) E/AndroidHarness(17777): at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:301) E/AndroidHarness(17777): at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:353) E/AndroidHarness(17777): at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:765) E/AndroidHarness(17777): at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:721) E/AndroidHarness(17777): at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:985) E/AndroidHarness(17777): at com.jme3.renderer.RenderManager.render(RenderManager.java:1031) E/AndroidHarness(17777): at com.jme3.app.SimpleApplication.update(SimpleApplication.java:251) E/AndroidHarness(17777): at com.jme3.app.AndroidHarness.update(AndroidHarness.java:485) E/AndroidHarness(17777): at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:332) E/AndroidHarness(17777): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363) E/AndroidHarness(17777): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)
Main.java [java] public void simpleInitApp() { Box b = new Box(Vector3f.ZERO, 1, 1, 1); Geometry geom = new Geometry("Box", b);
    Material mat = new Material(assetManager, "Materials/Phong.j3md");
    Vector3f lightPositon = new Vector3f(0, 2.0f, 0.0f);
    Vector4f ambient = new Vector4f(0.3f, 0.3f, 0.3f, 0.0f);
    Vector4f diffuse = new Vector4f(0.0f, 200.0f, 0.0f, 0.0f);
    Vector4f specular = new Vector4f(200.0f, 200.0f, 200.0f, 0.0f);
    mat.setVector3("LightPosition", lightPositon);
     mat.setVector4("AmbientColor", ambient);
     mat.setVector4("DiffuseColor", diffuse);
     mat.setVector4("SpecularColor", specular);

    geom.setMaterial(mat);

    rootNode.attachChild(geom);
}

[/java]
Phong.j3md
[java]
MaterialDef My MaterialDef {
MaterialParameters {
Vector3 LightPosition;
Vector4 DiffuseColor;
Vector4 SpecularColor;
Vector4 AmbientColor;
}

Technique {
    VertexShader GLSL100:   Shaders/Phong.vert
    FragmentShader GLSL100: Shaders/Phong.frag

    WorldParameters {
        WorldViewProjectionMatrix
        WorldViewMatrix;
        NormalMatrix;
    }
}

}
[/java]
Phong.vert
[java]
uniform mat4 g_WorldViewMatrix;
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat3 g_NormalMatrix;
uniform vec3 m_LightPosition;

attribute vec4 inPosition;
attribute vec3 inNormal;

varying vec3 normal;
varying vec3 lightDir;
void main() {
normal = g_NormalMatrix * inNormal;
vec4 position4 = g_WorldViewMatrix * inPosition;
vec3 position3 = position4.xyz / position4.w;
lightDir = normalize(m_LightPosition - position3);
gl_Position = g_WorldViewProjectionMatrix * inPosition;
}
[/java] [java]
uniform vec4 m_DiffuseColor;
uniform vec4 m_SpecularColor;
uniform vec4 m_AmbientColor;

varying vec3 normal;
varying vec3 lightDir;
void main() {
float diff = max(0.0, dot(normal, lightDir));
vec4 color = m_AmbientColor;
color += diff * m_DiffuseColor;
vec3 ref = normalize(reflect(-lightDir, normal));
float spec = max(0.0, dot(normal, ref));
if(diff != 0.0){
float buf = pow(spec, 128.0);
color.rgb += vec3(buf, buf, buf);
}
gl_FragColor = color;
}
[/java]

1 Like

Looks like an unreported change to the OGLESShaderRender when Vector4f were added to the core.
I committed a fix in last SVN.

If you are using RC2, the workaround is to use ColorRGBA or Quaternion.
You should se ColorRGBA and Color in your material def (it will map to vec4 in your shader), it seems more suited to your use anyway.

Thanks for reporting this

thx. I didn’t notice setColor function.

I’ve got another question: It is possible to use array of uniforms?

Yes, you can see all supported types in this class
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/shader/VarType.java

Some of them aren’t supported i. e. Matrix3Array

btw… Compiling shaders on Android is frustrating. jME say only: compile error. Is it possible to check what exactly is wrong?
I’m looking for an error in this code. On computer it works.
[java]

uniform vec4 m_DiffuseColor;
uniform vec4 m_SpecularColor;
uniform vec4 m_AmbientColor;
uniform float m_InnerSpot;
uniform float m_OuterSpot;
uniform float m_SpecularExp;

uniform sampler2D m_Texture0;

varying vec3 normalMV;
varying vec3 lightPosMVs[2];
varying vec3 lightDirMVs[2];
varying vec2 texCoordsMV;
varying vec4 eyeMV;

void calculateLight(in vec3 lightPosMV, in vec3 lightDirMV, in vec3 normalN, in vec3 eyeN, inout vec4 color){
vec3 lightPosN = normalize(lightPosMV);
vec3 lightDirN = normalize(lightDirMV);
float diff = dot(normalN, lightPosN);

if(diff >= 0.0){
    
    float spot = dot(-lightPosN, lightDirN);
    
    if(spot > m_OuterSpot){

        float fuzzySpotSize = m_InnerSpot - m_OuterSpot;
        float fuzzySpot = spot - m_OuterSpot;
        float trueSpot = clamp(fuzzySpot / fuzzySpotSize, 0.0, 1.0);
        //color = vec3(trueSpot, trueSpot, trueSpot);
        
        color += diff * m_DiffuseColor * trueSpot;

        vec3 ref = normalize(reflect(-lightPosN, normalN));
        float spec = max(0.0, dot(eyeN, ref));
        
        float buf = pow(spec, 64.0);
        color +=  m_SpecularColor * vec4(buf, buf, buf, 0.0);
        
    }
}

}
void main() {
vec4 color = m_AmbientColor;
vec4 eyeN = normalize(eyeMV);
vec3 normalN = normalize(normalMV);
for(int i = 0; i < 2; i++){
calculateLight(lightPosMVs[i], lightDirMVs[i], normalN, eyeN, color);
}

gl_FragColor =  texture2D(m_Texture0, texCoordsMV) *color;

}
[/java]

Don’t you have a trace in the adb log with shader source and error line?
I can’t see any issue with the shader.
Make sure you have no implicit int to float conversion. Maybe check opengles 2.0 spec to check if you didn’t use unsupported functions or things like that.

Also Android doesn’t like branching a lot. I mean it support it, it’s not your issue, but it’s gonna be slow.
Not sure your for loop won’t be inlined, since you have a constant array length, but since you have only 2 lights I would inline it my self to be sure.

I’ll look in to the matrix3Array issue.