Vortex - Camera Picking and Project

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
Looks really great! Congratulations.
Hey @JaviCervera , great to see you here again. I hope life is treating you well.

I know I had asked that before. Is there any chance you could add Object or Camera picking aka raycasting to Vortex and 3d coords conversion to 2D coords. For some reason I can't get my head around it, I am simply to stupid.

I know there is no money to be made and no fame to get for doing this, just my endless gratitude. I would love to add your framework as an official module to CX but I know people would ask for these features. And of course, I would ask that myself. I would love to port my game CardRogues to Vortex, but I need picking/ray casting to see which object I have clicked on.

Did I say PLEASE Javi? :)
 

Amon

Member
Joined
Nov 19, 2018
Messages
50
@JaviCervera

Hi Javi. Can you let us know what the cost will be to have the features @MikeHart asked about in the previous post? I'm willing to fund having you implement those features.

As long as I don't need to mortgage my house to pay the fee then I'm positive we can come up with an agreement.
 

innerloop

New member
CX Code Contributor
Joined
Jan 18, 2021
Messages
8
@MikeHart
@Amon

I can offer you temporary solution

[CODE lang="cerberus" title="add some utils to file math3d.cxs"]
Function Vec3Sub:Void( result:Float[], l:Float[], r:Float[] )
result[0] = l[0] - r[0]
result[1] = l[1] - r[1]
result[2] = l[2] - r[2]
End

Function Vec3Cross:Void( result:Float[], l:Float[], r:Float[] )
result[0] = l[1] * r[2] - l[2] * r[1]
result[1] = l[2] * r[0] - l[0] * r[2]
result[2] = l[0] * r[1] - l[1] * r[0]
End

Function Vec3Dot:Float( l:Float[], r:Float[] )
Return l[0] * r[0] + l[1] * r[1] + l[2] * r[2]
End

Function Vec3Transform:Void( result:Float[], v:Float[], m:Float[] )
Local x:Float = v[0]
Local y:Float = v[1]
Local z:Float = v[2]
result[0] = x * m[0] + y * m[4] + z * m[ 8] + m[12]
result[1] = x * m[1] + y * m[5] + z * m[ 9] + m[13]
result[2] = x * m[2] + y * m[6] + z * m[10] + m[14]
End

Function Vec3TransformCoord:Void( result:Float[], v:Float[], m:Float[] )
Local x:Float = v[0]
Local y:Float = v[1]
Local z:Float = v[2]
Local t:Float = 1.0 / ( x * m[3] + y * m[7] + z * m[11] + m[15] )
result[0] = ( x * m[0] + y * m[4] + z * m[ 8] + m[12] ) * t
result[1] = ( x * m[1] + y * m[5] + z * m[ 9] + m[13] ) * t
result[2] = ( x * m[2] + y * m[6] + z * m[10] + m[14] ) * t
End

Function Vec3TransformNormal:Void( result:Float[], v:Float[], m:Float[] )
Local x:Float = v[0]
Local y:Float = v[1]
Local z:Float = v[2]
result[0] = x * m[0] + y * m[4] + z * m[ 8]
result[1] = x * m[1] + y * m[5] + z * m[ 9]
result[2] = x * m[2] + y * m[6] + z * m[10]
End

Function Vec3Normalize:Float( result:Float[], v:Float[] )
Local l:Float = Vec3Dot( v, v )
If l > 0.0 Then
l = Sqrt( l )
Local s:Float = 1.0 / l
result[0] = v[0] * s
result[1] = v[1] * s
result[2] = v[2] * s
End If
Return l
End

Function RayTriangleIntersection:Bool( result:Float[], origin:Float[], direction:Float[], point1:Float[], point2:Float[], point3:Float[] )
Local e1x := point2[0] - point1[0]
Local e1y := point2[1] - point1[1]
Local e1z := point2[2] - point1[2]
Local e2x := point3[0] - point1[0]
Local e2y := point3[1] - point1[1]
Local e2z := point3[2] - point1[2]
Local pvx := direction[1] * e2z - direction[2] * e2y
Local pvy := direction[2] * e2x - direction[0] * e2z
Local pvz := direction[0] * e2y - direction[1] * e2x
Local d := e1x * pvx + e1y * pvy + e1z * pvz
If d > -0.001 And d < 0.001 Then Return False
d = 1.0 / d
Local tvx := origin[0] - point1[0]
Local tvy := origin[1] - point1[1]
Local tvz := origin[2] - point1[2]
Local u := ( tvx * pvx + tvy * pvy + tvz * pvz ) * d
If u < 0.0 Or u > 1.0 Then Return False
Local qvx := tvy * e1z - tvz * e1y
Local qvy := tvz * e1x - tvx * e1z
Local qvz := tvx * e1y - tvy * e1x
Local v := ( direction[0] * qvx + direction[1] * qvy + direction[2] * qvz ) * d
If v < 0.0 Or u + v > 1.0 Then Return False
Local t := ( e2x * qvx + e2y * qvy + e2z * qvz ) * d
result[0] = t
result[1] = u
result[2] = v
Return True
End

