Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    3D position to screen position, screen position to 3D position

    Functions
    2
    2
    243
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mozipha
      mozipha last edited by

      Here's some code for translating 3D positions to screen positions and screen positions to 3D positions. It's a bit involved because it needs matrix math, but I've found it extremely useful.

      Main functions:

      // Projects world vector to screen postion.
      function worldPosToScreenPos(_worldPos, _camFwd, _camUp, _camPos, _camFov, _scrW, _scrH)
      	var screenPos = {float_min, float_min}
      	var nearClip = 0.25
      	var camPoint = worldVecToLocalVec(_worldPos, _camFwd, _camUp, _camPos)
      	
      	if camPoint.z >= nearClip then
      		var height = 2 * tan(_camFov * 0.5)
      		var width = height * (_scrW / _scrH)
      		
      		var posX = (camPoint.x / camPoint.z) / width
      		var posY = (camPoint.y / camPoint.z) / height
      		
      		posX += (_scrW * 0.5) / _scrW
      		posY += (_scrH * 0.5) / _scrH
      		
      		posX = (1 - posX) * _scrW
      		posY = (1 - posY) * _scrH
      		screenPos = {posX, posY}
      	endif
      return screenPos
      
      // Projects screen position to world vector.
      function screenPosToWorldPos(_scrPos, _zDepth, _camFwd, _camUp, _camPos, _camFov)
      	var posX = (_scrPos.x / gwidth() - 1) * -1
      	var posY = (_scrPos.y / gheight() - 1) * -1
      	
      	posX -= (gwidth() * 0.5) / gwidth()
      	posY -= (gheight() * 0.5) / gheight()
      	
      	var height = 2 * tan(_camFov * 0.5)
      	var width = height * (gwidth() / gheight())
      	
      	var pointX = posX * width * _zDepth
      	var pointY = posY * height * _zDepth
      return localVecToWorldVec({pointX, pointY, _zDepth}, _camFwd, _camUp, _camPos)
      

      Helper functions:

      // Remaps a world vector as a local vector.
      function worldVecToLocalVec(_vec, _locFwd, _locUp, _locPos)
      	_vec -= _locPos
      	_locFwd = axisRotVecBy(_locFwd, _locUp, 90)
      	var r = cross(_locFwd, _locUp)
      	
      	// Calculate inverse matrix	
      	var minFwd = {_locUp.y * r.z - r.y * _locUp.z, 
      		(_locUp.x * r.z - r.x * _locUp.z) * -1, 
      		_locUp.x * r.y - r.x * _locUp.y}
      	var minUp = {(_locFwd.y * r.z - r.y * _locFwd.z) * -1, 
      		_locFwd.x * r.z - r.x * _locFwd.z, 
      		(_locFwd.x * r.y - r.x * _locFwd.y) * -1}
      	var minR = {_locFwd.y * _locUp.z - _locUp.y * _locFwd.z, 
      		(_locFwd.x * _locUp.z - _locUp.x * _locFwd.z) * -1, 
      		_locFwd.x * _locUp.y - _locUp.x * _locFwd.y}
      	var adjFwd = {minFwd.x, minUp.x, minR.x}
      	var adjUp = {minFwd.y, minUp.y, minR.y}
      	var adjR = {minFwd.z, minUp.z, minR.z}
      	var det = 1 / (_locFwd.x * minFwd.x + _locUp.x * minUp.x + r.x * minR.x)
      	var invFwd = det * adjFwd
      	var invUp = det * adjUp
      	var invR = det * adjR
      	
      	var newVec = changeVecSpace(_vec, invFwd, invUp, invR, _locPos * -1)
      	newVec += _locPos
      return newVec
      
      // Remaps a local vector as a world vector.
      function localVecToWorldVec(_vec, _locFwd, _locUp, _locPos)
      	var newVec = changeVecSpace(_vec, _locFwd, _locUp, cross(_locUp, _locFwd), {0, 0, 0})
      	newVec += _locPos
      return newVec
      
      // Rotates 3D vector _v around 3D vector _axis by _deg degrees.
      function axisRotVecBy(_v, _axis, _deg)
      	// Euler-Rodrigues rotation formula
      	var halfDeg = _deg / 2
      	var w = _axis * sin(halfDeg)
      	var crossWV = cross(w, _v)
      return _v + 2 * cos(halfDeg) * crossWV + 2 * cross(w, crossWV)
      
      // Remaps a 3D vector to a different context.
      function changeVecSpace(_vec, _newFwd, _newUp, _newR, _newPos)
      	var mapped = {0, 0 ,0}
      	mapped.x = _vec.x * _newFwd.x + _vec.y * _newUp.x + _vec.z * _newR.x + _newPos.x
      	mapped.y = _vec.x * _newFwd.y + _vec.y * _newUp.y + _vec.z * _newR.y + _newPos.y
      	mapped.z = _vec.x * _newFwd.z + _vec.y * _newUp.z + _vec.z * _newR.z + _newPos.z
      return mapped
      
      1 Reply Last reply Reply Quote 4
      • Spacemario
        Spacemario F last edited by

        This is awesome, thanks for posting! I've tried to figure out how to do this myself on past occasions, and gave up-- my math skills aren't the best.

        1 Reply Last reply Reply Quote 1
        • First post
          Last post