• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

terrible annoying camera problem

Status
Not open for further replies.
Level 3
Joined
Mar 3, 2009
Messages
34
I created a camera system, in which the camera is locked on a specific target an freely rotatable.
But when the target unit comes too close to a steep cliff, the camera source moves down under the point where the unit is standing (see screenshot).

Can anyone help me, to fix this problem?

Btw.: Unfortunately i'm really not proficient in Jass, so i would prefer a solution in GUI.
 

Attachments

  • WC3ScrnShot_102709_223947_01.jpg
    WC3ScrnShot_102709_223947_01.jpg
    160 KB · Views: 169
Level 3
Joined
Mar 3, 2009
Messages
34
I simply locked the camera to a target unit. That means, the camera should keep the height distance to the target, where ever it moves.
But it seems, that the height of the unit is not equal to the height of the point, where the unit is standing.
 
Level 3
Joined
Mar 3, 2009
Messages
34
Isn't there any easier way, to get the height of the point, where an unit is standing? Then i would only need a function, to adjust the offset of the camera.
 
Level 10
Joined
May 26, 2005
Messages
194
First of all, I lookad at OppiCam.

It does not seem to do what B.O.B. wants to. OppiCam simply ignores the fact that Warcraft does not simply use Camera Height = GetLocationZ(P) + Custom Offset. Instead it uses a grid with (pre?)calculated camera heights and interpolates the height between them. Camera Height = InterpolatedCamOffset(P) + Custom Offset.

http://www.hiveworkshop.com/forums/jass-functions-413/getcamoffset-131434/
This is my try to fix that problem. It does not work with water (impossible to use GetLocationZ(p) on, it will return the water surface but the cam system uses the ground), nor does it work with doodads affecting the camera height (Something like overfly-height in the object editor, has to be set to zero then). Besides that, i did not try to get it to work near the map border, as i simply did not need it. Maybe I will work on the functions later, because it seems like they might be useful for someone, and even more useful when they work correctly.

So, back to the thread:
You are using GUI? So I assume that you are not using the newGen-Editor... The script is done in vJass so you would need the newGen-Editor to use it.
Download it, or otherwise wait for a non-newGen version (tell me that you would like me to convert it and then wait...).

In case you install newGen or already have it installed, then you can simply create a new trigger and convert it to custom text (somewhere in the menu). Then remove all the code displayed in the custom text box and paste all the code from library to endlibrary. You are done.
Now you can use the code like this: GetCamOffset(x,y)
or in GUI:

add globals tempLoc and tempOffset

[GUI] Set tempLoc = <your location>
[GUI] Custom Script: "set udg_tempOffset = GetCamOffset(GetLocationX(udg_tempLoc),GetLocationY(udg_tempLoc))"
<now do whatever you want with tempOffset, for example:>
[GUI] Camera - Set Camera Z Offset to <real height> - tempOffset
<and clean the location so it does not leak:>
[GUI] Custom Script: call RemoveLocation(udg_tempLoc)

<real height> does not depend on the terrain height. So <real height> = 1000 is always 1000. If your terrain height is 0, then the cam will be 1000 on top of it... If your terrain height is 1000, then the cam will be on ground level.

If you want to use it for offsets relative to the terrain, then add "-GetLocationZ(udg_tempLoc)" behind the first Custom Script.


by the way, udg_ stands for user declared global


Hope this helped. However, keep in mind that flying units arent flying at the same height all the time, either. Their flight pathes are "flattened" a bit, and as far as i know theres also a grid used for it. It may be easy to add to the code above as soon as you have some values, but currently i dont have those.
(I already had that problem with flying units once... so maybe i will work on it, but dont know)

All in all you see, this can only be used with restrictions... but its the best way i know of, and in my flight simulator it worked fine.


EDIT: Seems like i dont have the time to work on that code, sorry... If you want to use it without vJass (newGen), maybe someone will translate it for you... but as it is using a 64k 2d array, this would be annoying to translate. better use newGen
 
Last edited:
Level 3
Joined
Mar 3, 2009
Messages
34
Fu*$§%#