Function RayAxisAlignedBoxIntersection:Bool( result:Float[], origin:Float[], direction:Float[], min:Float[], max:Float[] )
Local l1:Float = ( min[0] - origin[0] ) / direction[0]
Local l2:Float = ( max[0] - origin[0] ) / direction[0]
Local t1:Float = Min( l1, l2 )
Local t2:Float = Max( l1, l2 )
l1 = ( min[1] - origin[1] ) / direction[1]
l2 = ( max[1] - origin[1] ) / direction[1]
t1 = Max( Min( l1, l2 ), t1 )
t2 = Min( Max( l1, l2 ), t2 )
l1 = ( min[2] - origin[2] ) / direction[2]
l2 = ( max[2] - origin[2] ) / direction[2]
t1 = Max( Min( l1, l2 ), t1 )
t2 = Min( Max( l1, l2 ), t2 )
If t2 < 0.0 Or t2 < t1 Then Return False
result[0] = t1
result[1] = t2
Return True
End

Function RaySphereIntersection:Bool(result:Float[], origin:Float[], direction:Float[], sphere:Float[] )
Local rox := origin[0] - sphere[0]
Local roy := origin[1] - sphere[1]
Local roz := origin[2] - sphere[2]
Local a := direction[0] * direction[0] + direction[1] * direction[1] + direction[2] * direction[2]
Local b := 2.0 * ( rox * direction[0] + roy * direction[1] + roz * direction[2] )
Local c := ( rox * rox + roy * roy + roz * roz ) - sphere[3] * sphere[3]
Local d := b * b - 4.0 * a * c
If d < 0.0 Then Return False
d = Sqrt( d )
a = 0.5 / a
Local t1 := ( d - b ) * a
Local t2 := ( -b - d ) * a
If t1 < 0.0 Then t1 = t2
If t2 < 0.0 Then t2 = t1
t1 = Min( t1, t2 )
If t1 < 0.0 Then Return False
result[0] = t1
Return True
End
[/CODE]

[CODE lang="cerberus" title="add this to class World inside file world.cxs"]
Private

Global rtTraceInfo:TraceInfo = New TraceInfo
Global rtProjectionTransform:Float[16]
Global rtViewTransform:Float[16]
Global rtInverseViewTransform:Float[16]
Global rtNormPoint:Float[3]
Global rtLineDirection:Float[3]
Global mPickedEntity:Entity
Global mPickedSurface:Surface
Global mPickedTriangle:Int
Global mPickedDistance:Float
Global mPickedPoint:Float[3]
Global mPickedNormal:Float[3]

Public

Function PickedEntity:Entity()
Return mPickedEntity
End

Function PickedSurface:Surface()
Return mPickedSurface
End

Function PickedTriangle:Int()
Return mPickedTriangle
End

Function PickedDistance:Float()
Return mPickedDistance
End

Function PickedX:Float()
Return mPickedPoint[0]
End

Function PickedY:Float()
Return mPickedPoint[1]
End

Function PickedZ:Float()
Return mPickedPoint[2]
End

Function PickedNX:Float()
Return mPickedNormal[0]
End

Function PickedNY:Float()
Return mPickedNormal[1]
End

Function PickedNZ:Float()
Return mPickedNormal[2]
End

