Hi John,

   We can reproduce this and bug ID 4401315 is filed for
investigation. In the meantime, please workaround this by
using two Appearance nodes as shown in the attachment.

Thanks for your bug report.

- Kelvin
----------------
Java 3D Team
Sun Microsystems Inc.


>X-Unix-From: [EMAIL PROTECTED]  Sat Dec 23 15:47:25 2000
>MIME-Version: 1.0
>X-Priority: 3
>X-MSMail-Priority: Normal
>X-MimeOLE: Produced By Microsoft MimeOLE V5.00.3018.1300
>Date: Sat, 23 Dec 2000 18:57:43 -0500
>From: John Owen <[EMAIL PROTECTED]>
>Subject: Re: [JAVA3D] Immediate Mode Appearance Question/Problem
>To: [EMAIL PROTECTED]
>
>
>I "fixed" this problem by inserting a GraphicsContext3D.flush(true) statement
between the rendering of each sphere (graphics.flush(false) does not work). This
eats into the frame rate but produces the correct results.
>
>So it seems like GraphicsContext3D.setAppearance() is not making a copy of my
appearance object but is instead holding onto a reference. Does anybody know if
this is by (ouch) design?
>
>If so it leaves you leaves you with 2 pretty grim alternatives, call
GraphicsContext3D.flush(true) before each call to
GraphicsContext3D.setAppearance() and pay a performance cost since your app is
going to block, or be forced into allocating a new appearance object before each
call to GraphicsContext3D.setAppearance().
>
>Please tell me this is a bug, thanks,
>
>- John
>  ----- Original Message -----
>  From: John Owen
>  To: [EMAIL PROTECTED]
>  Sent: Saturday, December 23, 2000 6:13 PM
>  Subject: [JAVA3D] Immediate Mode Appearance Question/Problem
>
>
>  Hi:
>
>  I have a pure immediate mode application which draws a textured sphere. It
works fine.
>
>  I modified the application so that it draws 2 spheres. It does this by using
a single appearance object and setting the appearance's texture to  texture1
when I draw sphere1 and to texture2 when I draw sphere2. It doesn't work. It
always draws both spheres with the same texture, texture2 (actually it is kind
of funny, every few frames I can see the correct texture "flash" onto sphere1
and then it is drawn over with sphere2's texture).
>
>  If I use two different appearance objects, one for each sphere, the
application works correctly. Why is this? Shouldn't I be able to change
appearance attributes on the fly, call GraphicsContext3D.setAppearance() and
expect the changes to take effect?
>
>  Thanks,
>
>  John
>
>  pseudo code looks like this:
>
>  Appearance appearance;
>  Geometry sphere1;
>  Geometry sphere2;
>  Texture2D texture1;
>  Texture2D texture2;
>  Canvas3D canvas;
>  GraphicsContext3D graphics;
>
>  .....
>  void draw() {
>      graphics.clear();
>      appearance.setTexture(texture1);
>      graphics.setAppearance(appearance);
>      graphics.draw(sphere1);
>      appearance.setTexture(texture2);
>      graphics.setAppearance(appearance);
>      graphics.draw(sphere2);
>      canvas.swap();
>  }
>
/*
 *      %Z%%M% %I% %E% %U%
 *
 * Copyright (c) 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;


/**
 * Pure immediate mode example program.  In pure immediate mode, the
 * renderer must be stopped on the Canvas being rendered into. In our
 * example, this is done immediately after the canvas is created. A
 * separate thread is started up to do the immediate mode rendering.
 */
public class PureImmediate extends Applet implements Runnable {

    private Canvas3D canvas;
    private GraphicsContext3D gc = null;
    private Box box1, box2;
    private Transform3D cmt = new Transform3D();

    // One rotation (2*PI radians) every 6 seconds
    private Alpha rotAlpha = new Alpha(-1, 6000);

    private SimpleUniverse u = null;
    private Appearance appearance1 = new Appearance();
    private Appearance appearance2 = new Appearance();
    private Texture texture1, texture2;

    //
    // Renders a single frame by clearing the canvas, drawing the
    // geometry, and swapping the draw and display buffer.
    //
    public void render() {
        if (gc == null) {
            // Set up Graphics context
            gc = canvas.getGraphicsContext3D();
            gc.setAppearance(new Appearance());

            // Set up geometry
            box1 = new Box(0.4f, 0.4f, 0.4f,
                           Box.GENERATE_TEXTURE_COORDS, appearance1);
            box2 = new Box(0.4f, 0.4f, 0.4f,
                           Box.GENERATE_TEXTURE_COORDS, appearance2);
            /* Bug 4401315
            box2 = new Box(0.4f, 0.4f, 0.4f,
                           Box.GENERATE_TEXTURE_COORDS, appearance1);
            */
            texture1 = new TextureLoader("stone.jpg", this).getTexture();
            texture2 = new TextureLoader("earth.jpg", this).getTexture();
        }




        // Render the geometry for this frame
        gc.clear();
        cmt.set(new Vector3d(-0.5, 0, 0));
        gc.setModelTransform(cmt);

        appearance1.setTexture(texture1);
        gc.setAppearance(appearance1);
        gc.draw(box1.getShape(Box.FRONT));

        cmt.set(new Vector3d(0.5, 0, 0));
        gc.setModelTransform(cmt);
        appearance2.setTexture(texture2);
        gc.setAppearance(appearance2);

        /* Bug 4401315
           appearance1.setTexture(texture2);
           gc.setAppearance(appearance1);
        */
        gc.draw(box2.getShape(Box.FRONT));
        canvas.swap();
    }


    //
    // Run method for our immediate mode rendering thread.
    //
    public void run() {
        System.out.println("PureImmediate.run: starting main loop");
        while (true) {
            render();
            Thread.yield();
        }
    }


    public PureImmediate() {
    }

    //
    // init: create the canvas, stop the renderer,
    // create the universe, and start the drawing thread.
    //
    public void init() {
        setLayout(new BorderLayout());
        GraphicsConfiguration config =
           SimpleUniverse.getPreferredConfiguration();

        canvas = new Canvas3D(config);
        canvas.stopRenderer();
        add("Center", canvas);

        // Create the universe and viewing branch
        u = new SimpleUniverse(canvas);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();

        // Start a new thread that will continuously render
        new Thread(this).start();
    }

    public void destroy() {
        u.removeAllLocales();
    }

    //
    // The following allows PureImmediate to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
        new MainFrame(new PureImmediate(), 256, 256);
    }
}

Reply via email to