New WorldProcessor created using 1 thread(s) and granularity of 1!Creating new world processor buffer for thread mainNew WorldProcessor created using 1 thread(s) and granularity of 1!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 17352/4051 vertices in 47ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 22500/5822 vertices in 46ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 23997/5037 vertices in 32ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 24000/5355 vertices in 31ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 6000/1552 vertices in 16ms!Object 12/object14 compiled to 5 subobjects in 391ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 2675 vertex indices!Creating vertex cache (64200 bytes)!Vertex indices will be mapped!Subobject of object 16/submesh0 compiled to indexed data using 11997/11997 vertices in 32ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 2728 vertex indices!Creating vertex cache (65472 bytes)!Vertex indices will be mapped!Subobject of object 16/submesh0 compiled to indexed data using 11196/11196 vertices in 15ms!Object 16/submesh0 compiled to 2 subobjects in 93ms!Creating new world processor buffer for thread mainChecking for triangle strip...Not a triangle strip at position 1!Remapping 2413 vertex indices!Creating vertex cache (57912 bytes)!Vertex indices will be mapped!Subobject of object 17/submesh1 compiled to indexed data using 11997/11997 vertices in 16ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 1879 vertex indices!Creating vertex cache (45096 bytes)!Vertex indices will be mapped!Subobject of object 17/submesh1 compiled to indexed data using 9552/9552 vertices in 16ms!Object 17/submesh1 compiled to 2 subobjects in 110ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 21/object23 compiled to indexed data using 5718/1031 vertices in 0ms!Object 21/object23 compiled to 1 subobjects in 0ms!Additional visibility list (2) created with size: 32000Additional visibility list (3) created with size: 32000VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object23'VBO created for object 'object14'Compiled 6 VBO!Shader compiled!

It's a bit strange that the tangent vector calculation happens after object and shader compilation. Try to move it closer to the actual object creation instead. This looks like as if it happens right before rendering, which might be too late.

New WorldProcessor created using 1 thread(s) and granularity of 1!Creating new world processor buffer for thread mainNew WorldProcessor created using 1 thread(s) and granularity of 1!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 17352/4051 verties in 46ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 22500/5822 verties in 32ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 23997/5037 verties in 32ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 24000/5355 verties in 31ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 12/object14 compiled to indexed data using 6000/1552 vertics in 15ms!Object 12/object14 compiled to 5 subobjects in 343ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 2675 vertex indices!Creating vertex cache (64200 bytes)!Vertex indices will be mapped!Subobject of object 16/submesh0 compiled to indexed data using 11997/11997 vertces in 16ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 2728 vertex indices!Creating vertex cache (65472 bytes)!Vertex indices will be mapped!Subobject of object 16/submesh0 compiled to indexed data using 11196/11196 vertces in 16ms!Object 16/submesh0 compiled to 2 subobjects in 110ms!Creating new world processor buffer for thread mainChecking for triangle strip...Not a triangle strip at position 1!Remapping 2413 vertex indices!Creating vertex cache (57912 bytes)!Vertex indices will be mapped!Subobject of object 17/submesh1 compiled to indexed data using 11997/11997 vertces in 32ms!Checking for triangle strip...Not a triangle strip at position 1!Remapping 1879 vertex indices!Creating vertex cache (45096 bytes)!Vertex indices will be mapped!Subobject of object 17/submesh1 compiled to indexed data using 9552/9552 vertics in 15ms!Object 17/submesh1 compiled to 2 subobjects in 109ms!Checking for triangle strip...Not a triangle strip at position 1!Subobject of object 21/object23 compiled to indexed data using 5718/1031 vertics in 16ms!Object 21/object23 compiled to 1 subobjects in 16ms!Additional visibility list (2) created with size: 32000Additional visibility list (3) created with size: 32000VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object14'VBO created for object 'object23'Compiled 6 VBO!Shader compiled!Visibility lists disposed!Visibility lists disposed!

The tangent vectors are part of the Mesh instance. Any chance that somebody (Bones?) replaces this instance with some other? Can you load the model outside of Bones and see if that works? Apart from that, one actually have to add some stuff to jPCT and Bones to allow proper handling of tangent vectors during an animation. But it may look good enough as it is now, so i would post-pone that step for now.

I'll make a test with Object3D now and report back. But don't you think that normal mapping is important enough to be considered a "standard" part of your engine? There should be a simple helper class for it, in my opinion.

That helper class would be either very limited or very complex, so i decided to leave it to the user for now. If everybody and his dog would be asking for direct support, i would consider it...but that's actually not the case. Only few people are explicitly using shaders and those who do, usually write their own.

I can't test the same model as OBJ, by the way, as the textures don't come out right and the model is exported with a different number of pieces. But can't you just assume I'm not doing anything wrong and that there's a better way to make that shader?

No, because the shader is fine. Just look at the shader in the example that is included in the zip. It should be the same thing line by line and it works fine. The only difference between your former and this one is, that this one takes the tangent vectors as an attribute. And the only problem that i can imagine in this context is that this attribute doesn't get filled correctly...most likely because the data needed for this just isn't there. Please try this jar...it also clones the tangent vectors if a mesh is being cloned. Maybe that will fix the problem: http://jpct.de/download/beta/jpct.jar