Why cant I texture only 1 box?

I tried adding a simple green texture with white lines to the floor in my scene but It would only show up as a dull green texure with no lines.

Then I tried adding another textured box to see if it would work and they both were textured fine!

If I remove either box though the one left has a dull single color textue. I have no clue as to why this happens or how it can even show a texture w/o the details. :?


Box testbox = new Box("Floor", new Vector3f(), 24f, 1, 24f);
      testbox.setModelBound(new BoundingBox());
      testbox.updateModelBound();
      testbox.setLocalTranslation(new Vector3f(0, 1, 0));
      URL floorLoc2;
        floorLoc2=FoosballTable.class.getClassLoader().getResource("Images/courtfloorTex.png");
      TextureState ts=display.getRenderer().createTextureState();
      
        Texture t2=TextureManager.loadTexture(floorLoc2,Texture.MM_LINEAR,Texture.FM_LINEAR);
        ts.setTexture(t2);
        testbox.setRenderState(ts);
        this.attachChild(testbox);
        //////////////////////////////////////////////////////////////////////////////////////////
        Box floor = new Box("Floor", new Vector3f(), 48f, 1f, 27f);
      floor.getLocalTranslation().y =1;
      floor.setModelBound(new BoundingBox());
      floor.updateModelBound();
        URL floorLoc;
        floorLoc=FoosballTable.class.getClassLoader().getResource("Images/foosballField.png");
       TextureState floorTS=display.getRenderer().createTextureState();
      
        Texture t=TextureManager.loadTexture(floorLoc,Texture.MM_LINEAR,Texture.FM_LINEAR);
        floorTS.setTexture(t);
        floor.setRenderState(floorTS);
        this.attachChild(floor);

maybe you forgot to call updateRenderState() on floor and testbox after setting the new TextureStates?

no, i tried that and still had same issue.

mud2005 said:

no, i tried that and still had same issue.


sure that the files are in the rigt directory ? if you use eclipse refresh your projectdir ?

watch for -> Could not load image...  URL was null <- in your console

no, the textures are there. when I add the second box the textures display correctly. its only when there is one box the texture is wrong, and its not missing just displayed as one dull color.

I can also add the same texture state to another box and have the textures display correctly.

wallR.setRenderState(floorTS);
wallR.updateRenderState();


the problem occurs when I try to apply texture to only one of the boxes in my scene.
mud2005 said:

no, the textures are there. when I add the second box the textures display correctly. its only when there is one box the texture is wrong, and its not missing just displayed as one dull color.
I can also add the same texture state to another box and have the textures display correctly.

wallR.setRenderState(floorTS);
wallR.updateRenderState();


the problem occurs when I try to apply texture to only one of the boxes in my scene.


what ist "this" in your scene ?
try this.updateRenderState(); at last statement

oh yeah, "this" is my court class which extends node.

I add everything to court node then add courtnode to rootnode.

ive tried updating renderstate just after adding texture and ive tried updating the rootnode renderstate after court was added, no change.

I have no idea whats causing this but my first thought was the "updaterenderstate" thing so Ive tried updating the renderstate every way I can and it never does anything. if I dont update the render state at all I still get the same behavior.


the only difference between the above shots is this line

wallR.setRenderState(floorTS);


wallR is the piece in the back. as soon as I add the texturestate to wallR the texture is displayed properly on the floor.
or if I add another texture and texturestate to wallR or any other box then the floor is right. weird behavior. im baffled.

How about an

updateGeometricState

call before the

updateRenderState

call?

How about an
Code:
updateGeometricState
call before the
Code:
updateRenderState
call?

yup, tried that.
made no difference. thanks anyway

I had to post this cause its wacky :slight_smile:

if I comment out these 2 lines I get a font texture somehow.

rootNode.updateGeometricState(0.0f, true);
      rootNode.updateRenderState();


i think it actually looks pretty cool  :wink:

Well you must call updateRenderState() or you get this (the texture for the FPS node will be applied).



So make sure you call updateRenderState() on spatials that you add a TextureState to. So that would be floor.updateRenderState(); after adding the texture state. Not on rootNode, this, that, courtnode or some other box. But though I don't see the code there, I assume you tried that… ?



The fact the font texture shows up seems to suggest you didn't, so if you did, then try telling us if you do anything special with this or rootNode or floor in some part of the code we can't see.


I assume you tried that.. ?

yeah, I was just trying some differnet stuff after I couldnt get it to work

I was messing with shadows and I inadvertanly found the solution to this problem.

It was the line

r.draw(rootNode);



in render method, I removed it and I can now texture 1 box :smiley:

I'm not sure that I understand your solution… aren't you supposed to call draw(rootNode) from the render loop?

If you can write a test to demonstrate this problem I'll look at it. Right now, no matter what I do, I always manage to texture something even if it's just 1 Quad.



import jmetest.effects.cloth.TestCloth;

import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.math.Vector3f;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;

public class TestQuadTex extends SimpleGame {

   
   public static void main(String[] args) {
      SimpleGame sg = new TestQuadTex();
      sg.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
      sg.start();
   }
   
   protected void simpleInitGame() {
      Quad quad = new Quad("test quad", 5, 5);

      TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
      ts.setTexture(
            TextureManager.loadTexture(
            TestCloth.class.getClassLoader().getResource(
            "jmetest/data/images/Monkey.jpg"),
            Texture.MM_LINEAR_LINEAR,
            Texture.FM_LINEAR));
      
      quad.setRenderState(ts);
      quad.setLocalTranslation(new Vector3f(5, 0, 5));
      // different render state doesn't matter.
      // quad.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
      // rootNode.attachChild(new Quad("add a quad before, still works",10,10));      
      rootNode.attachChild(quad);
      // rootNode.attachChild(new Quad("add a quad after, still works",10,10));   
      
   }
}

If you can write a test to demonstrate this problem I'll look at it

I will if I come accross it again its been awhile since I had this issue and I tried to recreate it and couldnt.
Im not sure if this was related but I commented out this line in BasicGameState and it fixed my issues I was having at the time.

DisplaySystem.getDisplaySystem().getRenderer().draw(rootNode);


without the rest of the code this doesnt mean much but its too extensive to post here and im not sure which part was even the problem now.

I was looking into this today and I recreated the problem here is the code:

the problem occurs with this line

r.draw(rootNode);


if I comment it out the texture appears properly, or if I dont comment it out and texture another box they both are textured properly.
otherwise the texture is just pale green.

import java.net.URL;
import java.util.HashMap;
import java.util.logging.Level;

import com.foosball.main.FoosballTable;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.ThirdPersonHandler;
import com.jme.input.joystick.JoystickInput;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.Node;
import com.jme.scene.Text;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.PQTorus;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.WireframeState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.LoggingSystem;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.physics.DynamicPhysicsObject;
import com.jmex.physics.PhysicsObject;
import com.jmex.physics.PhysicsWorld;
import com.jmex.physics.StaticPhysicsObject;

public class TestShadowPass extends BaseGame {
   protected Timer timer;
   protected InputHandler input;
   protected int alphaBits = 0;
   private int width, height, depth, freq;
   protected float tpf;
   protected Camera cam;
   private boolean fullscreen;
   protected Text fps;
   protected boolean showDepth = false;
   protected WireframeState wireState;
   protected BasicPassManager pManager;
   protected LightState lightState;
    /** Depth bits to use for the renderer. */
    protected int depthBits = 8;
    /** Stencil bits to use for the renderer. */
    protected int stencilBits = 0;
    protected StringBuffer updateBuffer = new StringBuffer(30);
    /** This is used to recieve getStatistics calls. */
    protected StringBuffer tempBuffer = new StringBuffer();
    /** Number of samples to use for the multisample buffer. */
    protected int samples = 0;
    protected boolean showBounds = false;
    protected boolean showNormals = false;
   protected Node rootNode;
   protected boolean pause;
    private Node m_character;
    private ChaseCamera chaser;
    Sphere guy;
  
