From 5c7bb87014359eeeb8730ca9d4fbf4a2eff853d0 Mon Sep 17 00:00:00 2001 From: monsterkodi Date: Sat, 13 Aug 2016 23:46:29 +0200 Subject: [PATCH] move --- coffee/actor.coffee | 1 + coffee/bot.coffee | 64 ++++++++++++++++++++++++------- coffee/event.coffee | 7 +++- coffee/lib/matrix.coffee | 25 +++++++------ coffee/lib/vector.coffee | 10 +++++ coffee/perspective.coffee | 12 +++--- coffee/player.coffee | 55 ++++++++++++++------------- coffee/world.coffee | 79 ++++++++++++++++++++------------------- 8 files changed, 156 insertions(+), 97 deletions(-) diff --git a/coffee/actor.coffee b/coffee/actor.coffee index 66346ed..655bb3c 100644 --- a/coffee/actor.coffee +++ b/coffee/actor.coffee @@ -94,6 +94,7 @@ class Actor extends Emitter startTimedAction: (action, duration) -> action.duration = duration if duration >= 0 + log "Actor.startTimedAction #{action.name} duration: #{duration}" Timer.addAction action module.exports = Actor diff --git a/coffee/bot.coffee b/coffee/bot.coffee index e0380b4..ffbcb52 100644 --- a/coffee/bot.coffee +++ b/coffee/bot.coffee @@ -25,18 +25,43 @@ class Bot extends Pushable @climb_orientation = new Quaternion @rest_orientation = new Quaternion - @geom = new THREE.SphereGeometry 1, 32, 32 - @mat = new THREE.MeshPhongMaterial + geom = new THREE.SphereGeometry 0.5, 32, 32 + mat = new THREE.MeshPhongMaterial color: 0x0000ff side: THREE.FrontSide shading: THREE.SmoothShading transparent: true opacity: 0.9 shininess: 0.99 - - @mesh = new THREE.Mesh @geom, @mat + @mesh = new THREE.Mesh geom, mat world.scene.add @mesh - + + geom = new THREE.TorusGeometry 0.5, 0.2, 16, 64 + mat = new THREE.MeshPhongMaterial + color: 0x0000ff + side: THREE.FrontSide + shading: THREE.SmoothShading + transparent: true + opacity: 0.9 + shininess: 0.99 + @leftTire = new THREE.Mesh geom, mat + @leftTire.position.set -0.5,0,0 + @leftTire.rotation.set 0, Vector.DEG2RAD(90), 0 + @mesh.add @leftTire + + geom = new THREE.TorusGeometry 0.5, 0.2, 16, 64 + mat = new THREE.MeshPhongMaterial + color: 0x0000ff + side: THREE.FrontSide + shading: THREE.SmoothShading + transparent: true + opacity: 0.9 + shininess: 0.99 + @rightTire = new THREE.Mesh geom, mat + @rightTire.position.set 0.5,0,0 + @leftTire.rotation.set 0, Vector.DEG2RAD(-90), 0 + @mesh.add @rightTire + @left_tire_rot = 0.0 @right_tire_rot = 0.0 @last_fume = 0 @@ -149,7 +174,7 @@ class Bot extends Pushable dltTime = action.getRelativeDelta() # log "Bot.performAction #{action.name} #{action.current} #{action.last} #{action.duration} id #{actionId}" - # log "Bot.performAction #{action.name} #{relTime} #{dltTime} id #{actionId}" + log "Bot.performAction #{action.name} #{relTime} #{dltTime} id #{actionId}" switch actionId when Action.SHOOT @@ -163,7 +188,7 @@ class Bot extends Pushable @left_tire_rot += @dir_sgn * dltTime @right_tire_rot += @dir_sgn * dltTime @current_position = @position.plus @getDir().mul relTime - log 'forward', @current_position + # log 'bot.forward', @current_position return when Action.JUMP @@ -203,7 +228,7 @@ class Bot extends Pushable @left_tire_rot += @dir_sgn * dltTime @right_tire_rot += @dir_sgn * dltTime if relTime <= 0.2 - @current_position = @position.plus @getDir().mul (relTime/0.2)/2 + @current_position = @position.plus @getDir().mul (relTime/0.2)/2 else if (relTime >= 0.8) @climb_orientation = Quaternion.rotationAroundVector @dir_sgn * 90.0, new Vector 1,0,0 @current_position = @position.plus @getDir().plus @getDown().mul 0.5+(relTime-0.8)/0.2/2 @@ -368,9 +393,8 @@ class Bot extends Pushable else @dir_sgn = 1 @jump_once = false if actionId != Action.NOOP - # keep action chain flowing in order to detect environment changes - log 'startTimedAction NOOP' - @startTimedAction @getActionWithId(Action.NOOP), 0 + # keep action chain flowinwg in order to detect environment changes + # @startTimedAction @getActionWithId(Action.NOOP), 0 moveBot: () -> @move_action = null @@ -413,10 +437,24 @@ class Bot extends Pushable @move_action.keepRest() # try to make subsequent actions smooth Timer.addAction @move_action - render: () -> + + # 0000000 000000000 00000000 00000000 + # 000 000 000 000 000 + # 0000000 000 0000000 00000000 + # 000 000 000 000 + # 0000000 000 00000000 000 + + step: (step) -> + # log 'Bot.step', step radius = 0.5 tireRadius = 0.15 + # log 'Bot.step', @current_position + @mesh.position.copy @current_position + @mesh.quaternion.copy @current_orientation + # @leftTire.rotation.copy @left_tire_rot + # @leftTire.rotation.copy @right_tire_rot + # if (@died) @getDeadColor().glColor() # else @getTireColor().glColor() @@ -440,7 +478,7 @@ class Bot extends Pushable # if not @died then @getBodyColor().glColor() - @render_body() + # @render_body() # if (@move_action or @rotate_action) and not @died # unsigned now = getTime() diff --git a/coffee/event.coffee b/coffee/event.coffee index 38f6048..02d64ff 100644 --- a/coffee/event.coffee +++ b/coffee/event.coffee @@ -23,13 +23,16 @@ class Event hasAction: (action) -> _.find @actions, action addAction: (action) -> - log "Event.addAction #{action.name}" if action? and not @hasAction action + log "Event.addAction #{action.name}" @actions.push action action.event = @ action.init() + else if not action? + console.log 'Event.addAction no action?' + throw new Error else - log 'no action?', action + log "Event.addAction has action #{action.name}" removeAllActions: () -> while @actions.length diff --git a/coffee/lib/matrix.coffee b/coffee/lib/matrix.coffee index f0e795f..3091fd9 100644 --- a/coffee/lib/matrix.coffee +++ b/coffee/lib/matrix.coffee @@ -4,8 +4,9 @@ # 000 0 000 000 000 000 000 000 000 000 000 # 000 000 000 000 000 000 000 000 000 000 -Quaternion = require './quaternion' -Vector = require './vector' +log = require '/Users/kodi/s/ko/js/tools/log' +Quaternion = require './quaternion' +Vector = require './vector' class Matrix @@ -24,6 +25,7 @@ class Matrix when o?.x? and o?.y? and o?.z? @initXYZ o.x, o.y, o.z else @reset() + log 'matrix.init', @matrix initXYZ: (x,y,z) -> @matrix[0] = x.x @@ -304,21 +306,22 @@ class Matrix @matrix[12] = v.x @matrix[13] = v.y @matrix[14] = v.z + # log 'Matrix.setPosition', @matrix setXVector: (v) -> - @matrix[0] = v[0] - @matrix[1] = v[1] - @matrix[2] = v[2] + @matrix[0] = v.x + @matrix[1] = v.y + @matrix[2] = v.z setYVector: (v) -> - @matrix[4] = v[0] - @matrix[5] = v[1] - @matrix[6] = v[2] + @matrix[4] = v.x + @matrix[5] = v.y + @matrix[6] = v.z setZVector: (v) -> - @matrix[8] = v[0] - @matrix[9] = v[1] - @matrix[10] = v[2] + @matrix[8] = v.x + @matrix[9] = v.y + @matrix[10] = v.z getXVector: () -> new Vector @matrix[0], @matrix[1], @matrix[2] getYVector: () -> new Vector @matrix[4], @matrix[5], @matrix[6] diff --git a/coffee/lib/vector.coffee b/coffee/lib/vector.coffee index 35c3aa7..9e5ddb6 100644 --- a/coffee/lib/vector.coffee +++ b/coffee/lib/vector.coffee @@ -109,6 +109,16 @@ class Vector isZero: -> @x == @y == @z == @w == 0 + @rayPlaneIntersection: (rayPos, rayDirection, planePos, planeNormal) -> + x = planePos.minus(rayPos).dot(planeNormal) / rayDirection.dot(planeNormal) + return rayPos.plus rayDirection.mul x + + @pointMappedToPlane: (point, planePos, planeNormal) -> + point.minus(planeNormal).dot point.minus(planePos).dot(planeNormal) + + @rayPlaneIntersectionFactor: (rayPos, rayDirection, planePos, planeNormal) -> + planePos.minus(rayPos).dot(planeNormal) / rayDirection.dot(planeNormal) + @DEG2RAD: (d) -> Math.PI*d/180.0 @RAD2DEG: (r) -> r*180.0/Math.PI diff --git a/coffee/perspective.coffee b/coffee/perspective.coffee index 40f4c38..47abf0e 100644 --- a/coffee/perspective.coffee +++ b/coffee/perspective.coffee @@ -65,6 +65,8 @@ class Perspective extends Matrix lookAt = @getLookAtPosition() # log "Perspective.apply", @matrix #camPos, up, lookAt + # log "Perspective.apply", camPos, up, lookAt + # log "Perspective.apply", new Pos(camPos), new Pos(up), new Pos(lookAt) camera.position.clone camPos #set camPos.x, camPos.y, camPos.z camera.up.clone up #new THREE.Vector3 up.x, up.y, up.z @@ -79,19 +81,19 @@ class Perspective extends Matrix setEyeDistance: (distance) -> lookAtPos = @getLookAtPosition() - @eye_distance = kMin( kMax(@znear, distance), 0.9 * @zfar ); - setPosition lookAtPos + @eye_distance * @getZVector() + @eye_distance = Math.min Math.max(@znear, distance), 0.9*@zfar + @setPosition lookAtPos.plus @getZVector().mul @eye_distance setLookAtPosition: (lookAtPos) -> up = @getYVector() - newLook = (lookAtPos - @getPosition()).normal() + newLook = lookAtPos.minus(@getPosition()).normal() newRight = up.cross(newLook).normal() newUp = newLook.cross(newRight).normal() @setXVector newRight @setYVector newUp @setZVector newLook - + log 'setLookAtPosition', @matrix @eye_distance = lookAtPos.minus(@getPosition()).length() getLookAtPosition: -> @getZVector().mul(-@eye_distance).plus @getPosition() @@ -112,7 +114,7 @@ class Perspective extends Matrix setViewportBorder: (l, b, r, t) -> @border = [l,b,r,t] - @updateViewport(); + @updateViewport() setViewport: (l, b, w, h) -> @viewport = [l,b,w,h] diff --git a/coffee/player.coffee b/coffee/player.coffee index 5b7e402..ade2676 100644 --- a/coffee/player.coffee +++ b/coffee/player.coffee @@ -39,6 +39,7 @@ class Player extends Bot lookDown: 'down' shoot: 'space' jump: 'command' + view: 'v' @look_action = null @look_angle = 0.0 @@ -100,7 +101,7 @@ class Player extends Bot updatePosition: () -> if @move_action - relTime = (world.getTime() - @move_action.getStart()) / @move_action.getDuration() + relTime = (world.getTime() - @move_action.start) / @move_action.duration if relTime <= 1.0 switch @move_action.id when Action.FORWARD @@ -119,10 +120,10 @@ class Player extends Bot # 000 000 000 0000000 0000000 00000000 0000000 000 000 0000000 000 000 getProjection: () -> + # smooth camera movement a little bit posDelta = world.getSpeed() / 10.0 @projection.setPosition @projection.getPosition().mul(1.0 - posDelta).plus @current_position.mul posDelta - playerDir = @getCurrentDir() playerUp = @current_orientation.rotate(new Vector(0,1,0)).normal() @@ -131,6 +132,7 @@ class Player extends Bot @look_rot = Quaternion.rotationAroundVector @look_angle, @projection.getXVector() @projection.setYVector @look_rot.rotate playerUp @projection.setZVector @look_rot.rotate playerDir.neg() + log 'Player.getProjection 2', @projection.matrix else # smooth camera rotation a little bit lookDelta = (2.0 - @projection.getZVector().dot playerDir) * world.getSpeed() / 50.0 @@ -141,6 +143,7 @@ class Player extends Bot @projection.setYVector playerUp @projection.setZVector newLookVector + # log 'Player.getProjection', @projection.getPosition() @projection # 0000000 00000000 000 000 000 000 000 0000000 @@ -150,43 +153,42 @@ class Player extends Bot # 0000000 00000000 000 000 000 000 000 0000000 getBehindProjection: () -> - log 'getBehindProjection' @updatePosition() - playerDir = getCurrentDir() + playerDir = @getCurrentDir() playerUp = @current_orientation.rotate(new Vector(0,1,0)).normal() # find a valid camera position - botToCamera = (playerUp - 2 * playerDir) + botToCamera = playerUp.minus playerDir.mul 2 min_f = botToCamera.length() botToCamera.normalize() min_f = Math.min world.getWallDistanceForRay(@current_position, botToCamera), min_f - cameraPos = @current_position + kMax(min_f, 0.72) * botToCamera + cameraPos = @current_position.plus botToCamera.mul Math.max min_f, 0.72 cameraPos = world.getInsideWallPosWithDelta cameraPos, 0.2 # smooth camera movement a little bit posDelta = 0.2 - @projection.setPosition ((1.0 - posDelta) * @projection.getPosition() + posDelta * cameraPos) + @projection.setPosition @projection.getPosition().mul(1.0 - posDelta).plus cameraPos.mul posDelta if @look_angle - @projection.setXVector(playerUp.cross(playerDir).normal()) - KQuaternion look_rot = KQuaternion.rotationAroundVector(@look_angle, @projection.getXVector()) - @projection.setYVector(look_rot.rotate(playerUp)) - @projection.setZVector(look_rot.rotate(playerDir.neg())) + @projection.setXVector playerUp.cross(playerDir).normal() + look_rot = Quaternion.rotationAroundVector @look_angle, @projection.getXVector() + @projection.setYVector look_rot.rotate playerUp + @projection.setZVector look_rot.rotate playerDir.neg() else # smooth camera rotation a little bit lookDelta = 0.3 - newLookVector = @projection.getZVector().mul((1.0 - lookDelta)).minus @playerDir.mul lookDelta + newLookVector = @projection.getZVector().mul(1.0 - lookDelta).minus playerDir.mul lookDelta newLookVector.normalize() - @projection.setZVector(newLookVector) - @projection.setXVector(playerUp.cross(newLookVector).normal()) - @projection.setYVector(newLookVector.cross(@projection.getXVector()).normal()) + @projection.setZVector newLookVector + @projection.setXVector playerUp.cross(newLookVector).normal() + @projection.setYVector newLookVector.cross(@projection.getXVector()).normal() + log 'Player.getBehindProjection', @projection.getPosition() @projection - # 00000000 0000000 000 000 0000000 000 000 # 000 000 000 000 000 000 000 000 0 000 # 000000 000 000 000 000 000 000 000000000 @@ -194,7 +196,7 @@ class Player extends Bot # 000 0000000 0000000 0000000 0000000 00 00 getFollowProjection: () -> - log 'getFollowProjection' + cameraPos = @projection.getPosition() # current camera position desiredDistance = 2.0 # desired distance from camera to bot @@ -236,16 +238,16 @@ class Player extends Bot botToCamera = cameraPos.minus playerPos botToCameraNormal = botToCamera.normal() - rot_factor = 1.0 - wall_distance = world.getWallDistanceForPos (playerPos + botToCamera) + rotFactor = 1.0 + wall_distance = world.getWallDistanceForPos playerPos.plus botToCamera if wall_distance < 0.5 - # ____________________________________________________ apiercing walls - if (wall_distance < 0.2) + # ____________________________________________________ piercing walls + if wall_distance < 0.2 cameraPos = world.getInsideWallPosWithDelta cameraPos, 0.2 botToCamera = cameraPos.minus playerPos botToCameraNormal = botToCamera.normal() - rot_factor = 0.5 / (wall_distance-0.2) + rotFactor = 0.5 / (wall_distance-0.2) # ____________________________________________________ try view bot from behind # calculate horizontal angle between bot orientation and vector to camera @@ -254,7 +256,7 @@ class Player extends Bot if botToCameraNormal.dot(playerRight) > 0 horizontalAngle = -horizontalAngle - cameraPos = playerPos.plus Quaternion.rotationAroundVector(horizontalAngle / (rot_factor * 400.0), playerUp).rotate botToCamera + cameraPos = playerPos.plus Quaternion.rotationAroundVector(horizontalAngle / (rotFactor * 400.0), playerUp).rotate botToCamera botToCamera = cameraPos.minus playerPos botToCameraNormal = botToCamera.normal() @@ -262,7 +264,7 @@ class Player extends Bot # ____________________________________________________ finally, set the position @projection.setPosition cameraPos - + log 'cameraPos:', cameraPos # ____________________________________________________ refining camera orientation # slowly adjust look direction by interpolating current and desired directions @@ -282,6 +284,7 @@ class Player extends Bot @projection.setZVector newLookVector @projection.setXVector newRightVector @projection.setYVector newUpVector + log 'Player.getFollowProjection', @projection.getPosition() @projection # 0000000 0000000 000000000 000 0000000 000 000 @@ -513,9 +516,7 @@ class Player extends Bot # 000 000 000 000 000 000 000 000 000 # 0000000 000 0000000 000 0000000 000 000 000 - display: () -> - if world.getCameraMode() != world.CAMERA_INSIDE or world.getEditMode() - render() + step: (step) -> super step getBodyColor: () -> if world.getCameraMode() == world.CAMERA_BEHIND diff --git a/coffee/world.coffee b/coffee/world.coffee index e5f8b01..8d5b69f 100644 --- a/coffee/world.coffee +++ b/coffee/world.coffee @@ -34,13 +34,21 @@ class World extends Actor @levelList = [] @levelDict = [] - @speed = 5 + + @normals = [ + new Vector 1, 0, 0 + new Vector 0, 1, 0 + new Vector 0, 0, 1 + new Vector -1,0, 0 + new Vector 0,-1, 0 + new Vector 0, 0,-1 + ] constructor: (@view) -> super - @speed = 0.5 + @speed = 2.0 @screenSize = new Size @view.clientWidth, @view.clientHeight # log "view @screenSize:", @screenSize @@ -96,9 +104,9 @@ class World extends Actor @cells = [] @size = new Pos() @depth = -Number.MAX_SAFE_INTEGER - @camera_mode = World.CAMERA_BEHIND + # @camera_mode = World.CAMERA_BEHIND @camera_mode = World.CAMERA_INSIDE - @camera_mode = World.CAMERA_FOLLOW + # @camera_mode = World.CAMERA_FOLLOW @edit_projection = null @raster_size = 0.1 @@ -476,7 +484,7 @@ class World extends Actor toggle: (objectName) -> # toggles object with name objectName - Controller.startTimedAction(@getObjectWithName(objectName).getActionWithName("toggle")) + @startTimedAction(@getObjectWithName(objectName).getActionWithName("toggle")) escape: (self) -> # handles an ESC key event @@ -737,10 +745,19 @@ class World extends Actor Timer.event.triggerActions() Timer.event.finishActions() - @player.getProjection().apply @camera + @player.step step + @display() @sun.position.copy @camera.position @renderer.render @scene, @camera + display: () -> + # log "world.display #{@camera_mode}" + switch @camera_mode + when World.CAMERA_INSIDE then @projection = @player.getProjection() + when World.CAMERA_BEHIND then @projection = @player.getBehindProjection() + when World.CAMERA_FOLLOW then @projection = @player.getFollowProjection() + @projection.apply @camera + getTime: -> now().toFixed 0 setSpeed: (s) -> @speed = s getSpeed: -> @speed @@ -825,39 +842,32 @@ class World extends Actor insidePos = new Vector pos for w in [0..5] planePos = new Vector -0.5, -0.5, -0.5 - if w >= 3 then planePos.add size - - f = kRayPlaneIntersectionFactor pos, -@normals[w], planePos, @normals[w] - + if w >= 3 then planePos.add @size + f = Vector.rayPlaneIntersectionFactor pos, World.normals[w].neg(), planePos, World.normals[w] if f < delta - insidePos.add new Vector (delta-f)*@normals[w] - + insidePos.add World.normals[w].mul delta-f + log 'getInsideWallPosWithDelta', insidePos insidePos - # returns the distance to the next wall (positive or negative) - getWallDistanceForPos: (pos) -> - + getWallDistanceForPos: (pos) -> # distance to the next wall (positive or negative) min_f = 10000 for w in [0..5] planePos = new Vector -0.5, -0.5, -0.5 - if w >= 3 then planePos.add size - - f = kRayPlaneIntersectionFactor pos, -@normals[w], planePos, @normals[w] - + if w >= 3 then planePos.add @size + f = Vector.rayPlaneIntersectionFactor pos, World.normals[w].neg(), planePos, World.normals[w] + log "getWallDistanceForPos #{min_f} #{f}" min_f = absMin min_f, f + log "getWallDistanceForPos #{min_f}", pos min_f - # returns the distace to the next wall in direction rayDirection from rayPos (positive values only) - getWallDistanceForRay: (rayPos, rayDirection) -> - + getWallDistanceForRay: (rayPos, rayDirection) -> # distance to the next wall in rayDirection min_f = 10000 for w in [0..5] - planePos -0.5, -0.5, -0.5 - if w >= 3 then planePos.add size - - f = kRayPlaneIntersectionFactor rayPos, rayDirection, planePos, @normals[w] - + planePos = new Vector -0.5, -0.5, -0.5 + if w >= 3 then planePos.add @size + f = Vector.rayPlaneIntersectionFactor rayPos, rayDirection, planePos, World.normals[w] min_f = f if f >= 0.0 and f < min_f + log "getWallDistanceForRay #{min_f}", rayDirection min_f displayLights: () -> @@ -865,24 +875,15 @@ class World extends Actor lignt.display() getProjection: () -> - log "world.getProjection #{@camera_mode}" + # log "world.getProjection #{@camera_mode}" if not @projection switch @camera_mode when World.CAMERA_INSIDE then @projection = @player.getProjection() when World.CAMERA_BEHIND then @projection = @player.getBehindProjection() when World.CAMERA_FOLLOW then @projection = @player.getFollowProjection() @projection - - display: (mode) -> - log "display #{@mode}" - switch @camera_mode - when World.CAMERA_INSIDE then @projection = @player.getProjection() - when World.CAMERA_BEHIND then @projection = @player.getBehindProjection() - when World.CAMERA_FOLLOW then @projection = @player.getFollowProjection() - @projection.apply @camera - - playSound: (sound, pos, time) -> - log "World.playSound #{sound} #{time}", pos + + playSound: (sound, pos, time) -> # log "World.playSound #{sound} #{time}", pos # 000 000 00000000 000 000 # 000 000 000 000 000