Function RayTrace:Bool( rayOrigin:Float[], rayDirection:Float[], maxDistance:Float = 0.0 )
mPickedEntity = Null
mPickedSurface = Null
mPickedTriangle = -1
mPickedDistance = 10000000000.0
Local minDistance:Float = 10000000000.0
For Local targetEntity:Entity = EachIn mEntities
If Not ( targetEntity.Visible And targetEntity.Pickable ) Then Continue
If Not targetEntity.RayTrace( rtTraceInfo, rayOrigin, rayDirection, maxDistance ) Then Continue
If rtTraceInfo.mDistance >= minDistance Then Continue
minDistance = rtTraceInfo.mDistance
mPickedEntity = targetEntity
mPickedSurface = rtTraceInfo.mSurface
mPickedTriangle = rtTraceInfo.mTriangle
mPickedDistance = rtTraceInfo.mDistance
mPickedPoint[0] = rtTraceInfo.mPoint[0]
mPickedPoint[1] = rtTraceInfo.mPoint[1]
mPickedPoint[2] = rtTraceInfo.mPoint[2]
mPickedNormal[0] = rtTraceInfo.mNormal[0]
mPickedNormal[1] = rtTraceInfo.mNormal[1]
mPickedNormal[2] = rtTraceInfo.mNormal[2]
End
Return mPickedEntity <> Null
End

Function CameraPick:Bool( cameraEntity:Camera, screenX:Int, screenY:Int )
Mat4PerspectiveLH( cameraEntity.FovY, cameraEntity.AspectRatio, cameraEntity.Near, cameraEntity.Far, rtProjectionTransform )
rtNormPoint[0] = ( screenX * 2.0 / cameraEntity.ViewportWidth - 1.0 ) / rtProjectionTransform[0]
rtNormPoint[1] = ( 1.0 - screenY * 2.0 / cameraEntity.ViewportHeight ) / rtProjectionTransform[5]
rtNormPoint[2] = 1.0
Mat4ViewEuler( cameraEntity.WorldX, cameraEntity.WorldY, cameraEntity.WorldZ, cameraEntity.Pitch, cameraEntity.Yaw, cameraEntity.Roll, rtViewTransform )
Mat4Invert( rtViewTransform, rtInverseViewTransform )
Local rayOrigin:Float[3]
rayOrigin[0] = rtInverseViewTransform[12]
rayOrigin[1] = rtInverseViewTransform[13]
rayOrigin[2] = rtInverseViewTransform[14]
Local rayDirection:Float[3]
Vec3TransformNormal( rayDirection, rtNormPoint, rtInverseViewTransform )
Return RayTrace( rayOrigin, rayDirection )
End

Function LinePick:Bool( lineStart:Float[], lineEnd:Float[] )
Vec3Sub( rtLineDirection, lineEnd, lineStart )
Local lineLength:Float = Vec3Normalize( rtLineDirection, rtLineDirection )
Return RayTrace( lineStart, rtLineDirection, lineLength )
End
[/CODE]

[CODE lang="cerberus" title="add this to class Model inside file model.cxs"]
Private

Field rtModelBox:Float[6]
Field rtModelSphere:Float[4]
Field rtIntersectionInfo:Float[2]
Field rtModelTransform:Float[16]
Field rtInverseModelTransform:Float[16]
Field rtLocalRayOrigin:Float[3]
Field rtLocalRayDirection:Float[3]

Public

Method RayTrace:Bool( ti:Object, rayOrigin:Float[], rayDirection:Float[], maxDistance:Float = 0.0 )
Local traceInfo:TraceInfo = TraceInfo( ti )
rtModelBox[0] = BoxMinX
rtModelBox[1] = BoxMinY
rtModelBox[2] = BoxMinZ
rtModelBox[3] = BoxMaxX
rtModelBox[4] = BoxMaxY
rtModelBox[5] = BoxMaxZ
rtModelSphere[0] = ( rtModelBox[0] + rtModelBox[3] ) * 0.5
rtModelSphere[1] = ( rtModelBox[1] + rtModelBox[4] ) * 0.5
rtModelSphere[2] = ( rtModelBox[2] + rtModelBox[5] ) * 0.5
rtModelSphere[3] = Max( rtModelBox[5] - rtModelBox[2],
Max( rtModelBox[3] - rtModelBox[0],
rtModelBox[4] - rtModelBox[1] ) )
If Not RaySphereIntersection( rtIntersectionInfo, rayOrigin, rayDirection, rtModelSphere ) Then Return False
If maxDistance > 0.0 And rtIntersectionInfo[0] > maxDistance Then Return False
Mat4TransformEuler( WorldX, WorldY, WorldZ, Pitch, Yaw, Roll, ScaleX, ScaleY, ScaleZ, rtModelTransform )
Mat4Invert( rtModelTransform, rtInverseModelTransform )
Vec3TransformCoord( rtLocalRayOrigin, rayOrigin, rtInverseModelTransform )
Vec3TransformNormal( rtLocalRayDirection, rayDirection, rtInverseModelTransform )
If Not Mesh.RayTrace( traceInfo, rtLocalRayOrigin, rtLocalRayDirection ) Then Return False
If maxDistance > 0.0 And traceInfo.mDistance > maxDistance Then Return False
Vec3Transform( traceInfo.mPoint, traceInfo.mPoint, rtModelTransform )
Return True
End
[/CODE]

