Clip or Cull - well i dont know

Hi



Following my usual pattern of adding things at the last moment, need to add walls to my rooms ( yes, currently the rooms in my game are just floors)



The intention is that walls can be decorated with objects like cupboards and mirrors.



When looking into a room, the camera will be outside of the room, the issue is the wall obscures vision into the room.



What do i make the wall ??. Presumably each wall is a node ( the camera can be turned 360 degree around the room ). Then each object like a cupboard or a mirror can be added to that node.



Whats the best approach, should i try and manually cull the wall, or should i clip it.

One consideration is that the user can spin the camera around and depending on the angle of the camera to the room, then the wall will be visible.



Have looked at the clipping demo


clipState.setEnableClipPlane(ClipState.CLIP_PLANE0, true);
clipState.setClipPlaneEquation(0, 0.5f, 0.5f, 0,0);



presumably i can calculate the camera andgle and just enable, disable the clipstate. Is this efficient ??

If i cull, whats the best way, given that the whole wall node and all children of that node will need to be removed ??

if the walls were just simple quads setup like the jme Box, then cull frontfacing would do it…but if the wall is something bigger and better looking, like a Node like you said with stuff under it, I would do something similar to the cullstate…one way would be to setup an imaginary normal that rotates with the wall and points inwards in the room, then just test cameraDirection.dot(normal), if it's bigger than zero, draw the wallnode, if it's less or equal, don't draw it…

Hey, top suggestion



Delving into it - the Wall Node is now a class extending node, im overiding

public void draw(Renderer r)

of Node to check if the quad ( the basic wall ) is culled by the normals direction to the camera, if so dont draw the node.



Came across the method onDraw on spatial - looks like there is some superflous code in there



Here is the method


 public void onDraw(Renderer r) {

Well, spatial on draw seems to work like this - should this ( minus the commenting out ) be committed



public void onDraw(Renderer r) {

camera.contains changes the planeState…

Edit - have deleted a load of ramble





My vector maths is letting me down



Have attached a line to the wall node. The points of the line are v1{0,0,0} and v2{0,1,0}.

the line.magnitude is v1 + v2

the line.direction is magnitude.normalise.



The camera is in world space

do i need to translate v1 and v2 to world space before testing camera.getDirection().dot(line.direction)



if so, what is the maths to translate a local space point into a world space point.





I guess i could do away with line altogether and just have 2 points







The line is next to the sphere








i was just wondering: is this a GUI thread?  :smiley:

Nope - but i misposted, was meant for general but i missed - DOH



If mojo wants to move it then for the better

Yay - Thanks Mr Coder - finally got through chapter 1 of basic pythagorus meets world space



Vector3f point1 = new Vector3f();
localToWorld(new Vector3f(0,1,0),point1);
      
Vector3f point2 = new Vector3f();
localToWorld(new Vector3f(0,5,0),point2);
Vector3f magnitude = point1.add(point2);
      
Vector3f dir = magnitude.normalize();      
      
directionToCameraDiff =  r.getCamera().getDirection().dot(dir);
      
if(directionToCameraDiff > -0.2f) {
    super.draw(r);
}




And now for the complete optimised class



5 points for anyone that can optimise it further




import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;

public class WallNode extends Node{
   
   WallQuad quad;
   Vector3f point1 = new Vector3f();
   Vector3f point2 = new Vector3f();
   
   Vector3f dir = null;
   
   private float directionToCameraDiff;
   
   public WallNode(String name) {   
      super(name);
   }
   
   public void draw(Renderer r) {      
      if(dir == null) {
         localToWorld(new Vector3f(0,1,0),point1);
         localToWorld(new Vector3f(0,5,0),point2);
         
         Vector3f magnitude = point1.add(point2);
         dir = magnitude.normalize();   
      }
      directionToCameraDiff =  r.getCamera().getDirection().dot(dir);
      
      if(directionToCameraDiff > -0.5f) {
         super.draw(r);
      }
   }
}

  1. the direction vector between two points p1 and p2 is p2-p1 (p1-p2 points from p2 to p1). not add.
  2. since you are only interested in the normal vector of the wall, one vector3f would be enough. just rotate it by doing getWorldRotation().mult(normalVector)
  3. if you only care about if the normalvector is pointing away from the camera direction, you don't have to normalize since normalization only changes the length of the vector and not the direction (unfortunately you have to check against a value since the perspective projection makes this code brake when the object is not centered on the screen)
  4. if you use only one vector that you only rotate, you don't have to normalize it either since it will allways be of the initialized length(preferably length 1)
  5. if you want to i could whip up an example that handles the perspective as well

Respect to Mr Coder



Points 1 - 4 ( back to learning for me, thats 20 points to you)



point 5, would be very grateful to see how you would do it, theres much for me ( and hopefully others ) to learn from it.





Im in the process of making a webstart for this, this code will act as a benchmark/troubleshooter for users if they get problems running the full game ( when its released ).


Ok, a webstart is here



http://www.forthestars.com/site/play.html



If it doesnt work on Mac or Linux, please let me know

following on from youre points 1 to 5



Have done away with magnitude ( length ), likewise the normalising



code is now



public void draw(Renderer r) {
if(dir = null) {
  dir = new Vector3f(0,0,0);
  localToWorld(new vector3f(0,1,0), dir);
}
directionToCameraDiff = r.getCamera().getDirection().dot(dir);



Im chewing over some of the other points you raised

localToWorld does:

getWorldRotation().mult(in,store).multLocal(getWorldScale()).addLocal( getWorldTranslation());



so it takes the point(or vector from origo to that point) and rotates, scales and translates it. so your "normal" vector will be useless if you do it like that. what you want is only the rotation:



getWorldRotation().mult(Vector3f.UNIT_Y, dir); //if unit y like you coded is the correct unrotated direction for your walls…

wow - good point



dont need translation or scale at all, and indeed 0,1,0 from origin is all i need.

When ruining your tests the walls seem to disappear two soon (When the camera is looking downwards). You may want to ignore the Up/Down portion of the vector.

To be honest, there isnt yet a fixed notion on how the camera will be controlled for the game in general.

Possibly a mix of 3 options,


  • first person with cursor look, camera staying where the players head is.

  • third person where camera is higher and further back from the player, looking down at the player. The player has a limited control of the camera angle and distance

  • a plan view, camera is high up looking down but the people are not shown



Need to do the same with the roof as has been done with the walls so that the roof can be viewed first person, but may be culled on the right angle of third person view


Im glad the test worked - havent had it yet confirmed wether it works on mac or linux