Jump to content

Get perfect positions based on rotation


Recommended Posts

Hello!

I am working on a "low-quality" way of light shadows, working with dx functions. I want to use it for my vehicle system. I have a problem with this function's position calculations. I would like to make the shadow always rotate in the direction as the attached element, in this case the vehicle. The function uses dxDrawMaterialLine3D drawing function, so I guess I would have to get the left and the right side of the element (vehicle), and get a rotation based on that, and then use math.cos and math.sin? Maybe, I am not so sure, I was trying something like this but it was not working.

Here's the part of the code mentioned:

local matching = attachedGroundLightShadows[data.lightShadow]
if matching then
  local elementX, elementY, elementZ = getElementPosition(matching.element)
  local rx, ry, rz = getElementRotation(matching.element)
  local facez = getGroundPosition(elementX, elementY, elementZ + 5000000)
  local x, y, z = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y, facez)

  if elementZ <= fixedGroundPosition+2 then
    dxSetBlendMode("add")
    dxDrawMaterialLine3D(worldX, worldY-data.size, fixedGroundPosition, worldX, worldY+data.size, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
    dxSetBlendMode("blend")
  end
else
  dxSetBlendMode("add")
  dxDrawMaterialLine3D(worldX, worldY-data.size, fixedGroundPosition, worldX, worldY+data.size, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
  dxSetBlendMode("blend")
end

And here's the current results:

This would be the good rotation for the image:

WAo8oz8.jpg

But the problem is that the image always has the same rotation, doesn't matter what's the vehicle's rotation:

1XRDwiV.jpg

XF6gveM.jpg

I would like to ask for help with the position and rotation calculations for this script, I don't know how to fix it!

Link to comment

faceTowardX/Y/Z: The position the front of the line should face towards. If this is not set, the camera position is used, so the front of the line faces toward the camera.

Try putting the vehicle position here.

 

Also

worldX, worldY-data.size

This is wrong, give me a moment and I'll write the correction

local matching = attachedGroundLightShadows[data.lightShadow]

if matching then
  local elementX, elementY, elementZ = getElementPosition(matching.element)
  local rx, ry, rz = getElementRotation(matching.element)
  local facez = getGroundPosition(elementX, elementY, elementZ)
  local xa, ya = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y-data.size, facez)
  local xb, yb = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y+data.size, facez)

  if elementZ <= fixedGroundPosition+2 then
    dxSetBlendMode("add")
    dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), elementX, elementY, elementZ)
    dxSetBlendMode("blend")
  end
else
  dxSetBlendMode("add")
  dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), elementX, elementY, elementZ)
  dxSetBlendMode("blend")
end

Give this a try (I'm not 100% certain it's what you want due to some unclearly defined variables though)

Edited by CodyJ(L)
Link to comment

This is not working out really well. Here's my full code, it would be awesome if you could help me!

Client:

local lightShadowVisibleDistance = 50
--local tailLightShadow = dxCreateTexture("files/images/groundLightShadow.png")
local lightShadowTypes = {
	["pointlight"] = dxCreateTexture("files/images/pointlight.png"),
	["taillight"] = dxCreateTexture("files/images/taillight.png"),
}

local groundLightShadows = {}
local attachedGroundLightShadows = {}

function createLightShadow(x, y, z, shadowType, size, r,g,b,a)
	local vehicleLightShadow = createElement("vehicleLightShadow")
	
	local groundPosition = getGroundPosition(x, y, z)
	setElementPosition(vehicleLightShadow, x, y, groundPosition+0.03)
	
	if not r then r = 255 end
	if not g then g = 255 end
	if not b then b = 255 end
	if not a then a = 255 end
	
	if not size then size = 2 end
	
	if not shadowType then shadowType = "normal" end
	
	local array = {}
	
	array.color = {r,g,b,a}
	array.size = size
	
	--local renderTarget = dxCreateRenderTarget(512, 512, true)
	
	--[[dxSetRenderTarget(renderTarget, true)
	local width, height = dxGetMaterialSize(renderTarget)
	dxSetBlendMode("add")
	dxDrawImage(width, height, width-width*2, height-height*2, tailLightShadow, 0, 0, 0, tocolor(255,255,255,255))
	dxSetBlendMode("blend")
	dxSetRenderTarget()]]
	
	--array.texture = renderTarget
	
	--if array.texture and isElement(array.texture) then
	--	setElementParent(array.texture, vehicleLightShadow)
	--end
	
	array.lightShadow = vehicleLightShadow
	array.lightShadowType = shadowType
	
	groundLightShadows[vehicleLightShadow] = array
	return vehicleLightShadow
