Dzsozi (h03) Posted May 26, 2018 Share Posted May 26, 2018 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: But the problem is that the image always has the same rotation, doesn't matter what's the vehicle's rotation: 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
Captain Cody Posted May 26, 2018 Share Posted May 26, 2018 (edited) 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 May 26, 2018 by CodyJ(L) Link to comment
Dzsozi (h03) Posted May 27, 2018 Author Share Posted May 27, 2018 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
Captain Cody Posted May 27, 2018 Share Posted May 27, 2018 (edited) 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 May 27, 2018 by CodyJ(L) Fixed something 1 Link to comment
Dzsozi (h03) Posted May 27, 2018 Author Share Posted May 27, 2018 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
Captain Cody Posted May 27, 2018 Share Posted May 27, 2018 Alright, cool; wasn't paying attention to which element you were using on the first part. Link to comment
Dzsozi (h03) Posted September 19, 2018 Author Share Posted September 19, 2018 (edited) 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: 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 September 19, 2018 by Dzsozi (h03) Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now