    private static ShadowedRenderPass sPass = new ShadowedRenderPass();
 

    public static void main(String[] args) {
        LoggingSystem.getLogger().setLevel(java.util.logging.Level.WARNING);
        TestShadowPass app = new TestShadowPass();
        app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
        app.start();
    }
   
    TestShadowPass() {
        stencilBits = 4; // we need a minimum stencil buffer at least.
    }
   
    private void setupCharacter() {
        PQTorus b = new PQTorus("torus - target", 2, 3, 2.0f, 1.0f, 64, 12);
    
        guy=new Sphere("ball",16,16,1.55f);
        guy.setModelBound(new BoundingSphere());
        guy.updateModelBound();
       
        guy.setLocalTranslation(new Vector3f(0,10,0));
 
       guy.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   
       guy.updateRenderState();
      
        m_character = new Node("char node");
      
        rootNode.attachChild(guy);
        rootNode.updateGeometricState(0,true);
       
        DynamicPhysicsObject guyObj = new DynamicPhysicsObject(guy, 30);
        PhysicsWorld.getInstance().addObject(guyObj);
    }
   
    private void setupTerrain() {

        Box floor = new Box("box", new Vector3f(), 25, 1, 25);
        floor.setModelBound(new BoundingBox());
        floor.updateModelBound();
        floor.setLocalTranslation(new Vector3f(0,-2,0));
        rootNode.attachChild(floor);
       
        URL floorLoc;
        floorLoc=FoosballTable.class.getClassLoader().getResource("Images/foosballFieldMonkey.png");
       TextureState floorTS=display.getRenderer().createTextureState();
        Texture t=TextureManager.loadTexture(floorLoc,Texture.MM_LINEAR,Texture.FM_LINEAR);
       
        floorTS.setTexture(t);
        floor.updateGeometricState(0,false);
        floor.updateRenderState();
       
        PhysicsObject floorPhysicsObj = new StaticPhysicsObject(floor);
        PhysicsWorld.getInstance().addObject(floorPhysicsObj);
       
       floor.setRenderState(floorTS);
     
       floor.updateRenderState();
      
    }

    private void setupChaseCamera() {
        Vector3f targetOffset = new Vector3f();
        chaser = new ChaseCamera(cam, m_character);
        chaser.getMouseLook().setMinRollOut(150);
        chaser.setMaxDistance(25);
        chaser.setMinDistance(25);
    }

    private void setupInput() {
        HashMap handlerProps = new HashMap();
        handlerProps.put(ThirdPersonHandler.PROP_DOGRADUAL, "true");
        handlerProps.put(ThirdPersonHandler.PROP_TURNSPEED, ""+(.5f * FastMath.PI));
        handlerProps.put(ThirdPersonHandler.PROP_LOCKBACKWARDS, "true");
        handlerProps.put(ThirdPersonHandler.PROP_CAMERAALIGNEDMOVE, "true");
        handlerProps.put(ThirdPersonHandler.PROP_ROTATEONLY, "true");
        input = new ThirdPersonHandler(m_character, cam, handlerProps);
        input.setActionSpeed(100f);
    }

