Snippet Coordinate Cameras

uberfoop

~=Admiral Stukov=~
Reaction score
177
Coordinate Cameras

Version History:
7/21/09: Basic system posted
7/22/09: Updated with Toadcop's method for bypassing default terrain mapping
9/16/09: Updated to have better documentation and format
9/17/09: Updated to be more efficient

Requires:
-vJass

Code:
JASS:

//                   Coordinate Cameras
//                       By uberfoop
//
//
//  ->What is this?
//  It is a snippet with functions designed to allow the positioning
//  of the wc3 camera based on spatial coordinates instead of target
//  positions, distance to target, and what have you.
//  Functions use absolute z value.
//  They are instant and apply to all players.
//
//  ->Functions:
//
//  function SetCameraCoord takes real x, real y, real z,...
//  ...real azimuth, real vertical, real roll returns nothing
//  
//  x, y, and z are spatial coordinates of the camera.
//  azimuth is the horizontal rotation of the camera.
//  vertical is the vertical angle of the camera. For example,
//  '30' is 30 degrees up from paralell with the ground.
//  roll is the roll angle of the camera.
//  
//
//  function SetCameraCoordB takes real x, real y, real z,...
//  ...real azimuth, real vertical, real roll returns nothing
//
//  This is the same as SetCameraCoord for everything except vertical.
//  For vertical, this uses the angle down from the zenith. For example,
//  '30' is 60 degrees up from paralell with the ground.
//
//
//  function SetCameraCoordTarget takes real x, real y, real z,...
//  ...real fx, real fy, real fz, real roll returns nothing
//
//  x, y, and z are spatial coordinates of the camera.
//  fx, fy, and fz are spatial coordinates that the camera will face.
//  roll is the roll angle of the camera.

library CoordCameras
private function SetZ takes real z returns nothing
    set z = GetCameraField(CAMERA_FIELD_ZOFFSET)+z-GetCameraTargetPositionZ()
    call SetCameraField(CAMERA_FIELD_ZOFFSET,z,-.01)
    call SetCameraField(CAMERA_FIELD_ZOFFSET,z,.01)
endfunction

globals
    private real ccdist
    private real radazim
    private real radvert
endglobals

function SetCameraCoord takes real x, real y, real z, real azimuth, real vertical, real roll returns nothing
    set radazim = bj_DEGTORAD*azimuth
    set radvert = bj_DEGTORAD*vertical
    set ccdist = 100*Cos(radvert)
    call SetZ(z + 100*Sin(radvert))
    call SetCameraPosition(x + ccdist*Cos(radazim),y + ccdist*Sin(radazim))
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE,100,0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK,vertical,0)
    call SetCameraField(CAMERA_FIELD_ROTATION,azimuth,0)
    call SetCameraField(CAMERA_FIELD_ROLL,roll,0)
endfunction

function SetCameraCoordB takes real x, real y, real z, real azimuth, real vertical, real roll returns nothing
    set radazim = bj_DEGTORAD*azimuth
    set radvert = bj_DEGTORAD*vertical
    set ccdist = 100*Sin(radvert)
    call SetZ(z + 100*Cos(radvert))
    call SetCameraPosition(x + ccdist*Cos(radazim),y + ccdist*Sin(radazim))
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE,100,0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK,90 - vertical,0)
    call SetCameraField(CAMERA_FIELD_ROTATION,azimuth,0)
    call SetCameraField(CAMERA_FIELD_ROLL,roll,0)
endfunction

globals
    private real azim
    private real vert
endglobals

function SetCameraCoordTarget takes real x, real y, real z, real fx, real fy, real fz, real roll returns nothing
    set fx = fx - x
    set fy = fy - y
    set radazim = Atan2(fy,fx)
    set radvert = Atan2(fz - z,SquareRoot(fx*fx + fy*fy))
    set ccdist = 100*Cos(radvert)
    call SetZ(z + 100*Sin(radvert))
    call SetCameraPosition(x + ccdist*Cos(radazim),y + ccdist*Sin(radazim))
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE,100,0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK,bj_RADTODEG*radvert,0)
    call SetCameraField(CAMERA_FIELD_ROTATION,bj_RADTODEG*radazim,0)
    call SetCameraField(CAMERA_FIELD_ROLL,roll,0)
