[Contribution] Camera and CameraNode

I everyone!



I've just made a small update of CameraNode class.

Currently, CameraNode don't take camera current position and direction in constructor and "setCamera" method, which make problems (in my case…)



Here the new CameraNode object:



/*
 * Copyright (c) 2003-2006 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jme.scene;

import java.io.IOException;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;

/**
 * <code>CameraNode</code> defines a node that contains a camera object. This
 * allows a camera to be controlled by any other node, and allows the camera to
 * be attached to any node. A call to <code>updateWorldData</code> will adjust
 * the camera's frame by the world translation and the world rotation. The
 * column 0 of the world rotation matrix is used for the camera left vector,
 * column 1 is used for the camera up vector, column 2 is used for the camera
 * direction vector.
 *
 * @author Mark Powell
 * @version $Id: CameraNode.java,v 1.8 2006/05/11 19:39:19 nca Exp $
 */
public class CameraNode extends Node {
   private static final long serialVersionUID = 1L;

   private Camera camera;

   
    public CameraNode() {}
   
    /**
     * >> ADDITION HERE <<
     * Update object position and rotation by camera location/rotation when new camera object is set.
     * @author Yacine Petitprez
     */
    private void updateLocationAndRotation() {
       Quaternion rotation = new Quaternion();
       rotation.fromAxes(camera.getLeft(), camera.getUp(), camera.getDirection());
       
       Vector3f translation = camera.getLocation();
   
       setLocalRotation(rotation);       
       setLocalTranslation(translation);
    }
   
    /**
    * Constructor instantiates a new <code>CameraNode</code> object setting
    * the camera to use for the frame reference.
    *
    * @param name
    *            the name of the scene element. This is required for
    *            identification and comparision purposes.
    * @param camera
    *            the camera this node controls.
    */
   public CameraNode(String name, Camera camera) {
      super(name);
      this.camera = camera;
      
      updateLocationAndRotation();
   }

   /**
    *
    * <code>setCamera</code> sets the camera that this node controls.
    *
    * @param camera
    *            the camera that this node controls.
    */
   public void setCamera(Camera camera) {
      this.camera = camera;
      
      updateLocationAndRotation();
   }

   /**
    *
    * <code>getCamera</code> retrieves the camera object that this node
    * controls.
    *
    * @return the camera this node controls.
    */
   public Camera getCamera() {
      return camera;
   }

   /**
    * <code>updateWorldData</code> updates the rotation and translation of
    * this node, and sets the camera's frame buffer to reflect the current
    * view.
    *
    * @param time
    *            the time between frames.
    */
   public void updateWorldData(float time) {
      super.updateWorldData(time);
      if (camera != null) {
         camera.setFrame(worldTranslation, worldRotation);
      }
   }
   
    public void write(JMEExporter e) throws IOException {
        super.write(e);
        OutputCapsule capsule = e.getCapsule(this);
        capsule.write(camera, "camera", null);
       
    }

    public void read(JMEImporter e) throws IOException {
        super.read(e);
        InputCapsule capsule = e.getCapsule(this);
        camera = (Camera)capsule.readSavable("camera", null);
       
    }
}



I hope this will be usefull!

It would be more useful as a patch/diff :slight_smile:

But i don't know how work CVS and contributions with JMonkey :// (I thinked only members can make patchs!)

anykeyh said:

I thinked only members can make patchs!

No, everyone can :) - e.g. in eclipse choose Team->Create Patch from the context menu

In linux type in a terminal:

diff oldCameraNode.java newCameraNode.java > CameraNode.patch



In windows:

a) Download diff for windows. Not recommended, since it doesn't work that well.

b) download and install cygwin. Excecute the command above.

c) download and install Linux. Recommended. Watch movie on YouTube about Compiz Fusion. Install Compiz Fusion. Look at that nice screen telling your graphics card isn't supported. Buy new graphics card. If you took Ubuntu, reinstall Ubuntu. If you took openSuSE, start with parameter "init 3", login as root, and type "sax2", after that type "init 5". Reinstall Compiz Fusion. Spin the cube. Open terminal. Make terminal transparent by default. Type command in terminal.

o_O

SeySayux said:
Buy new graphics card. If you took Ubuntu, reinstall Ubuntu.

if you have to reinstall ubuntu just because can't start X (an ati card problm since all nvidia cards use the very same settings) you should look twice

