shang445751741 / earth-api-samples

Automatically exported from code.google.com/p/earth-api-samples
0 stars 0 forks source link

Ability to access to different parts of model or different objects in a model #598

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi friends, 

As usual lately, today I bring a new beatiful issue. What I'm trying to do this 
time is to move a model in the GE API. At first this seems extremely easy if 
the model is unique (a single object), but, what happens when the object is 
composed of several models? More specifically, it is a tank and its various 
parts, the wheels rotate and the barrel moves independently of the direction of 
the object. What I've done is create an array of objects I enter through a 
'for' 

var MODEL_URL = new Array ("http://localhost/tankbody.kmz", 
"http://localhost/tankwhells.kmz", "http://localhost/tankcanon.kmz"); 

and then ... 

for (i = 0; i <MODEL_URL.length; i + +) { 
  window.google.earth.fetchKml (ge, MODEL_URL, function (obj) {me.finishInit (obj);}); 
  } 

me.finishInit would function like this ... 

TankCam.prototype.finishInit = function(kml){

  var me = this;

  me.placemark = kml.getFeatures().getChildNodes().item(1);
  me.model = me.placemark.getGeometry();
  me.orientation = me.model.getOrientation();
  me.location = me.model.getLocation();

  me.model.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_SEA_FLOOR);
  me.orientation.setHeading(0);
  me.model.setOrientation(me.orientation);

  avatar = me.placemark;
  ge.getFeatures().appendChild(me.placemark); 
}

So far so good, as I have previously separate parts within the API and 
everything is in place, what happens is that when I try to move all the pieces 
at the same time ... 