endfunction
endlibrary


[ljass]//===================================================[/ljass]


This is a group of functions which each can be used to set the position and rotation of the Warcraft 3 camera.

In Warcraft 3, the closest distance to camera target useable is 100, and thus you're always moving a camera around some point a notable distance away. This bypasses that by using some vector math to place the camera target in a location such that, with desired camera rotation applied, the camera viewing point is at a specific desired coordinate.
Note that with this system, 'z' denotes absolute z, not z offset from terrain. Additionally, these functions are instant and affect all players.

Functions:
JASS:
function SetCameraCoord takes real x, real y, real z, real a, real v, real roll returns nothing

x, y, and z are the coordinates that the camera viewer will be at. a is the azimuth, the horizontal angle that the camera will face. v is the vertical angle; for this function, it is relative to the x/y plane (ie, a value of 30 will tilt the camera 30 degrees up from the wc3 plane). Roll is the camera roll.

JASS:
function SetCameraCoordB takes real x, real y, real z, real a, real v, real roll returns nothing

Exactly the same as the last one except that rather than having v be the angle offset from the x/y plane, it's the angle offset from the vertical (ie, a value of 30 will be 30 degrees lower than straight up and 60 degrees up from the wc3 plane).

JASS:
function SetCameraCoordTarget takes real x, real y, real z, real fx, real fy, real fz, real roll returns nothing

The x,y,z and roll inputs work exactly like the other two. However, instead of inputting two angles, for this function you input a target coordinate (fx,fy,fz) that you want the camera to face.



Example:
JASS:
call SetCameraCoord(0,0,400,0,-45,0)

This will cause the camera to be 400 above the center of the map, facing eastward and diagonally down at the ground, with a roll of 0.


Example 2:
JASS:

scope spinningthings initializer Init
globals
    private real r = 0
endglobals

private function CALLBACK takes nothing returns nothing
    set r = r + 3
    if r > 360 then
        set r = r - 360
    endif
    //call SetCameraCoord(300*Cos(bj_DEGTORAD*r),300*Sin(bj_DEGTORAD*r),456,180+r,-15,r)
    //call SetCameraCoord(300*Cos(bj_DEGTORAD*r),300*Cos(bj_DEGTORAD*r),456,180+r,-15,r)
    //call SetCameraCoord(300*Cos(bj_DEGTORAD*r),500*Sin(bj_DEGTORAD*r),456,180+r,-15,r)
    //call SetCameraCoordTarget(300*Cos(bj_DEGTORAD*r),500*Sin(bj_DEGTORAD*r),456,0,0,356,r)

    //This next one is a little long, but I'm soooo glad I made it. The calculus on the angles is a little big.
    //call SetCameraCoord(800*Cos(bj_DEGTORAD*r),1300*Sin(bj_DEGTORAD*r),700 + 300*Cos(bj_DEGTORAD*r),bj_RADTODEG*Atan2(1300*Cos(bj_DEGTORAD*r),-800*Sin(bj_DEGTORAD*r)),bj_RADTODEG*Atan2(-300*Sin(bj_DEGTORAD*r),SquareRoot((-800*Sin(bj_DEGTORAD*r))*(-800*Sin(bj_DEGTORAD*r)) + (1300*Cos(bj_DEGTORAD*r))*(1300*Cos(bj_DEGTORAD*r)))),-45+20*Cos(2*bj_DEGTORAD*r))
endfunction


private function Actions takes nothing returns nothing
    call TimerStart(CreateTimer(),.03,true,function CALLBACK)
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterPlayerChatEvent(t,Player(0),"-",true)
    call TriggerAddAction(t,function Actions)
endfunction
endscope
If you put this in your map and player one says "-", the callback goes off.
The commented things in the callback will cause simple looping parametric movement around the map origin if uncommented.
 

quraji

