PDA

View Full Version : A "SL-like" camera for Blue Mars


Cale Vinson
07-11-2010, 11:21 AM
I'm going to continue to pretend that there is someone here interested in Blue Mars apart from myself. :)

The following is from a post to the Caledonia mailing-list, I hope people won't mind too much that I didn't redraft it.

================================================== =====

As part of my ongoing Blue Mars training program, I've managed to get a scripted-camera working that works in a similar way to the SL camera. I'm calling it a "Focal Camera" (FC).

When logged into Blue Mars, hitting space toggles you between the standard AR camera, and the FC (I toggle back and forwards a few times at the start of the youtube below). The standard UI is hidden whilst in FC mode.

In FC mode, a left click on a solid object immediately points the camera at that object. Note - Caledon trees are not solid. :-) Dragging with the right mouse held down changes your pitch and/or yaw as you rotate around the selected focal-point. Holding shift whilst right-dragging zooms you towards and away from the focal-point.

Demo video: http://www.youtube.com/watch?v=XwdYutBLwiM

Caveats: The focal-point is set by a ray-intersection with the world, so you pick up collisions between the ray and *physics-proxy* for the object you've hit, rather than the graphical representation of the object. Objects can disappear if you zoom in too close to them.

-------

Without wanting to to get too carried away, as a scripter I think this current project demonstrates a number of nice features of Blue Mars, particularly compared to SL.

a) We have a ray-collision function! (Yes, I gather that SL recently introduced one on the test-grid, but it should have been available years ago.)

b) We have complete access to to user mouse-and-keyboard input. We can monitor any and all keys as we like, and we know where on the screen the mouse is at all times.

c) The consequence of (a) and (b) is that we can build pretty much any sort of camera we want. Which is very much not the case in SL. If people cry "the camera in BM sucks" (as some have), my argument would be that the camera should be seen as UGC like anything else, and subject to improvement over time like any other element of UGC. Personally, I'd much rather have the tools available to craft our own systems, than having no choice beyond the options provided by the VW company .....

================================================== ======

And for the SC2 audience, my standard disclaimer applies. Yes, I'm rather excited by the relatively low-level and complete access we have to at least some of the components of Blue Mars, but I know there are still many show-stopper issues for a lot of people (eg., the pg-13 rating) which no amount of technical wizardry will overcome. And that's cool too. :)

Charlemagne Allen
07-12-2010, 10:20 AM
Interesting stuff, thanks...

:bump:

Cale Vinson
07-13-2010, 11:00 AM
I got some feedback on the camera above from members of the Caledonia email list. There was interest in using the camera to take high-quality fashion-shots in-world, with a need to be able to zoom in on any given feature as much as we liked. But the problem there was that I'd already noted that the entire AV could disappear if you attempted to zoom-in too close.

Read on for the next exciting installment ........ :)

================================================== ==

Quick update - yes, FOV is our friend. :-)

New video: http://www.youtube.com/watch?v=xN9eZlCUyyo

At the start of the video I grab a handy pillar to spin around by 180 degrees, then focus on the AV. The intent is to get as high a level of zoom on her face as possible. First, I "zoom" as I have been doing, by moving the camera closer to the focal-point. You'll note that I can get close-ish to her face, but at some point the entire AV gets clipped away. I then back off a little, and try my-just-added-this-night option of zooming by changing the field-of-view - and you'll note I can then zoom in very close to her face indeed.

My script restricts the set fov to user-defined limits. Current min-fov is five degrees. To simulate what life must be like on drugs, I set the max-fov to an excessively large 150 degrees - the final part of the video shows the rather trippy effect. :-) (Its interesting to note that the AV disappears at large fov values.)

So, to answer Mako's question - yes, by using a combination of camera-movement and camera-fov, I think we can pretty much get any level of zoom we want.

Dale Innis
07-13-2010, 11:50 AM
Oh c'mon, max-fov should be 360! (Or 180, if that's in either direction.)

This is quite the coolness! Am I right that it's mostly client-side, so that it could be done for SL by client patches? (Rather than requiring getting the Lindens to do something?) And when we eventually get a viewer with client-side scripting... :)

Just what did you write, and in what language, to make this new camera?

Cale Vinson
07-14-2010, 11:31 PM
Oh c'mon, max-fov should be 360! (Or 180, if that's in either direction.)


Don't think I haven't seen through your dirty little game here Innis !!!!!!!!111!!!!!

I mean, *everyone* knows that if you try to set a 360 degree fov it causes a geometric singularity, and a resultant implosion/meltdown on your GPU card. :argh:


This is quite the coolness! Am I right that it's mostly client-side, so that it could be done for SL by client patches? (Rather than requiring getting the Lindens to do something?) And when we eventually get a viewer with client-side scripting... :)


Its all client-side, yes. I would imagine you could do it in SL via a suitably modified 3rd-party client, but that then brings up the interesting question of what is "part" of "SL" and what is not.