end

function attachGroundLightShadow(lightShadow, element, pos)
	attachedGroundLightShadows[lightShadow] = { lightShadow = lightShadow, element = element, pos = pos }
	addEventHandler("onClientElementDestroy", lightShadow, function() attachedGroundLightShadows[lightShadow] = nil end)
	addEventHandler("onClientElementDestroy", element, function() attachedGroundLightShadows[lightShadow] = nil end)
	return true
end

local function getPositionInFront(element,meters,component) 
   local x,y,z = getVehicleComponentPosition(element, component, "world")
   local a,b,r = getVehicleComponentRotation(element, component, "world")
   x = x - math.sin(math.rad(r)) * meters 
   y = y + math.cos(math.rad(r)) * meters 
   return x,y
end 

addEventHandler("onClientPreRender", root,
	function()
		local cameraX, cameraY, cameraZ = getCameraMatrix()
		
		for groundLightShadow, info in pairs(attachedGroundLightShadows) do
			local x, y, z = getPositionFromElementOffset(info.element, info.pos.x, info.pos.y, info.pos.z)
			setElementPosition(groundLightShadow, x, y, z)
		end
		
		for k, data in pairs(groundLightShadows) do
			if data.lightShadow and isElement(data.lightShadow) then
				local worldX, worldY, worldZ = getElementPosition(data.lightShadow)
				local groundPosition = getGroundPosition(worldX, worldY, worldZ)
				local fixedGroundPosition = groundPosition+0.03
				
				local onScreenX, onScreenY = getScreenFromWorldPosition(worldX, worldY, fixedGroundPosition, 20)
				if onScreenX and onScreenY then
					local lightColor = data.color
					
					local distance = getDistanceBetweenPoints3D(worldX, worldY, fixedGroundPosition, cameraX, cameraY, cameraZ)
					if distance <= lightShadowVisibleDistance then
						if isLineOfSightClear(cameraX, cameraY, cameraZ, worldX, worldY, fixedGroundPosition, true, false, false, false, false, true) then
							--local renderTarget = data.texture
							--dxSetRenderTarget(renderTarget, true)
							--local width, height = dxGetMaterialSize(renderTarget)
							--dxSetBlendMode("add")
							--dxDrawImage(width, height, width-width*2, height-height*2, tailLightShadow, 0, 0, 0, tocolor(255,255,255,255))
							--dxSetBlendMode("blend")
							--dxSetRenderTarget()
							--local width, height = dxGetMaterialSize(data.texture)
							--dxSetRenderTarget(data.renderTarget, true)
							--dxSetBlendMode("add")
							--dxDrawImage(0, 0, width, height, data.texture, 0, 0, 0, tocolor(255,255,255,255))
							--dxSetBlendMode("blend")
							--dxSetRenderTarget()
							
							local matching = attachedGroundLightShadows[data.lightShadow]
							if matching then
								local elementX, elementY, elementZ = getElementPosition(matching.element)
								local rx, ry, rz = getElementRotation(matching.element)
								local facez = getGroundPosition(elementX, elementY, elementZ + 5000000)
								local x, y, z = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y, facez)
								
								if elementZ <= fixedGroundPosition+2 then
									dxSetBlendMode("add")
									dxDrawMaterialLine3D(worldX, worldY-data.size, fixedGroundPosition, worldX, worldY+data.size, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
									dxSetBlendMode("blend")
								end
							else
								dxSetBlendMode("add")
								dxDrawMaterialLine3D(worldX, worldY-data.size, fixedGroundPosition, worldX, worldY+data.size, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
								dxSetBlendMode("blend")
							end
						end
					end
				end
			end
		end
	end, true, "low-1"
)

function findRotation( x1, y1, x2, y2 ) 
    local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
    return t < 0 and t + 360 or t
end

function getPositionFromElementOffset(element,offX,offY,offZ)
	local m = getElementMatrix ( element )  -- Get the matrix
	local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  -- Apply transform
	local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
	local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
	return x, y, z  -- Return the transformed point
end

collectgarbage("collect")
--local xddd = createLightShadow(1957.5991210938,-2288.2802734375,13.546875, 245,140,20,255)

And here are the images I am currently using:

https://imgur.com/a/MUYXbnq

My problem is that the images doesn't rotate with the vehicle when I use the "attachGroundLightShadow" function in an other script. I would like to make the attached light shadows rotate with the vehicle in the direction the vehicle facing, or it would be even better if I could change the rotation when calling the "createLightShadow" function.

Hope you understand me and you can help me.

Link to comment

Are you syncing the light rotation W/ the vehicle rotation?

Oh wait, try this

 

I misread before and wasn't paying attention to what I was grabbing position of.

local lightShadowVisibleDistance = 50
local lightShadowTypes = {
	["pointlight"] = dxCreateTexture("files/images/pointlight.png"),
	["taillight"] = dxCreateTexture("files/images/taillight.png"),
}

local groundLightShadows = {}
local attachedGroundLightShadows = {}

function createLightShadow(x, y, z, shadowType, size, r,g,b,a)
	local vehicleLightShadow = createElement("vehicleLightShadow")
	
	local groundPosition = getGroundPosition(x, y, z)
	setElementPosition(vehicleLightShadow, x, y, groundPosition+0.03)
	
	if not r then r = 255 end
	if not g then g = 255 end
	if not b then b = 255 end
	if not a then a = 255 end
	
	if not size then size = 2 end
	
	if not shadowType then shadowType = "normal" end
	
	local array = {}
	
	array.color = {r,g,b,a}
	array.size = size
	
	array.lightShadow = vehicleLightShadow
	array.lightShadowType = shadowType
	
	groundLightShadows[vehicleLightShadow] = array
	return vehicleLightShadow
end

function attachGroundLightShadow(lightShadow, element, pos)
	attachedGroundLightShadows[lightShadow] = { lightShadow = lightShadow, element = element, pos = pos }
	addEventHandler("onClientElementDestroy", lightShadow, function() attachedGroundLightShadows[lightShadow] = nil end)
	addEventHandler("onClientElementDestroy", element, function() attachedGroundLightShadows[lightShadow] = nil end)
	return true
end

local function getPositionInFront(element,meters,component) 
   local x,y,z = getVehicleComponentPosition(element, component, "world")
   local a,b,r = getVehicleComponentRotation(element, component, "world")
   x = x - math.sin(math.rad(r)) * meters 
   y = y + math.cos(math.rad(r)) * meters 
   return x,y
end 

addEventHandler("onClientPreRender", root,
	function()
		local cameraX, cameraY, cameraZ = getCameraMatrix()
		
		for groundLightShadow, info in pairs(attachedGroundLightShadows) do
			local x, y, z = getPositionFromElementOffset(info.element, info.pos.x, info.pos.y, info.pos.z)
			setElementPosition(groundLightShadow, x, y, z)
		end
		
		for k, data in pairs(groundLightShadows) do
			if data.lightShadow and isElement(data.lightShadow) then
				local worldX, worldY, worldZ = getElementPosition(data.lightShadow)
				local groundPosition = getGroundPosition(worldX, worldY, worldZ)
				local fixedGroundPosition = groundPosition+0.03
				
				local onScreenX, onScreenY = getScreenFromWorldPosition(worldX, worldY, fixedGroundPosition, 20)
				if onScreenX and onScreenY then
					local lightColor = data.color
					
					local distance = getDistanceBetweenPoints3D(worldX, worldY, fixedGroundPosition, cameraX, cameraY, cameraZ)
					if distance <= lightShadowVisibleDistance then
						if isLineOfSightClear(cameraX, cameraY, cameraZ, worldX, worldY, fixedGroundPosition, true, false, false, false, false, true) then

							local matching = attachedGroundLightShadows[data.lightShadow]
							if matching then
								local elementX, elementY, elementZ = getElementPosition(matching.element)
								local rx, ry, rz = getElementRotation(matching.element)
								local facez = getGroundPosition(elementX, elementY, elementZ + 5000000)
								local x, y, z = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y, facez)
								
								local xa, ya, za = getPositionFromElementOffset(data.lightShadow,0, -data.size, 0)
								local xb, yb, zb = getPositionFromElementOffset(data.lightShadow,0, data.size, 0)
								
								if elementZ <= fixedGroundPosition+2 then
									dxSetBlendMode("add")
									dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
									dxSetBlendMode("blend")
								end
							else
								dxSetBlendMode("add")
								dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), x, y, z)
								dxSetBlendMode("blend")
							end
						end
					end
				end
			end
		end
	end, true, "low-1"
)