zap
Reaction score
144
Nice functions. I just last night was doing a little camera thing and I couldn't for the life of me get good results trying to move the camera around...this is exactly what I needed. Good stuff, and +rep :D
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Updated just now with Toadcop's method for bypassing terrain mapping. It now demands that the exact absolute global z values be inputted rather than z-offset, but it positions the camera at the exact absolute z values rather than acting stupid when terrain heights change.
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Seems to work fine for me. Post what you're doing?



edit: In case anyone was looking at the example 2 I posted, I added a function at the bottom. It's length is kind of a joke, but the results are spectacular, and such kinds of movement should be much shorter when using non-trig parametric equations. It was actually really easy to throw together too, even if it does look long.
 

Viikuna

No Marlo no game.
Reaction score
265
edit.

Didnt read your code properly and suggested you that toadcops z height method you are already using lols.

Anyways, looks neat.
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
x, y, and z are the coordinates that the camera viewer will be at. a is the azimuth, the horizontal angle that the camera will face. v is the vertical angle; for this function, it is relative to the x/y plane (ie, a value of 30 will tilt the camera 30 degrees up from the wc3 plane). Roll is the camera roll.

Could you set the names of the variables to these to make it easier to understand (or at the very least comment above/below the function name so we can find this bit of information without having to look up this thread)?

I remember having the idea to create something similar to this awhile back (camera's that moved around like an eye, rather than around the source object (unit/location)), nice work. ;)
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Could you set the names of the variables to these to make it easier to understand (or at the very least comment above/below the function name so we can find this bit of information without having to look up this thread)?
Just added some documentation above all of the code with descriptions of each function, plus I made the angle parameter names better.

Also, I abused the new ljass tags in my post.

I remember having the idea to create something similar to this awhile back (camera's that moved around like an eye, rather than around the source object (unit/location)), nice work. ;)
:)
 

Jesus4Lyf

Good Idea™
Reaction score
397
Is Z in this system absolute Z or Z above the terrain? :)
For what player does SetCameraCoordTarget change the camera? And over any period of time?
JASS:
    local real a = bj_RADTODEG*Atan2(fy - y,fx - x)
    local real v = bj_RADTODEG*Atan2(fz - z,SquareRoot((fx - x)*(fx - x) + (fy - y)*(fy - y)))
    local real tz = GetZ(z + 100*Sin(bj_DEGTORAD*v))
    local real f = 100*Cos(bj_DEGTORAD*v)
    local real tx = x + f*Cos(bj_DEGTORAD*a)
    local real ty = y + f*Sin(bj_DEGTORAD*a)

Store radians and convert to degrees for the one time you use it as deg.

Edit:
You never use fx-x (or y or z same thing) by itself, so you should use private globals instead of locals and the first thing you do in your function should be [LJASS]set fx = fx-x[/LJASS] and so forth.

Why do you include the roll? Could let users do this on their own?

Aside from that, I think I really like this (but am yet to test it). Seems cool.
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Is Z in this system absolute Z or Z above the terrain? :)
For what player does SetCameraCoordTarget change the camera? And over any period of time?
-The functions use absolute z values.
-These are intended to be used like the natives, so they affect all players. Like those functions, unless setting a global real in a local player block causes a failcrash under all circumstances, using these within local blocks should be safe.
-The functions apply instantly.

JASS:
    local real a = bj_RADTODEG*Atan2(fy - y,fx - x)
    local real v = bj_RADTODEG*Atan2(fz - z,SquareRoot((fx - x)*(fx - x) + (fy - y)*(fy - y)))
    local real tz = GetZ(z + 100*Sin(bj_DEGTORAD*v))
    local real f = 100*Cos(bj_DEGTORAD*v)
    local real tx = x + f*Cos(bj_DEGTORAD*a)
    local real ty = y + f*Sin(bj_DEGTORAD*a)

Store radians and convert to degrees for the one time you use it as deg.
Updated, done a little differently in a way that should be slightly more efficient.

Edit:
You never use fx-x (or y or z same thing) by itself, so you should use private globals instead of locals and the first thing you do in your function should be [LJASS]set fx = fx-x[/LJASS] and so forth.
Agreed, except for the fz-z part, since it's only used once. Updated.


Why do you include the roll? Could let users do this on their own?
I could, but it is part of camera orientation and I found it handy to include in the call.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top