[CODE lang="cerberus" title="add this to class Entity inside file entity.cxs"]
Private

Field mPickable: Bool

Public

Method RayTrace:Bool( traceInfo:Object, rayOrigin:Float[], rayDirection:Float[], maxDistance:Float = 0.0 )
Return False
End

Method Pickable:Bool() Property
Return mPickable
End

Method Pickable:Void( state:Bool ) Property
mPickable = state
End
[/CODE]

[CODE lang="cerberus" title="add this class to file mesh.cxs"]
Class TraceInfo
Public
Field mSurface:Surface
Field mTriangle:Int
Field mDistance:Float
Field mPoint:Float[3]
Field mNormal:Float[3]
End
[/CODE]

[CODE lang="cerberus" title="add this to class Mesh inside file mesh.cxs"]
Private

Field rtVertexPosition0:Float[3]
Field rtVertexPosition1:Float[3]
Field rtVertexPosition2:Float[3]
Field rtTriangleEdge1:Float[3]
Field rtTriangleEdge2:Float[3]
Field rtTriangleCross:Float[3]
Field rtIntersectionInfo:Float[3]

Method rtGetTriangleData:Void( meshSurface:Surface, triangleIndex:Int )
Local vertexIndex0:Int = meshSurface.TriangleV0( triangleIndex )
Local vertexIndex1:Int = meshSurface.TriangleV1( triangleIndex )
Local vertexIndex2:Int = meshSurface.TriangleV2( triangleIndex )
rtVertexPosition0[0] = meshSurface.VertexX( vertexIndex0 )
rtVertexPosition0[1] = meshSurface.VertexY( vertexIndex0 )
rtVertexPosition0[2] = meshSurface.VertexZ( vertexIndex0 )
rtVertexPosition1[0] = meshSurface.VertexX( vertexIndex1 )
rtVertexPosition1[1] = meshSurface.VertexY( vertexIndex1 )
rtVertexPosition1[2] = meshSurface.VertexZ( vertexIndex1 )
rtVertexPosition2[0] = meshSurface.VertexX( vertexIndex2 )
rtVertexPosition2[1] = meshSurface.VertexY( vertexIndex2 )
rtVertexPosition2[2] = meshSurface.VertexZ( vertexIndex2 )
Vec3Sub( rtTriangleEdge1, rtVertexPosition1, rtVertexPosition0 )
Vec3Sub( rtTriangleEdge2, rtVertexPosition2, rtVertexPosition0 )
Vec3Cross( rtTriangleCross, rtTriangleEdge1, rtTriangleEdge2 )
End

Public

Method RayTrace:Bool( traceInfo:TraceInfo, rayOrigin:Float[], rayDirection:Float[] )
Local nearestSurface:Surface = Null
Local nearestTriangle:Int = -1
Local minDistance:Float = 10000000000.0
For Local surfaceIndex:Int = 0 Until NumSurfaces
Local meshSurface:Surface = Self.Surface( surfaceIndex )
For Local triangleIndex:Int = 0 Until meshSurface.NumTriangles
rtGetTriangleData( meshSurface, triangleIndex )
If Vec3Dot( rayDirection, rtTriangleCross ) >= 0.0 Then Continue
If Not RayTriangleIntersection( rtIntersectionInfo, rayOrigin, rayDirection, rtVertexPosition0, rtVertexPosition1, rtVertexPosition2 ) Then Continue
If rtIntersectionInfo[0] >= minDistance Then Continue
minDistance = rtIntersectionInfo[0]
nearestTriangle = triangleIndex
nearestSurface = meshSurface
End
End
If nearestSurface = Null Then Return False
traceInfo.mSurface = nearestSurface
traceInfo.mTriangle = nearestTriangle
traceInfo.mDistance = minDistance
traceInfo.mPoint[0] = rayOrigin[0] + rayDirection[0] * minDistance
traceInfo.mPoint[1] = rayOrigin[1] + rayDirection[1] * minDistance
traceInfo.mPoint[2] = rayOrigin[2] + rayDirection[2] * minDistance
rtGetTriangleData( nearestSurface, nearestTriangle )
Vec3Normalize( traceInfo.mNormal, rtTriangleCross )
Return True
End
[/CODE]

