#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Need some help making a look at function.

Posts: 51

Not too good at math, and i've been struggling to come up with a function to have a camera turn to a particular point. I figured I'd have to get the direction the camera is currently facing, and then some how calculate the direction it supposed to be at so I can use quat.fromToRotation()? I don't know if i'm on the right track, but if anybody has done this before or wants to attempt it, help me out!

Something like lookAt(objectToRotate, position)?

Tagged:

• edited January 18 Posts: 51

This is what I have so far, but it's definitely not correct lol

``````function cameraLook(look)
local cam = ACTIVESCENE.camera:get(craft.camera)
local camPos, camDir = cam:screenToRay(vec2(WIDTH/2,HEIGHT/2))
local forward = quat.lookRotation(camDir,vec3(0,1,0)):angles()
return quat.fromToRotation(forward,look):angles()
end``````
• Posts: 2,689

@John @dave1707 - thought occured to me with this thread - how does the Craft camera relate to the Codea camera ? Are both configrable through a single routine ?

• Posts: 412

@arismoko This is what I’ve used in the past but not sure if it’s what you’re looking for.

The `setDirection` function may be useful.

``````Transform = class()

function Transform:init()
self.pos = vec3(0, 0, 0)
self.rot = vec3(0, 0, 0)
self.scl = vec3(1, 1, 1)
end

function Transform:setDirection(dir, up)
dir.z = -dir.z
local q = quat.lookRotation(dir:normalize(), up or vec3(0, 1, 0))
self.rot = q:angles()
end

function Transform:getDirection()
return vec3(
math.cos(self.rot.x) * math.sin(self.rot.y),
math.cos(self.rot.x) * math.cos(self.rot.y),
math.sin(self.rot.x)
)
end

function Transform:getMatrix()
resetMatrix()

translate(self.pos.x, self.pos.y, self.pos.z)
rotate(self.rot.y, 0, 1, 0)
rotate(self.rot.x, 1, 0, 0)
rotate(self.rot.z, 0, 0, 1)
scale(self.scl.x, self.scl.y, self.scl.z)

return modelMatrix()
end

function Transform:getAsViewMatrix()
resetMatrix()

rotate(self.rot.y, 0, 1, 0)
rotate(self.rot.x, 1, 0, 0)
rotate(self.rot.z, 0, 0, 1)
translate(-self.pos.x, -self.pos.y, -self.pos.z)

return modelMatrix()
end
``````
• Posts: 762

@arismoko This is probably something I should have built-in to the entity class. For now I've made this:

``````    function lookAt(entity, target, up, t)
local dir = (entity.position - target):normalize()
local rot = quat.lookRotation(-dir, up or vec3(0, 1, 0))
if t and t > 0 then
entity.rotation = entity.rotation:slerp(rot, t)
else
entity.rotation = rot
end
end
``````