I tried it out, but now, i believe, i missunderstood your system (i'm so stupid:gg:).
The problem is following: The function "GetLocationZ(position of your unit)" doesn't return the correct height, where the unit's feet are touching the ground's surface - but this would be exactly the value i need, to keep the centered unit in the camera field, regardless of their position on my map.

And this is not possible with your GetCamOffset(x,y) - am i right?:confused:
 
Level 10
Joined
May 26, 2005
Messages
194
I dont know what you need...

but if its just the ground height, then use this:

Code:
    function Round takes real r returns integer
        if r>0. then
            return R2I(r+.5)
        endif
        return -R2I(-r+.5)
    endfunction

    function GetTerrainZ takes real x, real y returns real
        call MoveLocation(udg_TempLoc,x,y)
        return GetLocationZ(udg_TempLoc)
    endfunction

    function GetSurfaceZ takes real x, real y returns real
        local real xLo = Round(x/128.-.5)*128.
        local real yLo = Round(y/128.-.5)*128.
        local real xHi = xLo+128.
        local real yHi = yLo+128.
        local real baseZ
        if x-xLo+y-yLo>128. then
            set baseZ = GetTerrainZ(xHi,yHi)
            return baseZ+((xHi-x)*(GetTerrainZ(xLo,yHi)-baseZ)+(yHi-y)*(GetTerrainZ(xHi,yLo)-baseZ))/128.
        endif
        set baseZ = GetTerrainZ(xLo,yLo)
        return baseZ+((x-xLo)*(GetTerrainZ(xHi,yLo)-baseZ)+(y-yLo)*(GetTerrainZ(xLo,yHi)-baseZ))/128.
    endfunction


however, the difference between GetSurfaceZ and GetTerrainZ is very small, i doubt this is what you were looking for


udg_TempLoc is a global location variable. you have to create a location and save it into that variable at startup


EDIT: I am almost sure GetCamOffset is what you need... use this as "the height of the point where the unit is standing" to adjust the camera height

the camera target position z will then be = GetCamOffset(x,y) + CAMERA_FIELD_ZOFFSET
the unit position z will be = GetTerrainZ(x,y) + GetUnitFlyHeight(U)

you want the camera Z to be equal to the unit's Z, which means:
GetCamOffset(x,y) + CAMERA_FIELD_ZOFFSET = GetTerrainZ(x,y) + GetUnitFlyHeight(U)

Solving for CAMERA_FIELD_ZOFFSET, which is what you can adjust:
CAMERA_FIELD_ZOFFSET = GetTerrainZ(x,y) + GetUnitFlyHeight(U) - GetCamOffset(x,y)

Im pretty sure that is what you want (which by the way is the same as explained above, just in other words)

GetUnitFlyHeight(U) is 0 for ground units. If you have floating units then this will get the correct position. For actual flying units, this does not work unfortunately. And again: No Doodads affecting the camera, No water, Enough distance to the map border
 
Last edited:
Level 3
Joined
Mar 3, 2009
Messages
34
I think, the function GetSurfaceZ is something, I really need.
But somehow following line of custom script causes problems:

set udg_tempOffset = GetTerrainZ(GetLocationX(udg_TempLoc) , GetLocationY(udg_TempLoc))

I used your code for the ground height exactly like your GetCamOffset function, but the setting of the tempOffset variable doesn't work this way.
I don't know, what's wrong about this, but the JassHelper says, that the function GetTerrainZ is not declared.

What i've done wrong?
 
Level 10
Joined
May 26, 2005
Messages
194
sorry, but i cannot find that code anywhere...

are you sure it isnt GetCamOffset()?

Otherwise... In my code, GetTerrainZ() is the same as GetLocationZ() except it takes coordinates instead of a location.
(It then moves a global location to that coordinates and uses GetLocationZ())

in that case it would be the same as GetLocationZ(udg_TempLoc)
 
Level 3
Joined
Mar 3, 2009
Messages
34
Hm, i think it is not the GetCamOffset ^^.

You see, the problem is following:

When you take a look on the attachend picture, you can see the difference between the ground surface and the line, where the camera moves along, while following the target unit, which moves from point A to F.
And now i need a function, with which i can set the camera offset to (B-B'), (C-C'), etc.

Maybe, this function is included in your GetCamOffset?
 

Attachments

  • camera movement.jpg
    camera movement.jpg
    31.6 KB · Views: 114
Level 10
Joined
May 26, 2005
Messages
194
thats exactly what GetCamOffset is used for...

just use it as described...

GetCamOffset() returns B' (when Zoffset = 0)
GetLocationZ() returns B

so you need to increase the height of your cam by (B-B') to be at B where your cam would normally be at B'.
means: ZOffset = GetLocationZ() - GetCamOffset()

now let me quote my first post:
[GUI] Custom Script: "set udg_tempOffset = GetCamOffset(GetLocationX(udg_tempLoc),GetLocationY(udg_tempLoc))"
<now do whatever you want with tempOffset, for example:>
[GUI] Camera - Set Camera Z Offset to <real height> - tempOffset

if you still do not manage to do this... simply upload the map, its a job of a few seconds to add this when i know where....
 
Level 3
Joined
Mar 3, 2009
Messages
34
YES, BABY!

Could someone bring a medal for this guy (a really great one :grin: )?

No kidding! I can't give as much +Rep as you deserve. This problem has completely demotivated me but your support has really, really, really helped me :thumbs_up: !
If anytime i can finish my map, you will get the first credits of all!

Thanks a lot!
 
Status
Not open for further replies.
Top