[CODE lang="cerberus" title="add this to class Camera in file camera.cxs"]
Private

Field rtProjectionTransform:Float[16]
Field rtViewTransform:Float[16]
Field rtTempPoint:Float[3]
Field mProjectedPoint:Int[2]

Public

Method ProjectedX:Int() Property
Return mProjectedPoint[0]
End

Method ProjectedY:Int() Property
Return mProjectedPoint[1]
End

Method Project:Void( inputPoint:Float[] )
Mat4PerspectiveLH( FovY, AspectRatio, Near, Far, rtProjectionTransform )
Mat4ViewEuler( WorldX, WorldY, WorldZ, Pitch, Yaw, Roll, rtViewTransform )
Vec3TransformCoord( rtTempPoint, inputPoint, rtViewTransform )
Vec3TransformCoord( rtTempPoint, rtTempPoint, rtProjectionTransform )
mProjectedPoint[0] = ( rtTempPoint[0] + 1.0 ) * ( ViewportWidth / 2 )
mProjectedPoint[1] = ( 1.0 - rtTempPoint[1] ) * ( ViewportHeight / 2 )
End
[/CODE]

so, usage is simple:

[CODE lang="cerberus" title="usage"]
Entity.Pickable = True' enable pick for entity

World.CameraPick( camera, x, y )' pick all entities (models) in world with specific camera and screen coords

World.LinePick( lineStart, lineEnd )' pick all entities (models) in world with specific line start and end coords

World.PickedEntity()' returns nearest picked entity

World.PickedSurface()' returns picked surface

World.PickedTriangle()' returns picked triangle

' returns picked point
World.PickedX()
World.PickedY()
World.PickedZ()

' returns picked normal
World.PickedNX()
World.PickedNY()
World.PickedNZ()

camera.Project( someWorldPoint )' project 3d world point on screen for specific camera

' returns projected point
camera.ProjectedX()
camera.ProjectedY()
[/CODE]
 
Last edited:

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
Question, if I want to cast a ray from a given Vec3 to another, how would I do it?
 

innerloop

New member
CX Code Contributor
Joined
Jan 18, 2021
Messages
8
Question, if I want to cast a ray from a given Vec3 to another, how would I do it?
two way
1) compute ray from line between two vec3 and use RayTrace but reject all picked entities with distance great then line length
2) write code of intersection line with box and triangle and another RayTrace with line-specific math (too complicated)

content deleted, see first post in this thread.

not optimal solution because all entities traced anyway
 
Last edited:

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
Thanks, this example for picking doesn't work quite right, depending on the cubes position and the cameras position.
Hint: I didn't add your latest code modifies.

code_language.cerberus:
Strict

#GLFW_WINDOW_TITLE="Vortex2 Camera Picking Test"
#GLFW_WINDOW_WIDTH=800
#GLFW_WINDOW_HEIGHT=600
#GLFW_WINDOW_RESIZABLE=True
#GLFW_WINDOW_SAMPLES=2

Import mojo.app
Import mojo.input
Import vortex
Import vortex.src.math3d
Import vortex.src.renderstate

Class TestApp Extends App	
	
	Method OnCreate:Int()
		'Setup
		SetUpdateRate(30)
		SetSwapInterval(1)
		Seed = Millisecs()
	
		'Init vortex
		If Not World.Init() Then EndApp()
		Print "Vendor name: " + Graphics.VendorName()
		Print "Renderer name: " + Graphics.RendererName()
		Print "API version name: " + Graphics.APIVersionName()
		Print "Shading version name: " + Graphics.ShadingVersionName()+"~n"

		'Load font
		mFont = Font.Load("Roboto-Black_16.fnt.dat")

		
		'Create camera
		mCam = New Camera()
		mCam.BackgroundColor = $FF0000FF
		mCam.Position(0, 0, -2)
		mCam.Rotate(0,0,0)
		
		'Create model
		For Local i := 1 To 15
			Local mModel := New Model(New Mesh(Mesh.CreateCube()))
			mModel.Pickable(True)
			mModel.Position(Rnd(-4,4), Rnd(-4,4), Rnd(4,20))
			mModel.Name("This is cube #"+i+"   ( "+mModel.X+" : "+mModel.Y+" : "+mModel.Z+" )")
			mModel.Material.Color = Color.RGB(Rnd(0,255),Rnd(0,255),Rnd(0,255))
