Jump to content

Getting the right rotation from normals


Przemcio

Recommended Posts

Hey,

I'm struggling for hours with something, that should be easy enough, but my math skills are weak.

So, I'm trying to find a right rotation for dirX, dirY, dirZ when you shoot something, wth any of the effects such as https://wiki.multitheftauto.com/wiki/FxAddSparks, but I can't get it at all.

I'm using processLineOfSight to get a normal vectors, then I'm converting them to Euler angles with https://wiki.multitheftauto.com/wiki/Math.rotVecToEulerAngle, but the sparks are not flying right.

The code is pretty simple (there were like 100 different attempts and approaches, but let me show you the most normal example XD):

 

local Hit, TargetEndX, TargetEndY, TargetEndZ, _, NormalX, NormalY, NormalZ, Material = processLineOfSight(TargetX, TargetY, TargetZ, TargetEndX, TargetEndY, TargetEndZ, true, true, true, true, false, false, false, false, false, true, true)
	 
	if(Hit == true)
	then
	        local RotX, RotY, RotZ = math.rotVecToEular(NormalX, NormalY, NormalZ, 0.0)
            fxAddSparks(TargetEndX, TargetEndY, TargetEndZ, RotX, RotY, RotZ, 1.0, math.random(10), 0.0, 0.0, 0.0, true, 1.0, 1.0)
	end

 

and yeah, I don't know what actually should I calculate there, can't even find any similar script to what I'm trying to do, which is rather surprising :D Can someone enlighten me? Please, use a very simple language when it comes to maths, cause I'm mathidiot. Thanks!

Edited by Jamnik
Link to comment

First, you don't need to convert the normal vectors to euler angles, beacuse the fxAddSparks function needs a direction vector that is exactly what normal vectors is.

Second, you need to extend the TargetEndX/Y/Z values a bit because sometimes it's too short and the raycast returns false.

 

For scaling:
 

TargetEndX = TargetX + (TargetEndX - TargetX) * 5
TargetEndY = TargetY + (TargetEndY - TargetY) * 5
TargetEndZ = TargetZ + (TargetEndZ - TargetZ) * 5

 

  • Thanks 1
Link to comment

I'm feeling much stupid right now, it works without converting normals to eulers, thanks a bunch! As for the TargetEnd - no need to, debugged it already and there seems to be no issues like that.

Okay, so if I can use it like this in FX'es, what about functions that needs euler angles and/or use Vector3? I was playing with material3DEffects (https://community.multitheftauto.com/index.php?p=resources&s=details&id=13314), I tried to use that method:

-- texture or renderTarget, worldPosition Vector3(), rotation Vector3(deg) , size Vector2(0-n,0-n)   
	function CMat3DSoftBlend: create( texture, pos, rot, siz )
    local cShader = {
        shader = DxShader( "fx/material3D_soft_blend.fx" ),
        texture = texture,
        color = tocolor(255, 255, 255, 255),
        texCoord = {Vector2(1, 1),Vector2(0, 0)},
        position = pos,
        rotation = rot,
        size = siz,
        billboard = false,
        clip = 450,
        zEnable = true,
        zWriteEnable = false,
        flipVertex = false,
        fogEnable = true,
        cullMode = 1,
        depthAttenuation = 1.2,
        depthAttenuationPower = 1.5
    }
    if cShader.shader then
        local scX, scY = guiGetScreenSize()
        cShader.shader:setValue( "sHalfPixel", 1/(scX * 2), 1/(scY * 2) )
	        -- pass position and ZXY rotation to recreate gWorld matrix
        cShader.shader:setValue( "sElementRotation", math.rad( rot.x ), math.rad( rot.y ), math.rad( rot.z ))
        cShader.shader:setValue( "sElementPosition", pos.x, pos.y, pos.z )
        
        cShader.shader:setValue( "sElementSize", siz.x, siz.y )
        cShader.shader:setValue( "sFlipTexture", false )
        cShader.shader:setValue( "sFlipVertex", cShader.flipVertex )
        cShader.shader:setValue( "sIsBillboard", cShader.billboard )
        
        cShader.shader:setValue( "uvMul", cShader.texCoord[1].x, cShader.texCoord[1].y )
        cShader.shader:setValue( "uvPos", cShader.texCoord[2].x, cShader.texCoord[2].y )
        cShader.shader:setValue( "sFogEnable", cShader.fogEnable )
        cShader.shader:setValue( "fZEnable", cShader.zEnable )
        cShader.shader:setValue( "fZWriteEnable", cShader.zWriteEnable )
        cShader.shader:setValue( "fCullMode", cShader.cullMode )
	        cShader.shader:setValue( "fDepthAttenuation", cShader.depthAttenuation )
        cShader.shader:setValue( "fDepthAttenuationPower", cShader.depthAttenuationPower )
        -- set texture
        cShader.shader:setValue( "sTexColor", cShader.texture )
        self.__index = self
        setmetatable( cShader, self )
        return cShader
    else
        return false
    end
end

 

It creates 2D texture in the 3D world, similar to dxDrawImage3D, but with much better customization and accuracy. But I can't get the right angles here too. Yeah, the angles are in ZXY order, the code is almost identical to the previous one, just using CMat3DSoftBlend constructor with Vector3(RotZ, RotX, RotY) on the rotations, instead of FX function. Unfortunately, not converting the normals doesn't work in that case, it doesn't work with objects rotation either. Do you know what should I do in cases like that with normals, that processLineOfSight returns? Or is there a better way to render specific-placed 2D texture (like for example - a 2D dot at the end of the laser, which rotation should be relative to the surface) in 3D world? Thanks!

Edited by Jamnik
Link to comment

You can convert the normal vectors to euler angles with the following function, you can use the phi for the so called Z rotation and the theta for one of the remaining (check it which one is better for you). It's a working function, I had a fun time with it shooting trash cans everywhere :D

function directionToEuler(dirX, dirY, dirZ)
	local radius = (dirX*dirX + dirY*dirY + dirZ*dirZ) ^ 0.5
	local theta = math.deg(math.acos(dirZ / radius))
	local phi = math.deg(math.atan2(dirY, dirX)) % 360
	return theta, phi
end

 

  • Like 2
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...