function findRotation( x1, y1, x2, y2 ) 
    local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
    return t < 0 and t + 360 or t
end

function getPositionFromElementOffset(element,offX,offY,offZ)
	local m = getElementMatrix ( element )  -- Get the matrix
	local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  -- Apply transform
	local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
	local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
	return x, y, z  -- Return the transformed point
end

collectgarbage("collect")

 

Edited by CodyJ(L)
Fixed something
  • Like 1
Link to comment

Thank you, I managed to fix it that way:

local xa, ya, za = getPositionFromElementOffset(matching.element,matching.pos.x, matching.pos.y+data.size, 0)
local xb, yb, zb = getPositionFromElementOffset(matching.element,matching.pos.x, matching.pos.y-data.size, 0)

 

Link to comment
  • 3 months later...

Sorry for bringing up this topic again, but I have another problem that I can't solve. How can I make the drawn lights always lay on the surface (or at least always face the vehicle's top correctly)? Since right now when I go up on a hill with a light shadow attached to my vehicle it looks like this:

1N8zTe5.png

pQ3YKNT.png

How can I make it work like the default headlights on surface?

Just to make sure, here's my current calculations again:

addEventHandler("onClientPreRender", root,
	function()
		local cameraX, cameraY, cameraZ = getElementPosition(getCamera())
		
		for groundLightShadow, info in pairs(attachedGroundLightShadows) do
			local x, y, z = getPositionFromElementOffset(info.element, info.pos.x, info.pos.y, info.pos.z)
			setElementPosition(groundLightShadow, x, y, z)
		end
		
		for k, data in pairs(groundLightShadows) do
			if data.lightShadow and isElement(data.lightShadow) then
				local worldX, worldY, worldZ = getElementPosition(data.lightShadow)
				local groundPosition = getGroundPosition(worldX, worldY, worldZ)
				local fixedGroundPosition = groundPosition+0.05
				
				local onScreenX, onScreenY = getScreenFromWorldPosition(worldX, worldY, fixedGroundPosition, 20)
				if onScreenX and onScreenY then
					local distance = getDistanceBetweenPoints3D(worldX, worldY, fixedGroundPosition, cameraX, cameraY, cameraZ)
					if distance <= lightShadowVisibleDistance then
						if isLineOfSightClear(cameraX, cameraY, cameraZ, worldX, worldY, fixedGroundPosition, true, false, false, false, false, true) then
							
							local lightColor = data.color
							local matching = attachedGroundLightShadows[data.lightShadow]
							
							if matching then
								local elementX, elementY, elementZ = getElementPosition(matching.element)
								
								local rx, ry, rz = getElementRotation(matching.element)
								--local facez = getGroundPosition(elementX, elementY, elementZ + 5000000)
								local x, y, z = getPositionFromElementOffset(matching.element, matching.pos.x, matching.pos.y, matching.pos.z)
								
								local xa, ya, za = getPositionFromElementOffset(matching.element,matching.pos.x, matching.pos.y+data.size, matching.pos.z)
								local xb, yb, zb = getPositionFromElementOffset(matching.element,matching.pos.x, matching.pos.y-data.size, matching.pos.z)
								
								if elementZ <= fixedGroundPosition+2 then
									dxSetBlendMode("add")
									dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), (xa+xb)/2, (ya+yb)/2, z)
									dxSetBlendMode("blend")
								end
							else
								dxSetBlendMode("add")
								dxDrawMaterialLine3D(xa, ya, fixedGroundPosition, xb, yb, fixedGroundPosition, lightShadowTypes[data.lightShadowType], data.size*2, tocolor(lightColor[1],lightColor[2],lightColor[3],lightColor[4]), (xa+xb)/2, (ya+yb)/2, z)
								dxSetBlendMode("blend")
							end
						end
					end
				end
			end
		end
	end, true, "low-10"
)

 

Edited by Dzsozi (h03)
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...