Author Topic: math formula to calculate if 3d point is inside 3d oriented cone (or not)  (Read 800 times)

Offline RemiD

  • Hero Member
  • *****
  • Posts: 754
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,

Offline GaborD

  • Full Member
  • ***
  • Posts: 148
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.


Offline RemiD

  • Hero Member
  • *****
  • Posts: 754
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 :
Code: [Select]
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...

Offline col

  • Sr. Member
  • ****
  • Posts: 405
Sorry
Didn't meant to hit the post button.
Any bugs in my code are proof of its hand-coded nature.
https://github.com/davecamp

Offline GaborD

  • Full Member
  • ***
  • Posts: 148
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.

Offline STEVIE G

  • Sr. Member
  • ****
  • Posts: 252
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 :
Code: [Select]
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.

Offline RemiD

  • Hero Member
  • *****
  • Posts: 754
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 :
Code: [Select]
FOV# = 3.141592/4 ;(corresponds to 45.0=180.0/4)
by :
Code: [Select]
FOV# = 45.0 ;(=180.0/4)
and it seems to work... (not sure, i will check with a debug mesh)

Offline STEVIE G

  • Sr. Member
  • ****
  • Posts: 252
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


Offline RemiD

  • Hero Member
  • *****
  • Posts: 754
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... :)