math formula to calculate if 3d point is inside 3d oriented cone (or not)

Started by RemiD, March 11, 2018, 13:49:58

Previous topic - Next topic

RemiD

Hello,

I am searching for a math formula to calculate if a 3d point is inside a 3d oriented cone (or not)

what i mean by oriented cone, is a cone which has a specific orientation in 3d (same orientation than the camera)

the idea is to calculate if a vertex (3d point) is inside the cone shape or not, before calculating the vertex lighting shading...

(deltapitch + deltayaw gives me a pyramid shape, not a cone shape)

Thanks,

GaborD

No need for complex math, the dot() of the cone's center direction and the direction from the texel to the light is the cosinus of the offaxis-angle of the texel.
Thus you can easily use this for a smooth spot falloff:

float spotFactor = smoothstep( cosOuterAngle, cosInnerAngle, dot(normalize(spotPosition - texelPosition), -spotDir));

cosInnerAngle would be the cosinus of the inner cone angle (start of the falloff), outer the end-angle of the falloff. Keep in mind the angles are in radians in GLSL thus you are going from 0 to 1.5708 instead of 0 to 90.


RemiD

I have found this :
http://nic-gamedev.blogspot.fr/2011/11/using-vector-mathematics-and-bit-of.html

that i have converted to this (bb) code :

Graphics(640,360,32,2)

RootX# = 0 : RootY# = 0 : RootZ# = 0
RootNX# = 0 : RootNY# = 0 : RootNZ# = 1.0
PointX# = 0.5 : PointY# = 0 : PointZ# = 1.5
FOV# = 3.141592/4 ;(45=180/4)
Length# = Sqr( ( ( PointX - RootX ) * ( PointX - RootX ) ) + ( ( PointY - RootY ) * ( PointY - RootY ) ) + ( ( PointZ - RootZ ) * ( PointZ - RootZ ) ) )
VecX# = PointX-RootX : VecY# = PointY-RootY : VecZ# = PointZ-RootZ
VecNX# = VecX/Length : VecNY# = VecY/Length : VecNZ# = VecZ/Length
DP# = ( ( RootNX * VecNX ) + ( RootNY * VecNY ) + ( RootNZ * VecNZ ) )
DebugLog(DP)
C# = Cos(FOV/2) ;or ACos(FOV/2)
DebugLog(C)
If( DP >= C )
;point is inside cone
DebugLog("is inside")
Else If( DP < C )
;point is outside cone
DebugLog("is outside")
EndI

WaitKey()

End()


but it does not seem to work correctly (or maybe the Cos() / ACos() function of Blitz3d is not adequate ?)


@Gabor>>very nice, i really have to learn to code custom shaders...

col

Sorry
Didn't meant to hit the post button.
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

GaborD

The code looks OK at first glance. I don't have B3D installed, otherwise I would test it.
If you go through it line by line, you'll notice it's exactly the same approach that my posted shader code uses, just more verbose due to not having simple commands for the dot product and the normalization.
You could also streamline it a bit, the subtraction could be just done once instead of being redone basically 3 times. (I mean the PointX - RootX, PointY - RootY, PointZ - RootZ ones)

The Blitz version ofcourse has a hard cutoff with the conditional instead of a smooth border, but that could be easily added, you just have to port the smoothstep to B3D code.
Here is a simply portable smoothstep implementation:
float smoothstep(float a, float b, float x) {
    float f = saturate((x - a)/(b - a));
    return f*f*(3.0 - (2.0*f));
}

If you can't get the copied code to work you could try to port the shader line step by step, easier to work with own code.
The normalize is easy, just divide each component through the overall vector length.
The dot product is also easy, it's just A.x * B.x + A.y * B.y + A.z * B.z
Should be no problem in B3D.

STEVIE G

Quote from: RemiD on March 12, 2018, 08:08:14
I have found this :
http://nic-gamedev.blogspot.fr/2011/11/using-vector-mathematics-and-bit-of.html

that i have converted to this (bb) code :

Graphics(640,360,32,2)

RootX# = 0 : RootY# = 0 : RootZ# = 0
RootNX# = 0 : RootNY# = 0 : RootNZ# = 1.0
PointX# = 0.5 : PointY# = 0 : PointZ# = 1.5
FOV# = 3.141592/4 ;(45=180/4)
Length# = Sqr( ( ( PointX - RootX ) * ( PointX - RootX ) ) + ( ( PointY - RootY ) * ( PointY - RootY ) ) + ( ( PointZ - RootZ ) * ( PointZ - RootZ ) ) )
VecX# = PointX-RootX : VecY# = PointY-RootY : VecZ# = PointZ-RootZ
VecNX# = VecX/Length : VecNY# = VecY/Length : VecNZ# = VecZ/Length
DP# = ( ( RootNX * VecNX ) + ( RootNY * VecNY ) + ( RootNZ * VecNZ ) )
DebugLog(DP)
C# = Cos(FOV/2) ;or ACos(FOV/2)
DebugLog(C)
If( DP >= C )
;point is inside cone
DebugLog("is inside")
Else If( DP < C )
;point is outside cone
DebugLog("is outside")
EndI

WaitKey()

End()


but it does not seem to work correctly (or maybe the Cos() / ACos() function of Blitz3d is not adequate ?)


@Gabor>>very nice, i really have to learn to code custom shaders...

The FOV is in radians which is probably why it doesn't work.

RemiD

Quote
The FOV is in radians which is probably why it doesn't work.
so what do you suggest to make it work ? (i have only a basic understanding of maths...)


edit : simply replace :

FOV# = 3.141592/4 ;(corresponds to 45.0=180.0/4)

by :

FOV# = 45.0 ;(=180.0/4)

and it seems to work... (not sure, i will check with a debug mesh)

STEVIE G

Quote from: RemiD on March 13, 2018, 08:12:01
Quote
The FOV is in radians which is probably why it doesn't work.
so what do you suggest to make it work ? (i have only a basic understanding of maths...)

Change FOV to 45, rather than 45*PI/180.  Cos(theta#) expects degrees, not radians.  I can't guarantee you it'll work though. 

EDIT ... I see you've done this already. 

You might want to check out this wee gem by Fredborg ..

https://www.syntaxbomb.com/index.php/topic,2321.msg3310.html#msg3310


RemiD

yes, i confirm that it works correctly, and the cone can be oriented in 3d. very useful !


Quote
You might want to check out this wee gem by Fredborg ..
yes i have already seen this code example, some impressive wizardry going on... :)