Problems with picking .3ds


I am trying to develop a line of sight for the enemy and am thinking of using 5 rays - 1 from the center of enemy 2 from right at 1-2 unit distance and similarly 2 on the left. If the first result for any ray is the player then enemy can follow certain AI actions. I have just started with one ray and was just looking at how it detects .3ds model that enemies and players use.

When I fire the ray from the enemy's location, the first 3 objects it detects are itself - object2##0, object3##0, object1##0(they are located at distance 0.0 so I think its from its own .3ds model) and then the fourth one is the closest object. object2##0, object3##0 and object1##0 are string names achieved using .getName() while the parent nodes are object2 (com.jme.scene.Node), object3 (com.jme.scene.Node) and object1 (com.jme.scene.Node) instead of the normal playerNode achieved using .getParent() (see methods below). The .3ds objects are imported using the standard way and the picking is done fairly standard way as well. How can I get the methods to return its actual playerNode so if it gets detected then I can set some actions for the AI.

importing .3ds

private void createGuard()
        Node model = null;
            MaxToJme C1 = new MaxToJme();
            ByteArrayOutputStream BO = new ByteArrayOutputStream();
            URL maxFile = Ares.class.getClassLoader().getResource("jmetest/data/model/robot.3ds");
            C1.convert(new BufferedInputStream(maxFile.openStream()),BO);
            model = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
            model.setModelBound(new BoundingBox());
            //scale it to be much bigger than it is originally
            //Rotating the model 90 degree along the Y-axis as .3ds models are
            //not always straight when imported
            Vector3f axis = new Vector3f(Vector3f.UNIT_Y); // this equals (0, 1, 0) and does not require to create a new object
            float angle = 1.57f;
            model.getLocalRotation().fromAngleAxis(angle, axis);
            guardNode = new Node("Guard");
            guardNode.setLocalTranslation(new Vector3f(-60, 14, -10));
            scene.updateGeometricState(0, true);

picking method

private void lineOfSight()
        Ray ray = new Ray(guardNode.getLocalTranslation(), guardNode.getLocalRotation().getRotationColumn(2));
        PickResults results = new BoundingPickResults();
        if(results.getNumber() > 0)
            for(int i = 0; i < 4 /*results.getNumber()*/; i++)
                //System.out.println("Name of the object: " + results.getPickData(i).getTargetMesh().getParentGeom().getName() + " Distance: " + results.getPickData(i).getDistance());
                if(results.getPickData(3).getTargetMesh().getParentGeom().getParent() == playerNode)  //fourth result used as first
                {                                                                                     //three are itself as explained
                    shootAtPlayer();                                                                  //in the post
                    System.out.println("!!!!!!!!!!!!!!!!!Player spotted!!!!!!!!!!!!");
        //return true;

i do it this way:

@Nullable public static LightEntity getParentEntity(SceneElement p_sceneElement) {
    while (true) {
      if (p_sceneElement instanceof LightEntity) {
        final LightEntity l_entity = (LightEntity) p_sceneElement;
        return l_entity;
      } else if (p_sceneElement instanceof Geometry) {
        final Geometry l_batch = (Geometry) p_sceneElement;
        p_sceneElement = l_batch.getParent();
      } else if (p_sceneElement instanceof Node) {
        final Node l_node = (Node) p_sceneElement;
        p_sceneElement = l_node.getParent();
      } else if (p_sceneElement instanceof GeomBatch) {
        final GeomBatch l_geomBatch = (GeomBatch) p_sceneElement;
        p_sceneElement = l_geomBatch.getParentGeom();
      } else {
        return null;

lightentity is the baseclass for all my in game objects

to avoid picking yourself, you might do something like this:

 @Nullable public PickData getStaticMeshAtCrosshair() {
    if (getCurrentLevel().isAboveGround()) {
      ms_core.getStaticObjects().findPick(ms_tmpRay, ms_pickResultsTriangle);
    } else {
      //noinspection ConstantConditions
      getCurrentDungeonLevel().findPick(ms_tmpRay, ms_pickResultsTriangle);
    final int l_number = ms_pickResultsTriangle.getNumber();
    if (l_number > 0) {
      final PickData l_pickData = Utils.getNearestPick(ms_pickResultsTriangle);
      return l_pickData;
    return null;

in short: disable collisions before the pick and enable them again
(you might wonder about that getRelativeBackPointingAt(). well, in the first days of hhexen, i created a bug without noticing. every objects moves backwards, up is down, left is right, front is back, so every model is actually rotated 180

Hey HamsterofDeath,

Thats some slick work there… I bet hhexen would be a really good game and you have gathered some really useful experience on games programming and advanced functionalities of jME. My point here is only that why on picking instead of detecting the parent node of the object it detects the actual parts of the .3ds file?? e.g. if that ray is directed at a medical box (box geometry attached to medical node), instead of saying it detects a box, it says it detects "medical node" - the string name of medical node. Similarly for this .3ds file instead of saying it detects 3 parts of the .3ds file, why is it not saying "Guard" - string name of guardNode(see code in starter post above)…

It would be similar with automated picking… Is there any different way of picking with .3ds files or I should adjust something??

the ray picks the deepest sceneelement of the graph. it doesn't know where to stop. you have to traverse backwards until you get the node you are interested in. my getParentEntity() method solves exactly this problem. it stops at lightentitiy, which is the baseclass of every object in hhexen.