just log on, switch to root and dpkg-reconfigure xserver-xorg ( or xserver-xfree86 if you are running a really old linux)
then /etc/init.d/kdm (or gdm) restart

and you're done, you dont even have to reboot

Why couldn't you have told me that a few days earlier?!?



BTW it was SiS -> nVidia. So this dpkg thingy is something like ncurses yast, right?

SeySayux said:

Why couldn't you have told me that a few days earlier?!?

didn't know you needed help!  :P
most of the problems can be fixed withot reinstalling, the question is if the fix is going to take you long than reinstalling and reconfiguring the whole system
anyway, if you are happy with opensuse, stay with it!

SeySayux said:

BTW it was SiS -> nVidia. So this dpkg thingy is something like ncurses yast, right?

I have an old (like very old) laptop with an old 16M sis, i havent even tried to get hw acceleration on it, runs scummvm and i'm not going to ask for more :lol:

ncurses yasts is more like aptitude without args, dpkg is a command-line only tool to install and manage debian packages, it's used by all these apt, aptitude, synaptic, adept stuff

everybody should try to install an old debian release (woody or so) once in his life, you learn (and suffer) a lot  :roll:

and... we just hijacked the thread!  :D

YaST does a lot more as installing packages ;). Aptitude is only to install packages, afaik. Ahhh good old times with Debian and Aptitude… "This aptitude has super cow powers". Getting angry because I couldn't get a bigger resolution as 640x480… Ahh… Now I've got openSuSE, and it configures itself. No more messing in my Xorg.conf file…



One thing I remember about Debian: Not for Linux noobs (well it was the very first distro that I installed… if I knew about openSuSE, I wouldn't even tried installing it.)

To be fair many distributions have come a long way since the days of forcing you to edit your own xorg.conf files.  Both Ubuntu and Fedora have features to help out.  SuSE is a nice flavor, but if you're going to spout propaganda you should at least look at the latest versions of the other flavors so you don't look foolish. :wink:

To be back to the root of this topic:

Ok I'll make a patch this evening (at Paris time), and another for LensFlare class also :wink: (intensity modulation doesn't work correctly  )



Thanks a lot for JMe, the best engine I used (ok ok I use only it… :stuck_out_tongue: )

Eclipse seems have issues sometimes with patches submitted into the forum so you might want to reference an external file patch.

darkfrog said:

To be fair many distributions have come a long way since the days of forcing you to edit your own xorg.conf files.  Both Ubuntu and Fedora have features to help out.  SuSE is a nice flavor, but if you're going to spout propaganda you should at least look at the latest versions of the other flavors so you don't look foolish. ;)


I knew how to reconfigure the driver because it was on the nVidia driver page in the wiki. it told me: "init 3, sax2, init 5". While the Ubuntu wiki just said "open the restricted driver management (gnome only), click the driver you wish to install, restart X". So obviously if you don't have Gnome at hand, you don't know anything about dpkg-reconfigure's  ;).
I personally think Ubuntu is a very good distro, only thing is that it's KDE counterpart, Kubuntu, always seems to be a release behind. I need KDE because of it's kioslaves (especially the fish slave to get my files on the server). Yes, I could go search for another fish client, but that still doesn't offer me all the other kioslaves. And KDE was just the very first DE I tried.

You should probably create a new topic if you want to continue this discussion SeySayux. :o

Here the patch for camera node:


### Eclipse Workspace Patch 1.0
#P jme
Index: src/com/jme/scene/CameraNode.java
===================================================================
RCS file: /cvs/jme/src/com/jme/scene/CameraNode.java,v
retrieving revision 1.8
diff -u -r1.8 CameraNode.java
--- src/com/jme/scene/CameraNode.java   11 May 2006 19:39:19 -0000   1.8
+++ src/com/jme/scene/CameraNode.java   31 Aug 2007 17:11:22 -0000
@@ -34,6 +34,8 @@
 
 import java.io.IOException;
 
+import com.jme.math.Quaternion;
+import com.jme.math.Vector3f;
 import com.jme.renderer.Camera;
 import com.jme.util.export.InputCapsule;
 import com.jme.util.export.JMEExporter;
@@ -59,7 +61,23 @@
 
    
     public CameraNode() {}