   protected void update(float interpolation) {
      
      timer.update();
    
        tpf = timer.getTimePerFrame();
      
        input.update(tpf);

        PhysicsWorld.getInstance().update(tpf);
       
      chaser.update(tpf);
       
      pManager.updatePasses(tpf);
      
      rootNode.updateGeometricState(tpf, true);

        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_shadows", false)) {
            sPass.setRenderShadows(!sPass.getRenderShadows());
        }
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_pause", false)) {
            pause = !pause;
        }

        /** If toggle_wire is a valid command (via key T), change wirestates. */
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_wire", false)) {
            wireState.setEnabled(!wireState.isEnabled());
            rootNode.updateRenderState();
        }
        /** If toggle_lights is a valid command (via key L), change lightstate. */
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_lights", false)) {
            lightState.setEnabled(!lightState.isEnabled());
            rootNode.updateRenderState();
        }
        /** If toggle_bounds is a valid command (via key B), change bounds. */
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_bounds", false)) {
            showBounds = !showBounds;
        }
        /** If toggle_depth is a valid command (via key F3), change depth. */
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_depth", false)) {
            showDepth = !showDepth;
        }

        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "toggle_normals", false)) {
            showNormals = !showNormals;
        }
        /** If camera_out is a valid command (via key C), show camera location. */
        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "camera_out", false)) {
            System.err.println("Camera at: "
                    + display.getRenderer().getCamera().getLocation());
        }

        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "screen_shot", false)) {
            display.getRenderer().takeScreenShot("SimpleGameScreenShot");
        }

        if (KeyBindingManager.getKeyBindingManager().isValidCommand(
                "parallel_projection", false)) {
            if (cam.isParallelProjection()) {
                cameraPerspective();
            } else {
                cameraParallel();
            }
        }

        if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit",
                false)) {
            finish();
        }

        if (pause)
            return;
      
   }

   protected void render(float interpolation) {
      Renderer r = display.getRenderer();
        /** Reset display's tracking information for number of triangles/vertexes */
        r.clearStatistics();
        /** Clears the previously rendered information. */
        r.clearBuffers();
       
        /////THIS IS LINE THAT CAUSEES TROUBLE//////////////////////////////////////////////////
        r.draw(rootNode);
       
      pManager.renderPasses(r);
      
   }
   protected void cameraParallel() {
        cam.setParallelProjection(true);
        cam.setParallelProjection(true);
        float aspect = (float) display.getWidth() / display.getHeight();
        cam.setFrustum(-100, 1000, -50 * aspect, 50 * aspect, -50, 50);
        cam.update();
    }

   protected void initSystem() {
      
      try {
            display = DisplaySystem.getDisplaySystem(properties.getRenderer());
           
            display.setMinDepthBits(depthBits);
            display.setMinStencilBits(stencilBits);
            display.setMinAlphaBits(alphaBits);
            display.setMinSamples(samples);
            width = properties.getWidth();
          height = properties.getHeight();
          depth = properties.getDepth();
          freq = properties.getFreq();
          fullscreen = properties.getFullscreen();
           
            /** Create a window with the startup box's information. */
            display.createWindow(properties.getWidth(), properties.getHeight(),
                    properties.getDepth(), properties.getFreq(), properties
                            .getFullscreen());
          
            cam = display.getRenderer().createCamera(display.getWidth(),
                    display.getHeight());

        } catch (JmeException e) {
          
            e.printStackTrace();
            System.exit(1);
        }

        display.getRenderer().setBackgroundColor(ColorRGBA.black);

        cameraPerspective();
        Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
        /** Move our camera to a correct place and orientation. */
        cam.setFrame(loc, left, up, dir);
        /** Signal that we've changed our camera's location/frustum. */
        cam.update();
        /** Assign the camera to this renderer. */
        display.getRenderer().setCamera(cam);

        /** Create a basic input controller. */
        FirstPersonHandler firstPersonHandler = new FirstPersonHandler(cam, 50,
                1);
        input = firstPersonHandler;

        /** Get a high resolution timer for FPS updates. */
        timer = Timer.getTimer(properties.getRenderer());

        /** Sets the title of our display. */
        display.setTitle("SimpleGame");
       
        display.getRenderer().enableStatistics(true);

        /** Assign key P to action "toggle_pause". */
        KeyBindingManager.getKeyBindingManager().set("toggle_pause",
                KeyInput.KEY_P);
        /** Assign key T to action "toggle_wire". */
        KeyBindingManager.getKeyBindingManager().set("toggle_wire",
                KeyInput.KEY_T);
        /** Assign key L to action "toggle_lights". */
        KeyBindingManager.getKeyBindingManager().set("toggle_lights",
                KeyInput.KEY_L);
        /** Assign key B to action "toggle_bounds". */
        KeyBindingManager.getKeyBindingManager().set("toggle_bounds",
                KeyInput.KEY_B);
        /** Assign key N to action "toggle_normals". */
        KeyBindingManager.getKeyBindingManager().set("toggle_normals",
                KeyInput.KEY_N);
        /** Assign key C to action "camera_out". */
        KeyBindingManager.getKeyBindingManager().set("camera_out",
                KeyInput.KEY_C);
        KeyBindingManager.getKeyBindingManager().set("screen_shot",
                KeyInput.KEY_F1);
        KeyBindingManager.getKeyBindingManager().set("exit",
                KeyInput.KEY_ESCAPE);
        KeyBindingManager.getKeyBindingManager().set("parallel_projection",
                KeyInput.KEY_F2);
        KeyBindingManager.getKeyBindingManager().set("toggle_depth",
                KeyInput.KEY_F3);
   }

   protected void initGame() {
      pManager = new BasicPassManager();
      
      /** Create rootNode */
        rootNode = new Node("rootNode");

        PhysicsWorld.create();
      PhysicsWorld.getInstance().setUpdateRate(100);
      PhysicsWorld.getInstance().setStepSize(.02f);
      PhysicsWorld.getInstance().setStepFunction(PhysicsWorld.SF_STEP_SIMULATION);

       
        wireState = display.getRenderer().createWireframeState();
        wireState.setEnabled(false);
        rootNode.setRenderState(wireState);
        rootNode.updateRenderState();

        ZBufferState buf = display.getRenderer().createZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.CF_LEQUAL);
        rootNode.setRenderState(buf);
        rootNode.updateRenderState();
       
        DirectionalLight light = new DirectionalLight();
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
        light.setDirection(new Vector3f(1,-1,0));
        light.setShadowCaster(true);
        light.setEnabled(true);

          /** Attach the light to a lightState and the lightState to rootNode. */
        LightState lightState = display.getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.setGlobalAmbient(new ColorRGBA(.2f, .2f, .2f, 1f));
        lightState.attach(light);
        rootNode.setRenderState(lightState);
     
      display.setTitle("jME - Shadow Volume Test : X - enable/disable shadows");

        setupCharacter();
        setupTerrain();
        setupChaseCamera();
        setupInput();
       
        rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
        rootNode.updateRenderState();
       
        /** Assign key X to action "toggle_shadows". */
        KeyBindingManager.getKeyBindingManager().set("toggle_shadows",
                KeyInput.KEY_X);
       
        sPass.add(rootNode);
        sPass.addOccluder(guy);
        sPass.setRenderShadows(true);
        sPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);
        pManager.add(sPass);
      
   }
   protected void cameraPerspective() {
        cam.setFrustumPerspective(45.0f, (float) display.getWidth()
                / (float) display.getHeight(), 1, 1000);
        cam.setParallelProjection(false);
        cam.update();
    }
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
      
   }

   protected void cleanup() {
      LoggingSystem.getLogger().log(Level.INFO, "Cleaning up resources.");
      
        KeyInput.destroyIfInitalized();
        MouseInput.destroyIfInitalized();
        JoystickInput.destroyIfInitalized();
      
   }
}


this is the image

Ah yes…

rootNode is already being drawn because you use the pass system (and it's added to a pass). And as I understand it you didn't do this call yourself but BasicGameState (which I guess should be called SimpleGameState then) did this?



Doesn't mean it should go wrong per se (I'll look at what happens exactly) but at least that explains it… thirstynellan, are you doing something similiar?