This will point an entity towards a given target (I have to negate the direction to make the camera 'see' the position. It also lets you set an optional up value and t is used for interpolation if you want to turning to happen over time

@Bri_G Craft's camera system is separate to Codea's normal camera functionality. In Codea 4 I've unified these more so that you can use the camera class by itself or in a scene

• Posts: 51

@John Thanks a lot! That’s awesome! (:

• Posts: 2,689
@John - thought that could be the case. Bravo on unification in 4. Thanks.
• edited January 20 Posts: 9,977

I took one of my examples and stripped it down to just a camera and sphere. I added code for the look at calculations. I don’t understand any quat stuff, but I got it to work anyways. When the program starts, the camera and red sphere are randomly placed somewhere in a 400x400x400 area. When you tap the screen, the camera will rotate to look at the sphere. You can use the sliders to change the x,y,z positions of the camera and sphere. Tap the screen again to point the camera at the sphere. The x,y,z positions are displayed along with the camera quat values and camera to sphere distance.

``````viewer.mode=STANDARD

function setup()
print("slide window down")
assert(craft, "Please include Craft as a dependency")
parameter.integer("cxPos",-200,200,math.random(-200,200))
parameter.integer("cyPos",-200,200,math.random(-200,200))
parameter.integer("czPos",-200,200,math.random(-200,200))
parameter.integer("sxPos",-200,200,math.random(-200,200),createSphere)
parameter.integer("syPos",-200,200,math.random(-200,200),createSphere)
parameter.integer("szPos",-200,200,math.random(-200,200),createSphere)
direction=vec3(0,0,0)
scene = craft.scene()
skyMaterial = scene.sky.material
skyMaterial.horizon = color(0, 203, 255, 255)
createSphere()
fill(255)
end

function update(dt)
scene:update(dt)
scene.camera.position=vec3(cxPos,cyPos,czPos)
end

function draw()
background(0)
update(DeltaTime)
scene:draw()
dist()
text("Sphere position  x="..sxPos.."  y="..syPos.."  z="..szPos,WIDTH/2,HEIGHT-50)
text("Camera position  x="..cxPos.."  y="..cyPos.."  z="..czPos,WIDTH/2,HEIGHT-100)
text("Camera quat direction  x="..direction.x.."  y="..direction.y.."  z="..direction.z ,WIDTH/2,HEIGHT-125)
text("Distance from camere to sphere  "..distance,WIDTH/2,HEIGHT-150)
text("Tap screen to point camera at sphere",WIDTH/2,HEIGHT-250)
text("Move sliders to change camera and sphere positions",WIDTH/2,HEIGHT-280)

end

function createSphere()
if sphere then
sphere:destroy()
end
sphere=scene:entity()
sphere.model = craft.model.icosphere(2,3)
sphere.position=vec3(sxPos,syPos,szPos)
sphere.material = craft.material(asset.builtin.Materials.Specular)
sphere.material.diffuse=color(255,0,0)
end

function touched(t)
if t.state==BEGAN then
rotateCamera()
end
end

function rotateCamera()
local diff=-(scene.camera.position-sphere.position):normalize()
direction=quat.lookRotation(diff,vec3(0,1,0))
scene.camera.rotation=direction
end

function dist()
c,s=scene.camera.position,sphere.position
distance=math.sqrt((c.x-s.x)^2+(c.y-s.y)^2+(c.z-s.z)^2)
end
``````
• edited January 20 Posts: 9,977

As I mentioned above, I don’t understand the quat stuff, but I’ve been getting it to work. Here’s an example that uses the slerp function. It took awhile before I knew what it was supposed to do, but it works. This code creates 600 random green spheres just for reference, 1 random red sphere, and a randomly placed camera. When you tap the screen, the slerp function will rotate the camera at varying speeds to center the red sphere on the screen. To restart, just tap the restart icon again.

``````viewer.mode=FULLSCREEN

function setup()
assert(craft, "Please include Craft as a dependency")
scene = craft.scene()
skyMaterial = scene.sky.material
skyMaterial.horizon = color(0, 203, 255, 255)

-- 600 green spheres
for z=1,600 do
createSphere(math.random(-200,200),math.random(-200,200),
math.random(-200,200),color(0,255,0))
end

-- random red sphere
sxPos=math.random(-200,200)
syPos=math.random(-200,200)
szPos=math.random(-200,200)
createSphere(sxPos,syPos,szPos,color(255,0,0))

-- random camera position
cxPos=math.random(-200,200)
cyPos=math.random(-200,200)
czPos=math.random(-200,200)

direction=vec3(0,0,0)
fill(255)
end

function update(dt)
scene:update(dt)
scene.camera.position=vec3(cxPos,cyPos,czPos)
if rot then
rotateCamera(.01)
end
end

function draw()
background(0)
update(DeltaTime)
scene:draw()
text("Red sphere position  x="..sxPos.."  y="..syPos.."  z="..szPos,WIDTH/2,HEIGHT-50)
text("Camera position  x="..cxPos.."  y="..cyPos.."  z="..czPos,WIDTH/2,HEIGHT-100)
text("Camera quat direction  x="..direction.x.."  y="..direction.y.."  z="..direction.z ,WIDTH/2,HEIGHT-150)
text("Tap screen to point camera at red sphere",WIDTH/2,HEIGHT-200)
end

function createSphere(x,y,z,c)
sphere=scene:entity()
sphere.model = craft.model.icosphere(2,3)
sphere.position=vec3(x,y,z)
sphere.material = craft.material(asset.builtin.Materials.Specular)
sphere.material.diffuse=c
end

function touched(t)
if t.state==BEGAN then
rot=true
end
end

function rotateCamera(v)
local diff=-(scene.camera.position-sphere.position):normalize()
direction=quat.lookRotation(diff,vec3(0,1,0))
scene.camera.rotation=scene.camera.rotation:slerp(direction,v)
end
``````
• edited January 20 Posts: 2,689

@dave1707 code above crashed on me after running several times then scrolling Codea off screen to the iOS apps screen and seconds later got Codea crash alert.

Edit: so far unable to reproduce it.

• edited January 20 Posts: 9,977

@Bri_G It doesn’t surprise me if it crashes after a few times. I’m creating a lot of entities each time and Codea might not be cleaning up with restarts. Maybe a collectgarbage() in draw would help it it continues. This was mostly just for show and needs to be coded differently if used for real.