-   /**
+   
+    /**
+     * >> ADDITION HERE <<
+     * Update object position and rotation by camera location/rotation when new camera object is set.
+     * @author Yacine Petitprez
+     */
+    private void updateLocationAndRotation() {
+       Quaternion rotation = new Quaternion();
+       rotation.fromAxes(camera.getLeft(), camera.getUp(), camera.getDirection());
+       
+       Vector3f translation = camera.getLocation();
+       
+       setLocalRotation(rotation);       
+       setLocalTranslation(translation);
+    }
+   
+    /**
     * Constructor instantiates a new <code>CameraNode</code> object setting
     * the camera to use for the frame reference.
     *
@@ -72,6 +90,8 @@
    public CameraNode(String name, Camera camera) {
       super(name);
       this.camera = camera;
+      
+      updateLocationAndRotation();
    }
 
    /**
@@ -83,6 +103,8 @@
     */
    public void setCamera(Camera camera) {
       this.camera = camera;
+      
+      updateLocationAndRotation();
    }
 
    /**



And here the patch for LensFlare ( launch TestLensFlare to see the difference! ;) )

### Eclipse Workspace Patch 1.0
#P jme
Index: src/com/jmex/effects/LensFlare.java
===================================================================
RCS file: /cvs/jme/src/com/jmex/effects/LensFlare.java,v
retrieving revision 1.14
diff -u -r1.14 LensFlare.java
--- src/com/jmex/effects/LensFlare.java   21 Jun 2006 20:33:08 -0000   1.14
+++ src/com/jmex/effects/LensFlare.java   31 Aug 2007 17:18:08 -0000
@@ -246,18 +246,20 @@
             this.setIntensity(1);
             occludingTriMeshes.clear();
             for (int i = pickBoundsGeoms.size() - 1; i >= 0; i--) {
-                GeomBatch mesh = pickBoundsGeoms.get(i);
-                if (!mesh.getParentGeom().getWorldTranslation().equals(
-                        this.getWorldTranslation())
-                        && !((mesh.getParentGeom().getParent().getType() & SceneElement.SKY_BOX) != 0)
-                        && mesh.getRenderQueueMode() != Renderer.QUEUE_TRANSPARENT) {
-                    if ((mesh.getType() & SceneElement.TRIMESH) != 0) {
-                        occludingTriMeshes.add(mesh);
-                    } else {
-                        this.setIntensity(0);
-                        break;
-                    }
-                }
+               GeomBatch mesh = pickBoundsGeoms.get(i);
+               if (!mesh.getParentGeom().getWorldTranslation().equals(             //@patched: condition (anykeyh)
+                     this.getWorldTranslation())
+                     && ((mesh.getParentGeom().getParent().getType() & SceneElement.SKY_BOX) == 0)
+                     && mesh.getRenderQueueMode() != Renderer.QUEUE_TRANSPARENT) {
+
+                  if ((mesh.getType() & SceneElement.TRIMESH) == 0) {
+                     occludingTriMeshes.add(mesh);
+                  } else {
+                     this.setIntensity(0);
+                     break;
+                  }
+               }
+
             }
             if (occludingTriMeshes.size() > 0 && getIntensity() > 0) {
                 checkRealOcclusion();
@@ -296,7 +298,7 @@
         flaresWorldAxis.subtractLocal(pickRay.origin).normalizeLocal()
                 .multLocal(0.01f);
 
-        final int radius = 25;
+        final int radius = 15;
         secondRay.origin.set(flaresWorldAxis).multLocal(-radius).addLocal(
                 pickRay.origin);
         maxNotOccludedOffset = -radius;
@@ -315,7 +317,7 @@
         }
 
         setIntensity(Math.abs(maxNotOccludedOffset - minNotOccludedOffset)
-                / (radius >> 1));
+                / (radius));
         // flarePoint.addLocal( flarePoint.normalize().multLocal(
         // (maxNotOccludedOffset+minNotOccludedOffset) ) );
     }

There is any patches repository in the jME project? Or I have to use the 2 attached the previous post?

After they have been eval'd they will be applied and the classes updated in cvs.

The intensity looks nicer.  Thanks. 



In CameraNode I disagree with setCamera->auto applying transforms…  There is a good chance you may have your node where you want it and you want some camera to be updated to the new location (imagine multiple security camera nodes that you move the camera control around with setCamera.)  In such a case you would not want transforms auto applied.    That said, I'll expose a new updateFromCamera() that can be called as needed.  You should see these changes in CVS shortly.