if (turnLeft | | turnRight) { 
    turnSpeed var deltaX = 20.0 * / / radians / sec 
    if (turnLeft) 
      turnSpeed *= -1.0; 
    me.headingAngle turnSpeed * + = dt * Math.PI / 180.0; 
    me.orientation.setHeading (me.headingAngle * 180 / Math.PI) / / this is the movement running 

the movement is made only by the last item that I've entered in this case is 
the canon of the tank looking in the same direction as the camera, but when I 
try to access to the rest of the pieces, for example, the wheels (which make a 
cyclical motion when moving), does nothing or jerk. My question is, does anyone 
know any simple example or an alternative route to move all the kmz at the same 
time and access each one of them as I please? I accept any help or even pieces 
of code or hire an angel to get me out of this code, I have three days busy 
with this and I'm starting to get stressed. 

Thank you very much for all your help in advance.

Original issue reported on code.google.com by vrt...@gmail.com on 18 Feb 2011 at 1:13

GoogleCodeExporter commented 9 years ago
Here is the full code

I show you the code hoping you answer back with a solution

turnLeft = false;
turnRight = false;

g_mouseLocked = false;  
deltaX = 1;
deltaY = 1;
moveForward = false;
moveBackward = false;
strafeLeft = false;
strafeRight = false;

forwardVelocity = 3;
run = false;

rolling = 0;
var lastTurn = 0;
camera1 = true;
camera2 = false;
var avatar = new Array("");

var initScreen = false;

INITIAL_CAMERA_ALTITUDE = 1.7; // Roughly 6 feet tall
cameraAltitude = INITIAL_CAMERA_ALTITUDE;

var MODEL_URL = new 
Array("http://localhost/tankbody.kmz","http://localhost/tankwhell.kmz","http://l
ocalhost/tankcanion.kmz");

//----------------------------------------------------------------------------
// Utility Functions
//----------------------------------------------------------------------------

// Keep an angle in [-180,180]
function fixAngle(a) {
  while (a < -180) {
    a += 360;
  }
  while (a > 180) {
    a -= 360;
  }
  return a;
}

//----------------------------------------------------------------------------
// Input Handlers
//----------------------------------------------------------------------------

function mouseDown(e) {
    var mouseButton = e.getButton();
    var hitGlobe = e.getDidHitGlobe();

    if (mouseButton == 0 && hitGlobe == 1 && initScreen ){
        goUp = true;
    }
    if(mouseButton==2 && hitGlobe==1) { 
        goDown = true;        
        } 
    if (!initScreen){
    g_mouseLocked = !g_mouseLocked;
    initScreen = true;
    tiltDown = false;
    tiltUp = false;
    turnLeft = false;
    turnRight = false;
    }

}

function mouseUp(e){

    var mouseButton = e.getButton();
    var hitGlobe = e.getDidHitGlobe();
    if(mouseButton==2 && hitGlobe==1) { 
        goDown = false;        
        } 
    if(mouseButton == 0 && hitGlobe == 1) { 
        goUp = false;        
        } 
}

function eventHandler(event) {

    var x=event.getClientX();
    var y=event.getClientY();
    var screenX = event.getScreenX();
    var screenY = event.getScreenY();
    var text = 'Click';
    myWidth = window.innerWidth/5;
    myHeight = window.innerHeight/7;
    maxX = 2*myWidth;
    maxY = 2*myHeight;

     if (g_mouseLocked) {
            if (x<2*myWidth){

                turnRight = false;
                deltaX = Math.exp((((3*myWidth-x)/maxX)-1)*3);   //           (((3*myWidth-x)/maxX)+0.02)*3;
                turnLeft= true;  

            }
            else if (x>3*myWidth) {
                turnLeft = false;
                 deltaX = Math.exp((((x-3*myWidth)/maxX)-0.5)*3);//(((x-3*myWidth)/maxX)+0.02)*3;
                turnRight=true;

            }
                else{
                     turnLeft = false;
                     turnRight = false;
                }    
            if (y<2*myHeight){
                  tiltDown = false;
                  deltaY = (((2*myHeight-y)/maxY)+0.5);
                  tiltUp=true;            
            }
            else if (y>5*myHeight) {
                tiltUp = false;
                deltaY = (((y-5*myHeight)/maxY)+0.5);
                tiltDown = true; 
            }
                else{
                     tiltDown = false;
                     tiltUp=false;
                }  
    }  

    event.returnValue = false;

}

function keyDown(event) {
  if (!event) {
    event = window.event;
  }
  if (event.keyCode == 37) {  // Turn Left.
    turnLeft = true;
    event.returnValue = false;
  } else if (event.keyCode == 39) {  // Turn Right.
    turnRight = true;
    event.returnValue = false;
  } else if (event.keyCode == 38) {  // Tilt Up.
    tiltUp = true;
    event.returnValue = false;
  } else if (event.keyCode == 40) {  // Tilt Down.
    tiltDown = true;
    event.returnValue = false;
  } else if (event.keyCode == 65) {  // Strafe Left.
    strafeLeft = true;
    event.returnValue = false;
  } else if (event.keyCode == 68) {  // Strafe Right.
    strafeRight = true;
    event.returnValue = false;
  } else if (event.keyCode == 87) {  // Move Forward.
    moveForward = true;    
    event.returnValue = false;    
  } else if (event.keyCode == 83) {  // Move Forward.
    moveBackward = true; 
    event.returnValue = false;    
  } else if (event.keyCode == 32) {  // Spacebar           
    run=true;
    event.returnValue = false;
  } else if (event.keyCode == 49) {  // Camera 1           
    camera1 = true;
    event.returnValue = false;
  } else if (event.keyCode == 50) {  // Camera 2           
    camera2 = true;
    event.returnValue = false;
  } else if (event.keyCode == 27) {  // escape           
    initScreen = false;
    g_mouseLocked = false;
  }   
  else {
    return true;
  }
  return false;
}

function keyUp(event) {
  if (!event) {
    event = window.event;
  } 
  if (event.keyCode == 37) {  // Left.
    turnLeft = false;
    event.returnValue = false;
  } else if (event.keyCode == 39) {  // Right.
    turnRight = false;
    event.returnValue = false;
  } else if (event.keyCode == 38) {  // Up.
    tiltUp = false;
    event.returnValue = false;
  } else if (event.keyCode == 40) {  // Down.
    tiltDown = false;
    event.returnValue = false;   
  } else if (event.keyCode == 65) {  // Strafe Left.
    strafeLeft = false;
    event.returnValue = false;
  } else if (event.keyCode == 68) {  // Strafe Right.
    strafeRight = false;
    event.returnValue = false;
  } else if (event.keyCode == 87) {  // Move Forward.
    moveForward = false;    
    event.returnValue = false;    
  } else if (event.keyCode == 83) {  // Move Forward.
    moveBackward = false;
    event.returnValue = false;       
  } else if (event.keyCode == 32) {  // Run
    run = false;
    event.returnValue = false;
  } else if (event.keyCode == 49) {  // Camera1
    camera1 = false;
    event.returnValue = false;     
  } else if (event.keyCode == 50) {  // Camera2
    camera2 = false;
    event.returnValue = false;
  } else if (event.keyCode == 27) {  // escape

  } 
  return false;
}

function TankCam() {
  var me = this;

  me.localAnchorLla = [37.77976, -122.418307, 0]; 
  me.localAnchorCartesian = V3.latLonAltToCartesian(me.localAnchorLla);

  // Heading, tilt angle is relative to local frame
  me.headingAngle = 0*Math.PI/180;
  me.tiltAngle = 0;
  me.roll = 0;
  // Initialize the time
  me.lastMillis = (new Date()).getTime();  

  // Used for bounce.
  me.distanceTraveled = 0;              

  // prevent mouse navigation in the plugin
  ge.getOptions().setMouseNavigationEnabled(true);

  for (i=0; i<MODEL_URL.length; i++){

  window.google.earth.fetchKml(ge, MODEL, function(obj) { me.finishInit(obj); });
  }                             

  google.earth.addEventListener(ge, "frameend",
                                function() { me.update(); });
}

TankCam.prototype.finishInit = function(kml){

  var me = this;

  me.placemark = kml.getFeatures().getChildNodes().item(1);
  me.model = me.placemark.getGeometry();
  me.orientation = me.model.getOrientation();
  me.location = me.model.getLocation();

  me.model.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_SEA_FLOOR);
  me.orientation.setHeading(0);
  me.model.setOrientation(me.orientation);

  avatar = me.placemark;
  ge.getFeatures().appendChild(avatar); 
}

TankCam.prototype.updateOrientation = function(dt) {

   var me = this;

  // Based on dt and input press, update turn angle.
  if (turnLeft || turnRight) {  
    var turnSpeed = 20.0 * deltaX; // radians/sec
    if (turnLeft)
      turnSpeed *= -1.0;
    me.headingAngle += turnSpeed * dt * Math.PI / 180.0;

    ******** HERE IS THE CRAZY STUFF I'VE TRYED TO SET A DIFFERENT HEADING OF THE THREE OBJECTS ************** 
     ******* I KNOW IS WRONG BECAUSE I LEAVE THE IMPOSIBLE, DON'T CARE ABOUT THIS CODE ****************************

    //for (i=0;i<=avatar.length;i++){

    //  me.model[1] = avatar[1].getGeometry();
    //  me.orientation[1] = me.model[1].getOrientation();
    //  me.orientation[1].setHeading(me.headingAngle * 180 / Math.PI);

    //  avatar[i].orientation.setHeading(me.headingAngle * 180 / Math.PI);
    //  avatar[i].model.orientation.setHeading(me.headingAngle * 180 / Math.PI);
        me.orientation.setHeading(me.headingAngle * 180 / Math.PI);  
    //}
  }
********************************************************************************
*******************************  

  // TODO (1 - t) * a + t * b  formula del lerp 

  // tilting
  if (tiltUp || tiltDown) {
    var tiltSpeed = 10.0 * deltaY; // radians/sec
    if (tiltDown)
      tiltSpeed *= -1.0;
    me.tiltAngle += tiltSpeed * dt * Math.PI / 180.0;
    // Clamp
    var tiltMax = 90.0 * Math.PI / 180.0;
    var tiltMin = -90.0 * Math.PI / 180.0;

    if (me.tiltAngle > tiltMax){
      me.tiltAngle = tiltMax;
      }
    if (me.tiltAngle < tiltMin){
      me.tiltAngle = tiltMin;
      }
  } 
}

TankCam.prototype.updatePosition = function(dt) {

     var me = this;

  // Convert local lat/lon to a global matrix. The up vector is 
  // vector = position - center of earth. And the right vector is a vector
  // pointing eastwards and the facing vector is pointing towards north.
  var localToGlobalFrame = M33.makeLocalToGlobalFrame(me.localAnchorLla); 

  // Move in heading direction by rotating the facing vector around
  // the up vector, in the angle specified by the heading angle.
  // Strafing is similar, except it's aligned towards the right vec.
  var headingVec = V3.rotate(localToGlobalFrame[1], localToGlobalFrame[2],
                             -me.headingAngle);                             
  var rightVec = V3.rotate(localToGlobalFrame[0], localToGlobalFrame[2],
                             -me.headingAngle);
  // Calculate strafe/forwards                              
  var strafe = 0;                             
  if (strafeLeft || strafeRight) {
    var strafeVelocity = 4;

    if (strafeLeft)
      strafeVelocity *= -1;      
    strafe = strafeVelocity * dt;
    }

  var forward = 0;                             
  if (moveForward || moveBackward) {
    var forwardVelocity = 4;
    if (run)
        forwardVelocity = 12;

        if (run) forwardVelocity = forwardVelocity * 5;

    if (moveBackward)
      forwardVelocity *= -1;      
    forward = forwardVelocity * dt;
  }  

  cameraAltitude = Math.max(0, cameraAltitude);

  me.distanceTraveled += forward;

  // Add the change in position due to forward velocity and strafe velocity 
  me.localAnchorCartesian = V3.add(me.localAnchorCartesian, 
                                   V3.scale(rightVec, strafe));
  me.localAnchorCartesian = V3.add(me.localAnchorCartesian, 
                                   V3.scale(headingVec, forward));

  // Convert cartesian to Lat Lon Altitude for camera setup later on.
  me.localAnchorLla = V3.cartesianToLatLonAlt(me.localAnchorCartesian);

}

TankCam.prototype.updateCamera = function() {
  var me = this;

  var lla = me.localAnchorLla;
  lla[2] = ge.getGlobe().getGroundAltitude(lla[0], lla[1]); 

  // Update camera position. Note that tilt at 0 is facing directly downwards.
  //  We add 90 such that 90 degrees is facing forwards.
  var la = ge.createCamera('');
  la.set(me.localAnchorLla[0], me.localAnchorLla[1],
         cameraAltitude,
         ge.ALTITUDE_RELATIVE_TO_SEA_FLOOR,
         fixAngle(me.headingAngle * 180 / Math.PI), /* heading */         
         me.tiltAngle * 180 / Math.PI + 90, /* tilt */         
         me.roll /* altitude is constant */         
         );  

  ge.getView().setAbstractView(la);         
};

TankCam.prototype.update = function() {
  var me = this;

  ge.getWindow().blur();

  // Update delta time (dt in seconds)
  var now = (new Date()).getTime();  
  var dt = (now - me.lastMillis) / 1000.0;
  if (dt > 0.25) {
    dt = 0.25;
  }  
  me.lastMillis = now;    

  // Update orientation and then position  of camera based
  // on user input   
  me.updateOrientation(dt);
  me.updatePosition(dt);

  // Update camera
  me.updateCamera();
};

PROBABLY YOU'LL SEE THERE'S A FEW THINGS MISSING LIKE {},; OR WHATEVER STUFF 
LIKE THIS BUT IF YOU TRY TO FIX IT YOU'LL SEE THAT THERE'S NO FULL MOVEMENT OF 
ALL PARTS, I'VE TRYED EVERYTHING AND NO CHANGES.

Original comment by vrt...@gmail.com on 19 Feb 2011 at 10:20

GoogleCodeExporter commented 9 years ago
I'm not sure if I understand the issue. If these are a group of geometries, you 
should be able to add them as siblings to the DOM and then move them via their 
parent node. Do you have a link where your example can be seen in action?

Original comment by bcke...@google.com on 17 May 2011 at 12:28

GoogleCodeExporter commented 9 years ago
actually, sorry, my last statement is incorrect. You would have to transform 
each part separately and then update each position manually. This is slightly 
awkward in Earth because the KML DOM is specifically *not* a spatial 
scenegraph, which is the same reason that the Earth API does not have this 
functionality.

However, this is pretty standard code in just about any scenegraph library, so 
should be easily obtainable for this purpose. I suggest adapting that code for 
this purpose, then treating the KmlModel objects as write-only views, using 
setLocation() and setOrientation().

The Earth Utility Library may also be helpful:
http://code.google.com/p/earth-api-utility-library/

Original comment by bcke...@google.com on 17 May 2011 at 12:40