ChrisCoray
ChrisCoray

Reputation: 455

Three JS select geometry by id

Background: I'm a dev that knows JS, but is relatively new to Three JS. I've done a few small projects that involve static scenes with basic repeating animation.

I'm currently working on a modified version of Google's Globe project http://workshop.chromeexperiments.com/globe/. Looking back, I probably should have just started from scratch, but it was a good tool to see the approach their dev took. I just wish I could now update ThreeJS w/o the whole thing falling apart (too many unsupported methods and some bugs I never could fix, at least not in the hour I attempted it).

In the original, they are merging all of the geometric points into one object to speed up FPS. For my purposes, I'm updating the points on the globe using JSON, and there will never be more than 100 (probably no more than 60 actually), so they need to remain individual. I've removed the "combine" phase so I can now individually assign data to the points and then TWEEN the height change animation.

My question is, how do I manually select a single point (which is a Cube Geometry) so that I can modify the height value? I've looked through Stack Overflow and Three JS on GitHub and I'm not sure I understand the process. I'm assigning an ID to make it directly relate to the data that is being passed into it (I know WebGL adds an individual name/ID for particles, but I need something that is more directly related to what I'm doing for the sake of simplicity). That seems to work fine. But again, as a JS dev I've tried .getElementById(id) and $('#'+id) in jQuery, and neither works. I realize that Geometry objects don't behave the same way as HTML DOM objects, so I guess that's where I'm having struggles.

Code to add a point of data to the globe:

function addPoint(lat, lng, size, color, server) {
    geometry = new THREE.Cube(0.75, 0.75, 1, 1, 1, 1, null, false, { px: true,
    nx: true, py: true, ny: true, pz: false, nz: true});

    for (var i = 0; i < geometry.vertices.length; i++) {
        var vertex = geometry.vertices[i];
        vertex.position.z += 0.5;
    }

    var point = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial ({
        vertexColors: THREE.FaceColors
    }));

    var phi = (90 - lat) * Math.PI / 180;
    var theta = (180 - lng) * Math.PI / 180;

    point.position.x = 200 * Math.sin(phi) * Math.cos(theta);
    point.position.y = 200 * Math.cos(phi);
    point.position.z = 200 * Math.sin(phi) * Math.sin(theta);

    if($('#'+server).length > 0) {
        server = server+'b';
    }

    point.id = server;

    point.lookAt(mesh.position);

    point.scale.z = -size;
    point.updateMatrix();

    for (var i = 0; i < point.geometry.faces.length; i++) {
        point.geometry.faces[i].color = color;
    }

console.log(point.id);

    scene.addObject(point);
}

So now to go back, I know I can't use point.id because obviously that will only reference inside the function. But I've tried 'Globe.id', 'Globe.object.id', 'object.id', and nothing seems to work. I know it is possible, I just can't seem to find a method that works.

Upvotes: 2

Views: 2425

Answers (1)

ChrisCoray
ChrisCoray

Reputation: 455

Okay, I found a method that works for this by playing with the structure.

Essentially, the scene is labeled "globe" and all objects are its children. So treating the scene as an array, we can successfully pass an object into a var using the following structure:

Globe > Scene > Children > [Object]

Using a matching function, we loop through each item and find the desired geometric object and assign it to a temporary var for animation/adjustment:

function updatePoints(server){
    var p, lineObject;

    $.getJSON('/JSON/'+server+'.json', function(serverdata) {

        /* script that sets p to either 0 or 1 depending on dataset */

        var pointId = server+p;

        //Cycle through all of the child objects and find a patch in 
        for(var t = 3; t < globe.scene.children.length; t++) {
            if(globe.scene.children[t].name === pointId) {
                //set temp var "lineObject" to the matched object
                lineObject = globe.scene.children[t];
            }
        }

        /* Manipulation based on data here, using lineObject */
    });
}

I don't know if this is something that anyone else has had questions on, but I hope it helps someone else! :)

EDIT: Just realized this isn't a keyed array so I can use .length to get total # of objects

Upvotes: 0

Related Questions