Just what did you write, and in what language, to make this new camera?

That's quite a large-scope question. :) Let me attempt an initial answer, then you could follow-up as needed.

I start with the developer-tools on my PC, together with a copy of Desmond Shang's "Caledonia" city (which I use for testing because I'm too lazy to have done even the smallest development on my own outpost. :D ).

To the Caldedonia directory structure I add three files: an "ent" file, a file with a single LUA script, and a xml-file containing an "actionmap".

The "ent" file is a trivial one-liner - it just points to the location of the LUA script. But its the thing that the City-Editor reads on start-up to find the list of available entities. You can then add this entity (and hence its associated script) to a city-map by drag-dropping in the city editor.

"Actionmap" files are xml files that define the relationships between input (key, mouse) events and, well, "actions" that the LUA script will detect (more later).

Here's an example from my system:


<action name="CV_toggleCamera" onPress="1">
<key name="space" />
</action>
<action name="CV_hud_mouseClick" onPress="1">
<key name="mouse1" />


Pressing the space-bar will create a "CV_toggleCamera" action that a LUA script will detect. The system runs multiple actionmaps simultaneously, and you can make then active/inactive dynamically, from script. The reason why my AV doesn't attempt to move when I click on things in focal-mode is that the AR-defined "player" actionmap is disabled when I enter focal-mode, and re-enabled when I leave it.

As in SL, the BM LUA scripts are largely event-driven. There's an event-handler, "OnAction" to pick up actions defined in actiomaps.

Eg: here's the bit of the code that picks-up the camera-toggle action.


function CV_FocalCamera:OnAction(action, mode)

if (action == "CV_toggleCamera") then
if (self.focalMode) then
self:Stop()
self.focalMode = false
CV_EnableCompActionMaps()
else
self:Start()
self.focalMode = true
CV_DisableCompActionMaps()
end
end


'focalMode' is just a flag to keep track of what camera-mode we're in. There are routines to enable/disable the AR "competing" actionmaps.

BM supports the existence of multiple cameras ("views") simulataneously - you can then switch between then dynamically via script. That's what's done in those "start" / "stop" functions.

Eg:


function CV_FocalCamera:Start()
self:Activate(1)

self.origView = Game.GetActiveView()
self.origFov = Game.GetViewFov(self.origView)
Game.SetViewFov(self.view, self.origFov)
Game.SetActiveView(self.view)

self.controlDown = false
self.focalPos = nil
self.rightMouseDown = false
self.shiftDown = false

ARVirtualWorld.Instance:HideHUD()

local avatar = MMO:GetLocalAvatarEntity()
self.pos = SumVectors(avatar:GetWorldPos(), ScaleVector(g_Vectors.up,2))
self:SetWorldPos(self.pos)
self.angles = avatar:GetWorldAngles()
self:SetWorldAngles(self.angles)
end



Scripts can "activate" themselves. This is something that I don't think has an analogue in SL - it introduces a new event-handler "OnUpdate" which is fired for each frame executed on the client.

Here's the top of my Update-handler:


function CV_FocalCamera:OnUpdate(deltaTime)

if (System.HasFocus()) then
if (self.rightMouseDown) and (self.focalPos) then

self.mouseDx, self.mouseDy = CV_UpdateMouse()




"CV_UpdateMouse" is:


function CV_UpdateMouse()
local cx = math.floor(0.5*HUD.GetWidth())
local cy = math.floor(0.5*HUD.GetHeight())

local wx,wy = System.GetWindowMouse()
System.SetWindowMouse(cx, cy)

local dx = wx - cx
local dy = wy - cy

local dx = clamp(dx, -cx, cx)
local dy = clamp(dy, -cy, cy)

return dx, dy
end



Note that we are thus able to get the mouse-position every-frame, and measure its displacement from frame-to-frame (I don't recall SL having this sort of funtionality).

Further down in the "Update" handler we have:


if (self.shiftDown) then

-- Moving towards and away from the focal point.

FastDifferenceVectors(g_Vectors.temp_v1, self.focalPos, self.pos)
local maxDist = LengthVector(g_Vectors.temp_v1)
local dist = self.radialSpeed*deltaTime*(-self.mouseDy)
dist = __min(dist, maxDist - self.minApproachDist)
NormalizeVector(g_Vectors.temp_v1)
ScaleVectorInPlace(g_Vectors.temp_v1, dist)
FastSumVectors(self.pos, self.pos, g_Vectors.temp_v1)
self:SetWorldPos(self.pos)



Which is fairly straightfoward stuff. Take a vector from your (here, "self" is the camera) position to the "focal point" position. Move a distance along that vector, proportional to the mouse-sensitivity (constant), the time to render the frame, and the amount of up-down mouse-motion. Limit the distance moved so you don't get too close, then, finally, move the camera.

=======

Hope that was useful - if not, ask me some more questions. :)