Help with 2d Shadow / Light Code

Blitz3D Forums/Blitz3D Programming/Help with 2d Shadow / Light Code

Roland(Posted 2007) [#1]
Hey all. I'm working on a concept that uses 2d spotlights shining on 3d objects creating shadows. hard to explain, but if you run my code you'll see what i mean.

Unfortunately, I'm having problems getting the "shadowing" to work right. I'm basically using linepicks from the source of the light to test if there is something blocking the light. I then use this to create the mesh that makes up the light on the fly.

Everything seems to work splendidly when the light is facing some directions, but doesn't work at all when you spin the light around. Can anyone help me figure out what I'm doing wrong?

In this code, click and drag on the cube "light" to move it, right-click and drag up and down on it to spin it. If you force the red "light" to go over the green spheres, they should stop the light where it hits them.

I'd be happy to hear other approaches to this too!

thanks,
roland

Graphics3D 800,600,32,2
SeedRnd MilliSecs()


Type light
	Field entity
	Field red
	Field green
	Field blue
	Field cone
	Field conesurf
	Field l
	Field angle#
	Field picker
	Field picked
	Field xspeed#
	Field yspeed#
	Field xtarget#
	Field ytarget#
	Field pickcyl
	Field length#
	Field width#
End Type


Type block
	Field entity
	Field picked
End Type

Type beacon
	Field entity
	Field red
	Field green
	Field blue
	Field activated
End Type


Global pivot = CreatePivot()

Global mainlight = CreateLight(1)
RotateEntity mainlight,30,120,0
PositionEntity mainlight,5,20,20

Global cam = CreateCamera()
PositionEntity cam,0,-5,30
PointEntity cam,pivot

Global ground = CreateCube()
ScaleEntity ground,22,15,1
EntityColor ground,200,200,200
PositionEntity ground,-3,0,0
EntityPickMode ground,2

Global pickedlight = 0
Global resetpicks = 1

Global startmousex
Global startmousey

makelight(0,0,2,255,0,0,45)

makebeacon(5,5,2,0,255,0)

makebeacon(12,5,2,0,255,0)

;WireFrame True

While Not KeyHit(1)



If MouseHit(1) Or MouseHit(2)
	startmousex = MouseX()
	startmousey = MouseY()
	chooselight()
EndIf

If MouseDown(1)
	movelight()
Else
	If resetpicks = 0
		For l.light= Each light
			EntityPickMode l\entity,2
			resetpicks = 1
		Next
	
	EndIf

EndIf


If MouseDown(2)
	rotatelight()
EndIf


updatelights()

If KeyHit(57)
	
	wf = 1-wf
	WireFrame wf
EndIf



UpdateWorld()

RenderWorld()

Text 0,0,pickedlight
l.light = First light

Text 0,20,EntityRoll(l\entity)

;ex# = EntityX#(l\entity)
;ey# = EntityY#(l\entity)
;ez# = EntityZ#(l\entity)

;CameraProject cam,ex,ey,ez

;startx = ProjectedX()
;starty = ProjectedY()

;For a=-l\width To l\width
		
		
;	dx# = Sin(l\angle+a)*l\length
;	dy# = -Cos(l\angle+a)*l\length
			
;	CameraProject cam,dx+ex,dy+ey,z
	
;	endx = ProjectedX()
;	endy = ProjectedY()
	
	;Line startx,starty,endx,endy
	
	
;Next




Flip

Wend


Function makelight(x#,y#,z#,r,g,b,angle#)

	l.light = New light
	l\red = r
	l\green = g
	l\blue = b
	l\angle = angle
	
	l\width = 15
	l\length = 20
	
	l\entity = CreateCube()
	EntityColor l\entity,200,100,100
	PositionEntity l\entity,x,y,z
	l\xtarget = x
	l\ytarget= y
	EntityPickMode l\entity,2


	l\cone = CreateMesh()
	l\conesurf = CreateSurface(l\cone)
	EntityColor l\cone,255,0,0
	EntityFX l\cone,2+32
	
;	l\cone = CreateCone(16)
;	PositionEntity l\cone,x,y-5,z
;	ScaleEntity l\cone,3,5,3
;	EntityColor l\cone,l\red,l\green,l\blue
;	EntityParent l\cone,l\entity
;	EntityBlend l\cone,3

;	l\pickcyl = CreateCylinder(3)
;	ScaleEntity l\pickcyl,.1,5,.1
;	EntityFX l\pickcyl,1
;	EntityColor l\pickcyl,0,0,0
;	PositionEntity l\pickcyl,x,y-5,z
;	EntityParent l\pickcyl,l\entity
	

	RotateEntity l\entity,0,0,l\angle
	


End Function


Function makebeacon(x#,y#,z#,r,g,bl)
	b.beacon = New beacon
	b\red = r
	b\green = g
	b\blue= bl
	
	b\entity = CreateSphere(8)

	PositionEntity b\entity,x,y,z
	
	EntityColor b\entity,b\red,b\green,b\blue
	b\activated = 0
	EntityPickMode b\entity,1
	EntityRadius b\entity,1.25
End Function

Function chooselight()

	CameraPick cam,MouseX(),MouseY()
	If PickedEntity() <> 0 And PickedEntity() <> ground
		For l.light = Each light
			If PickedEntity() = l\entity
				l\picked = 1
				pickedlight = Handle(l)			
			EndIf
		
		Next
	
	Else
		pickedlight = 0
	EndIf

End Function


Function updatelights()
	For l.light = Each light
		l\xspeed = (l\xtarget-EntityX(l\entity))/5	
		l\yspeed = (l\ytarget-EntityY(l\entity))/5	
		
		PositionEntity l\entity,EntityX(l\entity)+l\xspeed,EntityY(l\entity)+l\yspeed,EntityZ(l\entity)	
		
		x# = EntityX#(l\entity)
		y# = EntityY#(l\entity)
		z# = EntityZ#(l\entity)
		
		
		d1x# = Sin(l\angle-l\width)*l\length
		d1y# = -Cos(l\angle-l\width)*l\length

		d2x# = Sin(l\angle+l\width)*l\length
		d2y# = -Cos(l\angle+l\width)*l\length
		
		
		ClearSurface l\conesurf
		startvert = AddVertex(l\conesurf,x,y,z)
		leftvert = AddVertex(l\conesurf,x+d1x,y+d1y,z)
		rightvert = AddVertex(l\conesurf,x+d2x,y+d2y,z)
		
		VertexColor l\conesurf,startvert,255,0,0,255
		VertexColor l\conesurf,leftvert,255,0,0,0
		VertexColor l\conesurf,rightvert,255,0,0,0
		
		;AddTriangle(l\conesurf,v1,v2,v3)
		
		;UpdateNormals l\cone
		
		prevvert = leftvert
		
		For a=-l\width To l\width
		
			For b.beacon = Each beacon
		
				dx# = Sin(l\angle+a)*l\length
				dy# = -Cos(l\angle+a)*l\length
			
				LinePick(x,y,z,x+dx,y+dy,z)
				
				If PickedEntity() <> 0
									
					newvert = AddVertex(l\conesurf,PickedX#(),PickedY#(),z)
					AddTriangle(l\conesurf,prevvert,newvert,startvert)
					prevvert = newvert
					VertexColor l\conesurf,newvert,255,0,0,0
			
				Else
					newvert = AddVertex(l\conesurf,x+dx,y+dy,z)
					AddTriangle(l\conesurf,prevvert,newvert,startvert)
					prevvert = newvert
					VertexColor l\conesurf,newvert,255,0,0,0			
				
				EndIf
		
			Next	
		
		Next
		
		AddTriangle(l\conesurf,prevvert,rightvert,startvert)
		UpdateNormals l\cone
		
	Next
End Function

Function movelight()
	If pickedlight <> 0
		l.light = Object.light(pickedlight)
		EntityPickMode l\entity,0
		resetpicks = 0
		CameraPick cam,MouseX(),MouseY()
		If PickedEntity() = ground
			l\xtarget = PickedX()
			l\ytarget = PickedY()
		EndIf
	EndIf
End Function

Function rotatelight()
	If  pickedlight <> 0
		l.light = Object.light(pickedlight)
		dy# = MouseY()-startmousey
		l\angle = EntityRoll(l\entity)-(dy/20)
		RotateEntity l\entity,0,0,l\angle
	EndIf
End Function



Roland(Posted 2007) [#2]
Damn, found the problem... I was using "linepick" incorrectly (didn't need to add original position to the destination!)

sorry!


Stevie G(Posted 2007) [#3]
A common mistake!! ;)


Ross C(Posted 2007) [#4]
Impressive stuff :o)