Print mModel.Name
		Next
		
		'Disable sun
		World.SunColor($FFffffff)
		

		Return False
	End
	
	Method OnUpdate:Int()
		'End with escape key
		#If TARGET<>"html5"
		If KeyHit(KEY_ESCAPE) Then EndApp()
		#End
		
		'Update world
		World.Update()
		
		If KeyDown(KEY_LEFT)  mCam.Move(-0.05,    0,0)
		If KeyDown(KEY_RIGHT) mCam.Move( 0.05,    0,0)
		If KeyDown(KEY_UP)    mCam.Move(    0, 0.05,0)
		If KeyDown(KEY_DOWN)  mCam.Move(    0,-0.05,0)
		If KeyDown(KEY_PAGEUP)    mCam.Move( 0,   0, 0.05)
		If KeyDown(KEY_PAGEDOWN)  mCam.Move( 0,   0,-0.05)
		If KeyDown(KEY_SPACE)
		  mCam.Position( 0,   0, -2.0)
		  mCam.Rotate(0,0,0)
		Endif
		If KeyDown(KEY_A)  mCam.Turn( 0,   -0.5, 0.0)
		If KeyDown(KEY_D)  mCam.Turn( 0,    0.5, 0.0)
		If KeyDown(KEY_W)  mCam.Turn( -0.5,   0, 0.0)
		If KeyDown(KEY_S)  mCam.Turn( 0.5,    0, 0.0)
		If KeyDown(KEY_Q)  mCam.Turn(  0,   0, 0.5)
		If KeyDown(KEY_E)  mCam.Turn( 0.0,    0, -0.5)

		'If MouseHit(0) = True
			If World.CameraPick(mCam, MouseX(), MouseY()) = True
				mModelPicked = World.PickedEntity()
			Else
				mModelPicked = Null
			Endif
		'Endif
		Return False
	End


	Method OnRender:Int()
		'Render world
		World.Render()
		
		'Setup graphics for 2D
		Graphics.Setup2D(0, 0, DeviceWidth(), DeviceHeight())
		
		'Draw FPS
		Local text:String = Graphics.FPS() + " FPS"
		mFont.Draw(8, 8, text)
		text = "Cam x/y/z = " + mCam.X + " : "+ mCam.Y + " : "+ mCam.Z
		mFont.Draw(8, 25, text)
		If mModelPicked <> Null				
			text = "Picked Model = " + mModelPicked.Name
			mFont.Draw(8, 50, text)				
		Endif
		Return False
	End
	
Private
	Field mFont				: Font
	Field mCam				: Camera
	Field mModel			: Model
	Field mModelPicked      : Entity = Null
	Field mPos:Float[3]
	Field out:Int[]
	
End

Function Main:Int()
	New TestApp
	Return False
End
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
Ok, I added your changes. Still, when I move the camera with the cursor keys, it hardly detects anything.:oops:

But Camera.Project works fine so far.
 
Last edited:

innerloop

New member
CX Code Contributor
Joined
Jan 18, 2021
Messages
8
Ok, I added your changes. Still, when I move the camera with the cursor keys, it hardly detects anything.:oops:

But Camera.Project works fine so far.
Fixed, see post with code, there is last fixed version.
 
Last edited:

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
I will move your post and our conversation to a new topic, so Martin topic is not trashed up. Thanks again!
 

innerloop

New member
CX Code Contributor
Joined
Jan 18, 2021
Messages
8
Model.RayTrace
* add ray-vs-sphere (most generic collider) rejection instead of ray-vs-aabb => avoid false rejection in some cases
Mesh.RayTrace
*add triangle backface rejection => less amount of triangles checked => more performance
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
2,846
Model.RayTrace
* add ray-vs-sphere (most generic collider) rejection instead of ray-vs-aabb => avoid false rejection in some cases
Mesh.RayTrace
*add triangle backface rejection => less amount of triangles checked => more performance
Is that a suggestion or did you modify you post above?
 

innerloop

New member
CX Code Contributor
Joined
Jan 18, 2021
Messages
8
* take out arrays from functions -> avoid runtime memory allocation -> more performance
* fix bad code for RaySphereIntersection
* fix wrong calculation of model bounding sphere
* add Camera.ProjectedX and Y (blitz3d style)
* code cleanup
 
Top Bottom