From cac5fa1371e8a93bdc4bceb016ddcb577085f98e Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 1 May 2015 09:39:39 -0700 Subject: [PATCH 1/2] refactored grab script using velocity and spring force --- examples/grab.js | 214 ++++++++++++++++------------------------------- 1 file changed, 74 insertions(+), 140 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 88e23c9a46..cd7d59701e 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -5,17 +5,13 @@ var deltaMouse = { z: 0 } var entityProps; -var box, box2, ground; -var baseMoveFactor = .001; -var finalMoveMultiplier; -var avatarEntityDistance; -var camYaw, dv; -var prevPosition; -var newPosition; -var flingVelocity; -var flingMultiplier = 10; +var targetPosition; var moveUpDown = false; -var savedGravity; + +var currentPosition, currentVelocity; + +var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); +var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); var DROP_DISTANCE = 5.0; var DROP_COLOR = { @@ -23,14 +19,9 @@ var DROP_COLOR = { green: 200, blue: 200 }; -var DROP_WIDTH = 4; +var DROP_WIDTH = 2; -var autoBox = false; -if (autoBox) { - setUpTestObjects(); -} - var dropLine = Overlays.addOverlay("line3d", { start: { x: 0, @@ -50,104 +41,80 @@ var dropLine = Overlays.addOverlay("line3d", { function mousePressEvent(event) { - if(!event.isLeftButton){ + if (!event.isLeftButton) { return; - } + } var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects && intersection.properties.collisionsWillMove) { grabbedEntity = intersection.entityID; var props = Entities.getEntityProperties(grabbedEntity) - prevPosition = props.position; isGrabbing = true; - savedGravity = props.gravity; - Overlays.editOverlay(dropLine, { + targetPosition = props.position; + currentPosition = props.position; + currentVelocity = props.velocity; + updateDropLine(targetPosition); + Audio.playSound(grabSound, { + position: props.position, + volume: 0.4 + }); + } +} + +function updateDropLine(position) { + Overlays.editOverlay(dropLine, { visible: true, - start: props.position, - end: Vec3.sum(props.position, { + start: position, + end: Vec3.sum(position, { x: 0, y: -DROP_DISTANCE, z: 0 }) - }); - Entities.editEntity(grabbedEntity, { - gravity: { - x: 0, - y: 0, - z: 0 - } - }); - //We need to store entity's current gravity, and then disable it while we move - - } - + }) } function mouseReleaseEvent() { if (isGrabbing) { - // flingObject(); - Entities.editEntity(grabbedEntity, { - gravity: savedGravity + isGrabbing = false; + Overlays.editOverlay(dropLine, { + visible: false }); + targetPosition = null; + Audio.playSound(grabSound, { + position: entityProps.position, + volume: 0.25 + }); + } - isGrabbing = false; - Overlays.editOverlay(dropLine, { - visible: false - }); -} - -function flingObject() { - //calculate velocity to give object base on current and previous position - entityProps = Entities.getEntityProperties(grabbedEntity); - - flingVelocity = Vec3.subtract(entityProps.position, prevPosition); - flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); - Entities.editEntity(grabbedEntity, { - velocity: flingVelocity - }); } function mouseMoveEvent(event) { if (isGrabbing) { - entityProps = Entities.getEntityProperties(grabbedEntity); - avatarEntityDistance = Vec3.distance(MyAvatar.position, entityProps.position); - finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); deltaMouse.x = event.x - prevMouse.x; if (!moveUpDown) { deltaMouse.z = event.y - prevMouse.y; + deltaMouse.y = 0; } else { deltaMouse.y = (event.y - prevMouse.y) * -1; + deltaMouse.z = 0; } - finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); - deltaMouse = Vec3.multiply(deltaMouse, finalMoveMultiplier); - camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y; - dv = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse); - newPosition = Vec3.sum(entityProps.position, dv); - Entities.editEntity(grabbedEntity, { - position: newPosition - }); - Overlays.editOverlay(dropLine, { - start: newPosition, - end: Vec3.sum(newPosition, { - x: 0, - y: -DROP_DISTANCE, - z: 0 - }) - }); - - flingVelocity = Vec3.subtract(entityProps.position, prevPosition); - flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); - Entities.editEntity(grabbedEntity, { - velocity: flingVelocity - }); - prevPosition = entityProps.position; + // Update the target position by the amount the mouse moved + var camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y; + var dPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse); + // Adjust target position for the object by the mouse move + var avatarEntityDistance = Vec3.distance(Camera.getPosition(), currentPosition); + // Scale distance we want to move by the distance from the camera to the grabbed object + // TODO: Correct SCREEN_TO_METERS to be correct for the actual FOV, resolution + var SCREEN_TO_METERS = 0.001; + targetPosition = Vec3.sum(targetPosition, Vec3.multiply(dPosition, avatarEntityDistance * SCREEN_TO_METERS)); } prevMouse.x = event.x; prevMouse.y = event.y; } + function keyReleaseEvent(event) { if (event.text === "SHIFT") { moveUpDown = false; @@ -160,69 +127,34 @@ function keyPressEvent(event) { } } +function update(deltaTime) { + if (isGrabbing) { -function setUpTestObjects() { - var distance = 4; - box = Entities.addEntity({ - type: 'Box', - position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance, Quat.getFront(Camera.getOrientation()))), - dimensions: { - x: .5, - y: .5, - z: .5 - }, - color: { - red: 200, - green: 50, - blue: 192 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -1, - z: 0 - } - }); + entityProps = Entities.getEntityProperties(grabbedEntity); + currentPosition = entityProps.position; + currentVelocity = entityProps.velocity; - box2 = Entities.addEntity({ - type: 'Box', - position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance + 1, Quat.getFront(Camera.getOrientation()))), - dimensions: { - x: .5, - y: .5, - z: .5 - }, - color: { - red: 200, - green: 50, - blue: 192 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -1, - z: 0 - } - }); - - ground = Entities.addEntity({ - type: 'Box', - position: { - x: MyAvatar.position.x, - y: MyAvatar.position.y - 5, - z: MyAvatar.position.z - }, - dimensions: { - x: 100, - y: 2, - z: 100 - }, - color: { - red: 20, - green: 200, - blue: 50 - } - }); + var dPosition = Vec3.subtract(targetPosition, currentPosition); + var CLOSE_ENOUGH = 0.001; + if (Vec3.length(dPosition) > CLOSE_ENOUGH) { + // compute current velocity in the direction we want to move + var velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition)); + // compute the speed we would like to be going toward the target position + var SPRING_RATE = 0.35; + var DAMPING_RATE = 0.55; + var desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE); + // compute how much we want to add to the existing velocity + var addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget); + var newVelocity = Vec3.sum(currentVelocity, addedVelocity); + // Add Damping + newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE)); + // Update entity + Entities.editEntity(grabbedEntity, { + velocity: newVelocity + }) + } + updateDropLine(currentPosition); + } } Controller.mouseMoveEvent.connect(mouseMoveEvent); @@ -230,3 +162,5 @@ Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.update.connect(update); + From 3ee111d7572ebaf3786e79bbf58bc8dde25c628b Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 1 May 2015 09:56:21 -0700 Subject: [PATCH 2/2] added script to generate a lot of physical blocks within a specified range --- examples/lotsoBlocks.js | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 examples/lotsoBlocks.js diff --git a/examples/lotsoBlocks.js b/examples/lotsoBlocks.js new file mode 100644 index 0000000000..63ed774d2d --- /dev/null +++ b/examples/lotsoBlocks.js @@ -0,0 +1,63 @@ +var NUM_BLOCKS = 200; +var size; +var SPAWN_RANGE = 10; +var boxes = []; +var basePosition, avatarRot; +var isAssignmentScript = false; +if(isAssignmentScript){ + basePosition = {x: 8000, y: 8000, z: 8000}; +} +else { + avatarRot = Quat.fromPitchYawRollDegrees(0, MyAvatar.bodyYaw, 0.0); + basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(SPAWN_RANGE * 3, Quat.getFront(avatarRot))); +} +basePosition.y -= SPAWN_RANGE; + +var ground = Entities.addEntity({ + type: "Model", + modelURL: "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx", + dimensions: { + x: 100, + y: 2, + z: 100 + }, + position: basePosition, + shapeType: 'box' +}); + + +basePosition.y += SPAWN_RANGE + 2; +for (var i = 0; i < NUM_BLOCKS; i++) { + size = randFloat(-.2, 0.7); + boxes.push(Entities.addEntity({ + type: 'Box', + dimensions: { + x: size, + y: size, + z: size + }, + position: { + x: basePosition.x + randFloat(-SPAWN_RANGE, SPAWN_RANGE), + y: basePosition.y - randFloat(-SPAWN_RANGE, SPAWN_RANGE), + z: basePosition.z + randFloat(-SPAWN_RANGE, SPAWN_RANGE) + }, + color: {red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255}, + collisionsWillMove: true, + gravity: {x: 0, y: 0, z: 0} + })); +} + + + +function cleanup() { + Entities.deleteEntity(ground); + boxes.forEach(function(box){ + Entities.deleteEntity(box); + }); +} + +Script.scriptEnding.connect(cleanup); + +function randFloat(low, high) { + return low + Math.random() * ( high - low ); +} \ No newline at end of file