Cam.contains() and Rectangle Select for RTS game…

I want to make rectangle select for my RTS game…

As far as I can see, look at this simple test, the cam.contains(geo.getWorldBound()) not working correctly or I missed something?



[java]

package jme3test.model.shape;



import com.jme3.app.SimpleApplication;

import com.jme3.bounding.BoundingVolume;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.Camera.FrustumIntersect;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Sphere;

import java.util.ArrayList;



public class TestSphere extends SimpleApplication {



public static void main(String[] args) {

TestSphere app = new TestSphere();

app.start();

}

private ArrayList<Geometry> geos = new ArrayList<Geometry>();



@Override

public void simpleInitApp() {

Sphere sphMesh = new Sphere(14, 14, 1);

Material solidColor = assetManager.loadMaterial("Common/Materials/RedColor.j3m");



for (int y = -5; y < 5; y++) {

for (int x = -5; x < 5; x++) {

Geometry sphere = new Geometry("sphere", sphMesh);

sphere.setMaterial(solidColor);

sphere.setLocalTranslation(x * 4, 0, y * 4);

//sphere.setModelBound(new BoundingSphere(1, Vector3f.ZERO));

//sphere.updateModelBound();

geos.add(sphere);

rootNode.attachChild(sphere);

}

}

cam.setLocation(new Vector3f(0, 5, 0));

cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);



for (Geometry geo : geos) {





BoundingVolume bv = geo.getWorldBound();

System.out.println(" " + bv);



}



//Logger.getLogger("").setLevel(Level.WARNING);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



for (Geometry geo : geos) {



BoundingVolume bv = geo.getWorldBound();

int planeState = bv.getCheckPlane();

bv.setCheckPlane(0);

//System.out.println(" " + bv);

if (cam.contains(bv).equals(FrustumIntersect.Inside)) {

geo.getMaterial().setColor("Color", ColorRGBA.Blue);

} else {

geo.getMaterial().setColor("Color", ColorRGBA.Gray);

}





bv.setCheckPlane(planeState);

}

}

}[/java]

http://hub.jmonkeyengine.org/groups/graphics/forum/topic/how-to-select-multiple-3d-objects-programatically/#post-98478

@normen: Yeah , thanks, It’s good but what about cam.contains … Can you tell me what wrong with that method… I even add setCheckPlane(savedState)… But it doesn’t work

Can you also try to set the Camera plane state?

It didn’t work neither…

[java] BoundingVolume bv = geo.getWorldBound();

int planeState = bv.getCheckPlane();

bv.setCheckPlane(0);



int ps = cam.getPlaneState();

cam.setPlaneState(0);

//System.out.println(" " + bv);

if (cam.contains(bv).equals(FrustumIntersect.Inside)) {

geo.getMaterial().setColor(“Color”, ColorRGBA.Blue);

} else {

geo.getMaterial().setColor(“Color”, ColorRGBA.Gray);

}



cam.setPlaneState(ps);

bv.setCheckPlane(planeState);[/java]

@Momoko_Fan: can you tell me where I should add those lines, I’ve said to my self for days that it should work right away but I didn’t. Please help!

The FrustumIntersects has 3 values, perhaps you’re getting “intersects” and not “inside”?

http://hub.jmonkeyengine.org/javadoc/com/jme3/renderer/Camera.FrustumIntersect.html

Since I don’t want to take the time to download, setup a project, and run your code… can you explain what you are seeing that is incorrect? Maybe it’s something we can spot in the code without running it.



For example, all of your geometries share the same material… so if you set the color on one of them then I’d expect it to change all of them. So the last one updated will always win.

-.- my silly fault…



But I have done something more complete and not relate to the material stuff but still the cam.contains() can’t point out which geometries are inside or outside the frustum.

I think because I use cam.contains() by my self, not in renderManager loop, that error happens… as metioned in javadoc:



NOTE: This method is used internally for culling, for public usage,

the plane state of the bounding volume must be saved and restored, e.g:




[java]BoundingVolume bv;

Camera c;

int planeState = bv.getPlaneState();

bv.setPlaneState(0);

c.contains(bv);

bv.setPlaneState(plateState);[/java]

What are you actually seeing?

I want just the inside sphere to change it color to blue, but also the intersected sphere changed to blue. And it look like the checking is not exactly the same everytime, in this frame it blue, other frames gray…

New code, fix the mat error:

[java]package jme3test.model.shape;



import com.jme3.app.SimpleApplication;

import com.jme3.bounding.BoundingVolume;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.Camera.FrustumIntersect;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Sphere;

import java.util.ArrayList;



public class TestSphere extends SimpleApplication {



public static void main(String[] args) {

TestSphere app = new TestSphere();

app.start();

}

private ArrayList<Geometry> geos = new ArrayList<Geometry>();



@Override

public void simpleInitApp() {

Sphere sphMesh = new Sphere(14, 14, 1);

Material solidColor = assetManager.loadMaterial("Common/Materials/RedColor.j3m");



for (int y = -5; y < 5; y++) {

for (int x = -5; x < 5; x++) {

Geometry sphere = new Geometry("sphere", sphMesh);

sphere.setMaterial(solidColor.clone());

sphere.setLocalTranslation(x * 4, 0, y * 4);

//sphere.setModelBound(new BoundingSphere(1, Vector3f.ZERO));

//sphere.updateModelBound();

geos.add(sphere);

rootNode.attachChild(sphere);

}

}

cam.setLocation(new Vector3f(0, 5, 0));

cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);



for (Geometry geo : geos) {





BoundingVolume bv = geo.getWorldBound();

System.out.println(" " + bv);



}



//Logger.getLogger("").setLevel(Level.WARNING);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



for (Geometry geo : geos) {



BoundingVolume bv = geo.getWorldBound();

int planeState = bv.getCheckPlane();

bv.setCheckPlane(0);



//int ps = cam.getPlaneState();

//cam.setPlaneState(0);

//System.out.println(" " + bv);

if (cam.contains(bv).equals(FrustumIntersect.Inside)) {

geo.getMaterial().setColor("Color", ColorRGBA.Blue);

} else {

geo.getMaterial().setColor("Color", ColorRGBA.Gray);

}



//cam.setPlaneState(ps);

bv.setCheckPlane(planeState);

}

}

}

[/java]

Why do you have the plane state stuff commented out?

even if i don’t comment those lines, the same things happens. I take a few steps in debug more in Camera class in the method contains() and find the logic look quite … strange. Anyway, I think it still should work. Can you just run that Test and tell me if It just my fault. I like the “pyramid” check method of normen but Cam.contains can be handy in many situations.



It’s my fault! After removing the commented lines, it works like a charm. The error belongs to the my changes in Camera class before. Thanks all you guys for helping me!

Reading a forum post takes me 5 seconds. Downloading the code, setting up a project, running it, deep diving into what’s wrong, etc… takes much much longer. So someone else will have to do that.

1 Like