Shadow volume

Blitz3D Forums/Blitz3D Programming/Shadow volume

the new version "shadowinclude", i have a problem for procedure tom for robust shadow pleace help me!!! :(
i have optmized other than for fast silhouette

the time render is very slow
;======================================= 
;--------------------------------------- 
; 
;   Name file: Shadow_Include
; 
;   Programmatore: 
;      Caldarulo Vincenzo (Eye & Light) 
;   Descrizione: 
;			Creazione dei volumi d'ombra
; 
;--------------------------------------- 
;======================================= 
Include"commontype.bb"
;Include"cost.bb"
;======================================= 
;--------------------------------------- 
; Variabili ShadowVolume 
;--------------------------------------- 
;=======================================
;
;D3DCULL
Const D3DCULL_NONE				= 1
Const D3DCULL_CW					= 2
Const D3DCULL_CCW					= 3
		
;D3DSHADE_MODE
Const D3DSHADE_FLAT			= 1
Const D3DSHADE_GOURAUD	= 2
Const D3DSHADE_PHONG		= 3

;D3DFILL_MODE
Const D3DFILL_POINT			= 1
Const D3DFILL_WIREFRAME	= 2
Const D3DFILL_SOLID			= 3

;D3DSTENCILOP
Const D3DSTENCILOP_KEEP           = 1
Const D3DSTENCILOP_ZERO           = 2
Const D3DSTENCILOP_REPLACE        = 3
Const D3DSTENCILOP_INCRSAT        = 4
Const D3DSTENCILOP_DECRSAT        = 5
Const D3DSTENCILOP_INVERT         = 6
Const D3DSTENCILOP_INCR           = 7
Const D3DSTENCILOP_DECR           = 8
Const D3DSTENCILOP_FORCE_DWORD    = $7fffffff	;force 32-bit size enum

;D3DCMPFUNC
Const D3DCMP_NEVER               = 1
Const D3DCMP_LESS                = 2
Const D3DCMP_EQUAL               = 3
Const D3DCMP_LESSEQUAL           = 4
Const D3DCMP_GREATER             = 5
Const D3DCMP_NOTEQUAL            = 6
Const D3DCMP_GREATEREQUAL        = 7
Const D3DCMP_ALWAYS              = 8
Const D3DCMP_FORCE_DWORD         = $7fffffff	;force 32-bit size enum

;D3DBLEND
Const D3DBLEND_ZERO              = 1
Const D3DBLEND_ONE               = 2
Const D3DBLEND_SRCCOLOR          = 3
Const D3DBLEND_INVSRCCOLOR       = 4
Const D3DBLEND_SRCALPHA          = 5
Const D3DBLEND_INVSRCALPHA       = 6
Const D3DBLEND_DESTALPHA         = 7
Const D3DBLEND_INVDESTALPHA      = 8
Const D3DBLEND_DESTCOLOR         = 9
Const D3DBLEND_INVDESTCOLOR      = 10
Const D3DBLEND_SRCALPHASAT       = 11
Const D3DBLEND_BOTHSRCALPHA      = 12
Const D3DBLEND_BOTHINVSRCALPHA   = 13
Const D3DBLEND_FORCE_DWORD       = $7fffffff	;force 32-bit size enum
;===>
Const D3DRS_ANTIALIAS          = 2    ; D3DANTIALIASMODE */
Const D3DRS_TEXTUREPERSPECTIVE = 4    ; True For perspective correction */
Const D3DRS_ZENABLE            = 7    ; D3DZBUFFERTYPE (Or True/False For legacy) */
Const D3DRS_FILLMODE           = 8    ; D3DFILL_MODE        */
Const D3DRS_SHADEMODE          = 9    ; D3DFILL_MODE */
Const D3DRS_LINEPATTERN        = 10   ; D3DLINEPATTERN */
Const D3DRS_ZWRITEENABLE       = 14   ; True To enable z writes */
Const D3DRS_ALPHATESTENABLE    = 15   ; True To enable alpha tests */
Const D3DRS_LASTPIXEL          = 16   ; True For Last-pixel on lines */
Const D3DRS_SRCBLEND           = 19   ; D3DBLEND */
Const D3DRS_DESTBLEND          = 20   ; D3DBLEND */
Const D3DRS_CULLMODE           = 22   ; D3DCULL */
Const D3DRS_ZFUNC              = 23   ; D3DCMPFUNC */
Const D3DRS_ALPHAREF           = 24   ; D3DFIXED (long) */
Const D3DRS_ALPHAFUNC          = 25   ; D3DCMPFUNC */
Const D3DRS_DITHERENABLE       = 26   ; True To enable dithering */
Const D3DRS_ALPHABLENDENABLE   = 27   ; True To enable alpha blending */
Const D3DRS_FOGENABLE          = 28   ; True To enable fog blending */
Const D3DRS_SPECULARENABLE     = 29   ; True To enable specular */
Const D3DRS_ZVISIBLE           = 30   ; True To enable z checking */
Const D3DRS_STIPPLEDALPHA      = 33   ; True To enable stippled alpha (RGB device only) */
Const D3DRS_FOGCOLOR           = 34   ; D3DCOLOR */  INT (((a) << 24) Or ((r) << 16) Or ((g) << 8) Or (b)))
Const D3DRS_FOGTABLEMODE       = 35   ; D3DFOGMODE */
Const D3DRS_FOGSTART           = 36   ; Float Fog start (For both vertex And pixel fog) 
Const D3DRS_FOGEND             = 37   ; Float Fog End      */
Const D3DRS_FOGDENSITY         = 38   ; Fog density  */
Const D3DRS_EDGEANTIALIAS      = 40   ; True To enable edge antialiasing */
Const D3DRS_COLORKEYENABLE     = 41   ; True To enable source colorkeyed textures */
Const D3DRS_ZBIAS              = 47   ; LONG Z bias */
Const D3DRS_RANGEFOGENABLE     = 48   ; Enables range-based fog */
; *** STENCIL OPS ***
Const D3DRS_STENCILENABLE      = 52   ; BOOL enable/disable stenciling
Const D3DRS_STENCILFAIL        = 53   ; D3DSTENCILOP To do If stencil test fails
Const D3DRS_STENCILZFAIL       = 54   ; D3DSTENCILOP To do If stencil test passes And Z test fails
Const D3DRS_STENCILPASS        = 55   ; D3DSTENCILOP To do If both stencil And Z tests pass */
Const D3DRS_STENCILFUNC        = 56   ; D3DCMPFUNC fn.  Stencil Test passes If ((ref & mask) stencilfn (stencil & mask)) is True */
Const D3DRS_STENCILREF         = 57   ; INT Reference value used in stencil test */
Const D3DRS_STENCILMASK        = 58   ; Mask value used in stencil test  e.g (0xffffffff)
Const D3DRS_STENCILWRITEMASK   = 59   ; Write mask applied To values written To stencil buffer e.g (0xffffffff)
Const D3DRS_TEXTUREFACTOR      = 60   ; D3DCOLOR used For multi-texture blend */
Const D3DCLEAR_TARGET					= $00000001	;Clear target surface
Const D3DCLEAR_ZBUFFER				= $00000002	;Clear target z buffer
Const D3DCLEAR_STENCIL				= $00000004	;Clear Stencil
;ERRORS
Const D3DERR_ZBUFFER_NOTPRESENT					= 2070
Const D3DERR_STENCILBUFFER_NOTPRESENT		= 2071
Const D3DERR_VIEWPORTHASNODEVICE				= 774
Const DDERR_INVALIDOBJECT								= 130
Const DDERR_INVALIDPARAMS								= $80070057

;===>
Global Direct3DDevice7 = SystemProperty$("Direct3DDevice7")
Global Direct3D7 = SystemProperty$("Direct3D7")
Global DirectDraw7 = SystemProperty$("DirectDraw7")
Global DirectInput7 = SystemProperty$("DirectInput7")
Global AppHWND = SystemProperty$("AppHWND")
Global AppHINSTANCE = SystemProperty$("AppHINSTANCE")

;===>
Type EdgeToEdge
	Field IdModel
	Field cntSurface
	Field Surfaces.ETE_Surface
End Type
;===>
Type ETE_Surface
	Field IdSurface
	Field cntTriangle
	Field IdTriangle.ETE_Triangle[ETE_MaxTriang]
End Type
;===>
Type ETE_Triangle
	Field Normal.Point3D
	Field a.Point3D
	Field b.Point3D
	Field c.Point3D
	Field Triangle
	Field ATriangle
	Field BTriangle
	Field CTriangle
End Type
;===>
;=======================================
;===>
Const SHWTexSize = 128; Parametro di regolazione Ombra
Const sh_level# = 0.1
Const ETE_MaxTriang=65000
Const SHWL3D = 65000
Const Tolerance#=0.01
Const MaxEdgeCamera=1000
;===>
;======================================= 
;===>
Dim TriangleClone.ETE_Triangle(ETE_MaxTriang)
Dim EdgeCamera.Point3D(MaxEdgeCamera)
Dim AD(65000,2)
;===>
;======================================= 
;===>
Global CNTEdgeCamera = 0
;===>
Global Scena = CreatePivot(); CreateSphere(5)
Global result$=""
;===>
Global MeshFront = CreateMesh(); 
Global SurfaceFront = CreateSurface(MeshFront); 
EntityAlpha MeshFront, sh_level 
EntityFX MeshFront,1;4
EntityBlend MeshFront,3
;===>
Global cntLine3D=0
Dim Line3DAX#(SHWL3D)
Dim Line3DAY#(SHWL3D)
Dim Line3DAZ#(SHWL3D)
Dim Line3DBX#(SHWL3D)
Dim Line3DBY#(SHWL3D)
Dim Line3DBZ#(SHWL3D)
;===>
;Creiamo il piano che proietterà l'ombra
;===>
Global SHWScreenImage = CreateImage(SHWTexSize,SHWTexSize)
Global SHWSpriteFront=CreateSprite()
SpriteViewMode SHWSpriteFront,1
EntityFX SHWSpriteFront,1
;===>
Global sh_light.Point3D = New Point3D 
;===>
Global SHW_ETE_Object.EdgeToEdge
;===>
Global sh_lenght# = 0
Global CRValX# = 0
Global CRValY# = 0
Global CRValZ# = 0
;===>
; Equazione del piano e intersezione della retta
Global PickX# = 0
Global PickY# = 0
Global PickZ# = 0
Global PickD# = 0
Global Zfail#=0.0 

;======================================= 
;===>
;=======================
; 
Function CheckVertex_orig%(a.Point3D,b.Point3D)
	If (a\x=b\x)And(a\y=b\y)And(a\z=b\z) Then
		Return True 
	Else
		Return False 
	EndIf 
End Function 

Function CheckVertex%(a.Point3D,b.Point3D)
	If Abs(a\x-b\x) < Tolerance
		If Abs(a\y-b\y) < Tolerance
			If Abs(a\z-b\z) < Tolerance
				Return True 
			Else
				Return False 
			EndIf
		Else
			Return False 
		EndIf
	Else
		Return False 
	EndIf

End Function 
;======================================================================= 
;======================================================================= 
; Shadow Volume For silhouette Method Edge to Edge
;======================================================================= 
;======================================================================= 
;======================= 
; Inizialize Object Shadow
Function SHW_Init()
;	DX_D3D=SystemProperty$("Direct3D7")
;	DX_DEV7=SystemProperty$("Direct3DDevice7")
;	DX_DRAW7=SystemProperty$("DirectDraw7")
;	DX_HWND=SystemProperty$("AppHWND")
;	DX_INSTANCE=SystemProperty$("AppHINSTANCE")
;
;	Direct3DDevice7 = SystemProperty$("Direct3DDevice7")
	;===>
	; Search surface and triangle object
	For n=0 To ETE_MaxTriang
		;===>
		TriangleClone.ETE_Triangle(n) = New ETE_Triangle
		;===>
		TriangleClone(n)\Normal.Point3D = New Point3D
		TriangleClone(n)\a.Point3D = New Point3D
		TriangleClone(n)\b.Point3D = New Point3D
		TriangleClone(n)\c.Point3D = New Point3D
	Next
	;===>
	For n=0 To MaxEdgeCamera
		EdgeCamera.Point3D(n) = New Point3D
	Next
	;===>

	ShwInitDisplay()

End Function 
;======================= 
;
Function ShwInitDisplay()
	;===>
	EntityParent(SHWSpriteFront,Camera) 
;	PositionEntity SHWSpriteFront,-0.005,+0.005,1.001 
	PositionEntity SHWSpriteFront,0,0,1.001 
	;===>
End Function 
;=======================
; Inizialize Object Shadow
Function SHW_InitObject$(model)
	Time$=""
	Tim1=MilliSecs()

	Local Norm.Point3D = New Point3D
	Local IdSurface.ETE_Surface
	Local IdTriang.ETE_Triangle
	Local BTriang.ETE_Triangle
	Local IdN.Point3D
	Local IdA.Point3D
	Local IdB.Point3D
	Local IdC.Point3D
	Local IdBA.Point3D
	Local IdBB.Point3D
	Local IdBC.Point3D
	Local a%
	Local b%
	Local check1%
	Local check2%
	Local check3%
	Local check4%
	Local state1%
	Local state2
	Local state3%
	;===>
	SHW_ETE_Object.EdgeToEdge = New EdgeToEdge
	SHW_ETE_Object\IdModel = model
	;===>
	; Search surface and triangle object
	SHW_ETE_Object\cntSurface = CountSurfaces(model)-1
	For n=0 To SHW_ETE_Object\cntSurface
		;===>
		surf = GetSurface(model,n+1)
		NumFaces = CountTriangles(surf)-1
		;===>
		SHW_ETE_Object\Surfaces.ETE_Surface = New  ETE_Surface
		IdSurface.ETE_Surface = SHW_ETE_Object\Surfaces
		;===>
		IdSurface\IdSurface = surf
		IdSurface\cntTriangle = NumFaces
		For v=0 To NumFaces
			;===>
			IdSurface\IdTriangle.ETE_Triangle[v] = New ETE_Triangle
			IdTriang.ETE_Triangle = IdSurface\IdTriangle[v]
			;===>
			IdTriang\normal.Point3D = New Point3D
			IdTriang\a.Point3D = New Point3D
			IdTriang\b.Point3D = New Point3D
			IdTriang\c.Point3D = New Point3D
			IdN.Point3D = IdTriang\normal
			IdA.Point3D = IdTriang\a
			IdB.Point3D = IdTriang\b
			IdC.Point3D = IdTriang\c
			;===> 
			vert0 = TriangleVertex(surf,v,0)
			vert1 = TriangleVertex(surf,v,1)
			vert2 = TriangleVertex(surf,v,2)
			;===>
			IdA\x = VertexX( surf, vert0) : IdA\y = VertexY( surf, vert0) : IdA\z = VertexZ( surf, vert0)
			;===> 
			IdB\x = VertexX( surf, vert1) : IdB\y = VertexY( surf, vert1) : IdB\z = VertexZ( surf, vert1)
			;===> 
			IdC\x = VertexX( surf, vert2) : IdC\y = VertexY( surf, vert2) : IdC\z = VertexZ( surf, vert2)
			;===>
			;IdN\x= (VertexNX( surf, vert0) + VertexNX( surf, vert1) + VertexNX( surf, vert2))/3
			;IdN\y= (VertexNY( surf, vert0) + VertexNY( surf, vert1) + VertexNY( surf, vert2))/3
			;IdN\z= (VertexNZ( surf, vert0) + VertexNZ( surf, vert1) + VertexNZ( surf, vert2))/3
			CalcNormal( IdN, IdA, IdB, IdC)
			V_3Normalize( IdN, IdN) 
			;===>
			IdTriang\Triangle = v
			IdTriang\ATriangle = -1
			IdTriang\BTriangle = -1
			IdTriang\CTriangle = -1
			;===>
		Next 
		;===>
		; Search adjacent triangle
		;===>
		; ottimizzazione precalcolo
		For a=0 To IdSurface\cntTriangle
			AD(a,0)=1 : AD(a,1) = 1 : AD(a,2) = 1
		Next
		;===>
		For a=0 To IdSurface\cntTriangle
			;===>
			ATriang.ETE_Triangle = IdSurface\IdTriangle[a]
			IdA.Point3D = ATriang\a
			IdB.Point3D = ATriang\b
			IdC.Point3D = ATriang\c
			;===>
			For b=a+1 To IdSurface\cntTriangle
				;===>
				state1=AD(b,0) : state2=AD(b,1) : state3=AD(b,2)
				If a=b Or ( state1=0 And state2=0 And state3=0 ) Then Goto SIDEC
				;===>
				BTriang.ETE_Triangle = IdSurface\IdTriangle[b]
				IdBA.Point3D = BTriang\a
				IdBB.Point3D = BTriang\b
				IdBC.Point3D = BTriang\c
				;*********************************************************************
				; SIDE " A "
				;===>
				; Adjacent side A (il lato A del 1° triangolo confina con lato A del 2° Triangolo)
				If (state1=1)Then
					;===>
					check1 = CheckVertex( IdA, IdBA )
					check2 = CheckVertex( IdB, IdBB )
					check3 = CheckVertex( IdA, IdBB )
					check4 = CheckVertex( IdB, IdBA )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\ATriangle = b
						BTriang\ATriangle = a
						AD(b,0)=0
						Goto SIDEA
						;Stop
					EndIf
					;===>
				EndIf
				;===>
				; Adjacent side A (il lato A del 1° triangolo confina con lato B del 2° Triangolo)
				If (state2=1)Then
					;===>
					check1 = CheckVertex( IdA, IdBB )
					check2 = CheckVertex( IdB, IdBC )
					check3 = CheckVertex( IdA, IdBC )
					check4 = CheckVertex( IdB, IdBB )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\ATriangle = b
						BTriang\BTriangle = a
						AD(b,1)=0
						Goto SIDEA
						;Stop
					EndIf
					;===>
				EndIf
				;===>
				; Adjacent side A (il lato A del 1° triangolo confina con lato C del 2° Triangolo)
				If (state3=1)Then
					;===>
					check1 = CheckVertex( IdA, IdBC )
					check2 = CheckVertex( IdB, IdBA )
					check3 = CheckVertex( IdA, IdBA )
					check4 = CheckVertex( IdB, IdBC )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\ATriangle = b
						BTriang\CTriangle = a
						AD(b,2)=0
						;Stop
					EndIf
					;===>
				EndIf
				.SIDEA
				;===>
				;*********************************************************************
				; SIDE " B "
				;===>
				; Adjacent side A (il lato B del 1° triangolo confina con lato A del 2° Triangolo)
				If (state1=1)Then
					;===>
					check1 = CheckVertex( IdB, IdBA )
					check2 = CheckVertex( IdC, IdBB )
					check3 = CheckVertex( IdB, IdBB )
					check4 = CheckVertex( IdC, IdBA )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\BTriangle = b
						BTriang\ATriangle = a
						AD(b,0)=0
						Goto SIDEB
						;Stop
					EndIf 
					;===>
				EndIf 
				;===>
				; Adjacent side A (il lato B del 1° triangolo confina con lato B del 2° Triangolo)
				If (state2=1)Then
					;===>
					check1 = CheckVertex( IdB, IdBB )
					check2 = CheckVertex( IdC, IdBC )
					check3 = CheckVertex( IdB, IdBC )
					check4 = CheckVertex( IdC, IdBB )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\BTriangle = b
						BTriang\BTriangle = a
						AD(b,1)=0
						Goto SIDEB
						;Stop
					EndIf
					;===>
				EndIf
				;===>
				; Adjacent side A (il lato B del 1° triangolo confina con lato C del 2° Triangolo)
				If (state3=1)Then
					;===>
					check1 = CheckVertex( IdB, IdBC )
					check2 = CheckVertex( IdC, IdBA )
					check3 = CheckVertex( IdB, IdBA )
					check4 = CheckVertex( IdC, IdBC )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\BTriangle = b
						BTriang\CTriangle = a
						AD(b,2)=0
						;Stop
					EndIf
					;===>
				EndIf
				.SIDEB
			;===>
				;*********************************************************************
				; SIDE " C "
				;===>
				; Adjacent side A (il lato C del 1° triangolo confina con lato A del 2° Triangolo)
				If (state1=1)Then
					;===>
					check1 = CheckVertex( IdC, IdBA )
					check2 = CheckVertex( IdA, IdBB )
					check3 = CheckVertex( IdC, IdBB )
					check4 = CheckVertex( IdA, IdBA )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\CTriangle = b
						BTriang\ATriangle = a
						AD(b,0)=0
						Goto SIDEC
						;Stop
					EndIf
				;===>
				EndIf
				;===>
				; Adjacent side A (il lato C del 1° triangolo confina con lato B del 2° Triangolo)
				If (state2=1)Then
					;===>
					check1 = CheckVertex( IdC, IdBB )
					check2 = CheckVertex( IdA, IdBC )
					check3 = CheckVertex( IdC, IdBC )
					check4 = CheckVertex( IdA, IdBB )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\CTriangle = b
						BTriang\BTriangle = a
						AD(b,1)=0
						Goto SIDEC
						;Stop
					EndIf
					;===>
				EndIf 
				;===>
				; Adjacent side A (il lato C del 1° triangolo confina con lato C del 2° Triangolo)
				If (state3=1)Then
					;===>
					check1 = CheckVertex( IdC, IdBC )
					check2 = CheckVertex( IdA, IdBA )
					check3 = CheckVertex( IdC, IdBA )
					check4 = CheckVertex( IdA, IdBC )
					;===>
					If  (check1 And check2) Or (check3 And check4) Then
						ATriang\CTriangle = b
						BTriang\CTriangle = a
						AD(b,2)=0
						;Stop
					EndIf
					;===>
				EndIf
				.SIDEC
				;===>
			Next
			;===>
		Next 
		;===>
	Next
	;===>
	Delete Norm
	;===>
	Tim2=MilliSecs()
	Time$="Time Precalcolo: "+(Tim2-Tim1)
	Return Time$
	;===>
End Function 
;=======================
; Inizialize Object Shadow
Function CloneListTriangle(dst.ETE_Triangle,src.ETE_Triangle)
	;===>
	V_3Copy( dst\Normal, src\Normal)
	V_3Copy( dst\a, src\a)
	V_3Copy( dst\b, src\b)
	V_3Copy( dst\c, src\c)
	dst\Triangle = src\Triangle
	dst\ATriangle = src\ATriangle
	dst\BTriangle = src\BTriangle
	dst\CTriangle = src\CTriangle
	;===>
End Function 
;=======================
Function ResetShadowVolume()
	ClearSurface SurfaceFront;
	CNTEdgeCamera = 0

End Function 
;======================= 
; Shadows Volume start 
Function ShadowVolume$( Light, LightLenght, ShowVol=False, SBHardware=False )
	;===>
	ResetShadowVolume()
	;===>
	sh_light\x = EntityX(Light) : sh_light\y = EntityY(Light) : sh_light\z = EntityZ(Light) 
	sh_lenght = LightLenght 
	;===>
	cntLine3D=0
	;===>
	UpdateWorld()
	;===>
	result$ = ShadowVolumeCreate3()
	;===>
	ShadowVolumeStenciBuffer( ShowVol ) ; gestione hardware
	;===>
	Return result$
	;===>
End Function 
;=======================
; Calcolo del raggio
; 
Function CalcRay(Rtn.Point3D,val1.Point3D, val2.Point3D, Leght#)
	;----> 
	CRValX# = val1\x - val2\x; 
	CRValY# = val1\y - val2\y; 
	CRValZ# = val1\z - val2\z;
	;----> 
	do# = (1.0 / Sqr( ( CRValX * CRValX ) + ( CRValY * CRValY ) + ( CRValZ * CRValZ ) ) ) * Leght
	;---->
	Rtn\x = val1\x + ( CRValX * do ); 
	Rtn\y = val1\y + ( CRValY * do ); 
	Rtn\z = val1\z + ( CRValZ * do );
	;----> 
End Function 

;=======================
; Intersezione piano - retta
; questa fuzione verrà divisa in equazione del piano e intersezione della retta  per ottimizzazione maggiore 
Function Pick_GetCoordinate( Retta.Point3D, RettaVect.Point3D, P1.Point3D, P2.Point3D, P3.Point3D )
	;===>
	Local DirCam.Point3D = New Point3D
	; fattori Equazione piano
	Local a#
	Local b#
	Local c#
	Local d#
	;===>
	Local k#
	;===>
	; Equazione del piano
	; a = (y2-y1)*(z3-z1) - (z2-z1)*(y3-y1)
	; b = (z2-z1)*(x3-x1) - (x2-x1)*(z3-z1);
	; c = (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1);

	; d =((z2-z1)*(y3-y1) - (y2-y1)*(z3-z1))*x1 + 
	;		((x2-x1)*(z3-z1) - (z2-z1)*(x3-x1))*y1 + 
	;		((y2-y1)*(x3-x1) - (x2-x1)*(y3-y1))*z1;
	;===>
	a = ((P2\y-P1\y)*(P3\z-P1\z)) - ((P2\z-P1\z)*(P3\y-P1\y));
	b = ((P2\z-P1\z)*(P3\x-P1\x)) - ((P2\x-P1\x)*(P3\z-P1\z));
	c = ((P2\x-P1\x)*(P3\y-P1\y)) - ((P2\y-P1\y)*(P3\x-P1\x));

	d =	((P2\z-P1\z)*(P3\y-P1\y) - (P2\y-P1\y)*(P3\z-P1\z))*P1\x + ((P2\x-P1\x)*(P3\z-P1\z) - (P2\z-P1\z)*(P3\x-P1\x))*P1\y + ((P2\y-P1\y)*(P3\x-P1\x) - (P2\x-P1\x)*(P3\y-P1\y))*P1\z;

;	a =  (P1\y*P2\z)+(P2\y*P3\z)+(P1\z*P3\y)-(P3\y*P2\z)-(P3\z*P1\y)-(P2\y*P1\z);
;	b = -(P1\x*P2\z)-(P1\z*P3\x)-(P2\x*P3\z)+(P3\x*P2\z)+(P1\x*P3\z)+(P2\x*P1\z);
;	c =  (P1\x*P2\y)+(P1\y*P3\x)+(P2\x*P3\y)-(P2\y*P3\x)-(P1\x*P3\y)-(P2\x*P1\y);
;	d = -(P1\x*P2\y*P3\z)-(P1\y*P2\z*P3\x)-(P2\x*P3\y*P1\z)+(P3\x*P2\y*P1\z)+(P3\y*P2\z*P1\x)+(P2\x*P1\y*P3\z);

	; ax+by+cz+d=0   =>  a*x+b*y+c*z+d=0

	;===>
	; Assegnazione termini noti
	; Retta - Retta vettore ( l m n )
	;===>
	;k =   (( a*x0 + b*y0 + c*z0 + d ) 
	;		- ---------------------------
	;					( a*l + b*m + c*n));

	k = -(( a*Retta\x + b*Retta\y + c*Retta\z + d ) / ( a*RettaVect\x + b*RettaVect\y + c*RettaVect\z));

	;===>
	; Intersezione
	PickX = Retta\x + ( RettaVect\x*k );
	PickY= Retta\y + ( RettaVect\y*k );
	PickZ = Retta\z + ( RettaVect\z*k );
	;===>
	PickD = ( a*Retta\x + b*Retta\y + c*Retta\z + d )/Sqr( a*a + b*b + c*c );

End Function 

;=======================
; 
Function CreatePolygon( IdA.Point3D, RayA.Point3D, RayB.Point3D, IdB.Point3D)
	Local va=0
	Local vb=0
	Local vc=0
	Local vd=0
	;===>
	va = AddVertex(SurfaceFront,  IdA\x,			IdA\y, 			IdA\z ); 
	vb = AddVertex(SurfaceFront,  RayA\x,	RayA\y,		RayA\z ); 
	vc = AddVertex(SurfaceFront,  RayB\x,	RayB\y,		RayB\z ); 
	vd = AddVertex(SurfaceFront,  IdB\x,			IdB\y, 			IdB\z ); 
	;===>
	AddTriangle(SurfaceFront, va, vb, vc); faccia 1/3 a 
	AddTriangle(SurfaceFront, va, vc, vd); faccia 1/3 b
	;===>
	Line3DAX(cntLine3D) = IdA\x : Line3DAY(cntLine3D) = IdA\y : Line3DAZ(cntLine3D) = IdA\z
	Line3DBX(cntLine3D) = IdB\x : Line3DBY(cntLine3D) = IdB\y : Line3DBZ(cntLine3D) = IdB\z
	cntLine3D=cntLine3D+1
;	;===================================================
;	;===>
;	;TEST
;	Local Rrt.Point3D = New Point3D
;	Local P1.Point3D = New Point3D
;	Local P2.Point3D = New Point3D
;	Local P3.Point3D = New Point3D
;	Local PNormal.Point3D = New Point3D
;	;===>
;	TFormPoint 0, 0 , Zfail , SHWSpriteFront, 0
;	P1\x = TFormedX() : P1\y = TFormedY() : P1\z = TFormedZ()
;	TFormPoint 0, 1 , Zfail , SHWSpriteFront, 0
;	P2\x = TFormedX() : P2\y = TFormedY() : P2\z = TFormedZ()
;	TFormPoint 1, 0 , Zfail , SHWSpriteFront, 0
;	P3\x = TFormedX() : P3\y = TFormedY() : P3\z = TFormedZ()
;	CalcNormal(PNormal,P1,P2,P3)
;	V_3Normalize( PNormal, PNormal )
;	;coordinate di test 
;	P1\x = -5 : P1\y = -5 : P1\z = Zfail
;	P2\x = -5 : P2\y = 5 : P2\z = Zfail
;	P3\x = 5 : P3\y = -5 : P3\z = Zfail
;	V_3Dec(RayA,RayA,IdA)
;	V_3Normalize( RayA, RayA )
;	Dot# = V_3Dot( PNormal, RayA ) 
;	If Dot<0 Then 
;			;===>
;			V_3Dec(RayB,RayB,IdB)
;			V_3Normalize( RayB, RayB )
;			;===>
;			Pick_GetCoordinate( IdA, RayA, P1, P2, P3 )
;			Line3DAX(cntLine3D) = PickX : Line3DAY(cntLine3D) = PickY : Line3DAZ(cntLine3D) = PickZ
;			
;			EdgeCamera(CNTEdgeCamera)\x = PickX : EdgeCamera(CNTEdgeCamera)\y = PickY : EdgeCamera(CNTEdgeCamera)\z = PickZ
;			CNTEdgeCamera=CNTEdgeCamera+1
;			;===>
;			Pick_GetCoordinate(  IdB, RayB, P1, P2, P3 )
;			Line3DBX(cntLine3D) = PickX : Line3DBY(cntLine3D) = PickY : Line3DBZ(cntLine3D) = PickZ
;		
;			EdgeCamera(CNTEdgeCamera)\x = PickX : EdgeCamera(CNTEdgeCamera)\y = PickY : EdgeCamera(CNTEdgeCamera)\z = PickZ
;			CNTEdgeCamera=CNTEdgeCamera+1
;			;===>
;			cntLine3D=cntLine3D+1
;			;===>
;	EndIf 
;	;===>
;	Delete PNormal
;	Delete Rrt
;	Delete P1
;	Delete P2
;	Delete P3
;
End Function
;=======================
; Creazione volume
; forse si può fare ancora qualcosina!!
Function ShadowVolumeCreate3$()
	;===> 
	t0=MilliSecs()
	;===> 
	Local Result$ = ""
	;===> 
	Local RayA.Point3D = New Point3D 
	Local RayB.Point3D = New Point3D 
	Local RayC.Point3D = New Point3D
	Local Norm.Point3D = New Point3D
	Local MidPoint.Point3D = New Point3D
	Local NormLight.Point3D = New Point3D
	;===> 
	Local IdA.Point3D
	Local IdB.Point3D
	Local IdC.Point3D
	Local IdN.Point3D
	Local IdCLT.ETE_Triangle
	Local Surfaces.ETE_Surface
	;===> 
	Local CNTFront=0
	Local CNTBack=0
	Local surf=0
	Local Dot#=0
	Local check1 = -1
	Local check2 = -1
	Local check3 = -1

	Local TriangA = 0
	Local TriangB = 0
	Local TriangC = 0
	;===>
	Local v=0
	Local v1=0
	Local aSurf=0
	;===>
	
	For SHW_ETE_Object.EdgeToEdge = Each EdgeToEdge
		;===>
		; Cerchiamoci i vertici faccia vista verso la luce
		Surfaces = SHW_ETE_Object\Surfaces
		For aSurf = 0 To SHW_ETE_Object\cntSurface
			;===>
			If Surfaces=Null Then Goto ErrorSurf
			surf = Surfaces\IdSurface
			dwNumFaces = Surfaces\cntTriangle
			v1=0
			;===>
			For v=0 To dwNumFaces
				;===>
				IdCLT = TriangleClone(v)
				CloneListTriangle( IdCLT,Surfaces\IdTriangle[v] )
				IdA = IdCLT\a
				IdB = IdCLT\b
				IdC = IdCLT\c
				IdN = IdCLT\Normal
				;===>
				;associamo le trasformazioni ai vertici
				TFormPoint IdA\x, IdA\y , IdA\z, SHW_ETE_Object\IdModel, 0
				IdA\x = TFormedX() : IdA\y = TFormedY() : IdA\z = TFormedZ()
				;===> 
				TFormPoint IdB\x, IdB\y , IdB\z, SHW_ETE_Object\IdModel, 0
				IdB\x = TFormedX() : IdB\y = TFormedY() : IdB\z = TFormedZ() 
				;===> 
				TFormPoint IdC\x, IdC\y , IdC\z, SHW_ETE_Object\IdModel, 0
				IdC\x = TFormedX() : IdC\y = TFormedY() : IdC\z = TFormedZ() 
				;===>
				TFormNormal  IdN\x, IdN\y , IdN\z, SHW_ETE_Object\IdModel, 0
				Norm\x = TFormedX() : Norm\y = TFormedY() : Norm\z = TFormedZ()
				;Stop
				V_3Mid(MidPoint, IdA, IdB, IdC) 
				V_3Dec(NormLight, MidPoint, sh_light)
				V_3Normalize( NormLight, NormLight )
				Dot# = V_3Dot( Norm, NormLight ) 
				;===>
				; Marchiamo i vertici non rivolti verso la luce
				If Dot#=>0.0 Then
					;===>
					CNTFront=CNTFront+1
					v1=v1+1
					;===>
				Else
					;===>
					IdCLT\Triangle  = -1
					CNTBack=CNTBack+1
					;===>
				EndIf
				;===> 
			Next
			;===>
			; Ora creiamo il volume
			TriangA = 0
			TriangB = 0
			TriangC = 0
			For v=0 To dwNumFaces
				;===>
				IdCLT = TriangleClone(v)
				;===>
				; Saltiamo il triangolo se è a -1
				If IdCLT\Triangle<0 Then Goto continue
				;===>
				TriangA = IdCLT\ATriangle
				TriangB = IdCLT\BTriangle
				TriangC = IdCLT\CTriangle
				If TriangA>-1 Then check1 = TriangleClone(TriangA)\Triangle Else check1 = -1
				If TriangB>-1 Then check2 = TriangleClone(TriangB)\Triangle Else check2 = -1
				If TriangC>-1 Then check3 = TriangleClone(TriangC)\Triangle Else check3 = -1
				;===>
				If check1>-1 And check2>-1 And check3>-1  Then Goto continue
				;===>
				;Stop
				IdA =  IdCLT\a
				IdB =  IdCLT\b
				IdC =  IdCLT\c
				;===>
				;Edge A
				If check1<0 Then

					;===>
					;Calcolo raggio A
					CalcRay( RayA, IdA, sh_light, sh_lenght)
					;===>
					;Calcolo raggio B
					CalcRay( RayB, IdB, sh_light, sh_lenght)
					;===>
					CreatePolygon(IdA,RayA,RayB,IdB)
					;===>
				EndIf
				;===>
				;Edge B
				If check2<0 Then
					;===>
					;Calcolo raggio B
					CalcRay( RayB, IdB, sh_light, sh_lenght)
					;===>
					;Calcolo raggio C
					CalcRay( RayC, IdC, sh_light, sh_lenght)
					;===>
					CreatePolygon(IdB,RayB,RayC,IdC)
					;===>
				EndIf 
				;===>
				;Edge C
				If check3<0 Then
					;===>
					;Calcolo raggio A
					CalcRay( RayA, IdA, sh_light, sh_lenght)
					;===>
					;Calcolo raggio C
					CalcRay( RayC, IdC, sh_light, sh_lenght)
					;===>
					CreatePolygon(IdC,RayC,RayA,IdA)
					;===>
				EndIf 
				;===>
				.continue
				;===>
			Next 
			;===>
			Surfaces = After Surfaces
			.ErrorSurf
			;===>
		Next
		;===>
	Next
	;===> 
	For v=0 To CNTEdgeCamera-1 Step 2
		;===> 
		va = AddVertex(SurfaceFront,  EdgeCamera(v+0)\x, EdgeCamera(v+0)\y, EdgeCamera(v+0)\z ); 
		vc = AddVertex(SurfaceFront,  EdgeCamera(v+1)\x, EdgeCamera(v+1)\y, EdgeCamera(v+0)\z ); 
		vb = AddVertex(SurfaceFront,  EdgeCamera(v+2)\x, EdgeCamera(v+2)\y, EdgeCamera(v+0)\z ); 
		;===>
		AddTriangle(SurfaceFront, va, vb, vc); faccia 1/3 a 
		;===> 
	Next
	;===>
	Delete MidPoint
	Delete NormLight
	Delete Norm
	Delete RayA
	Delete RayB
	Delete RayC
	;===>
	t1=MilliSecs()
	t2=t1-t0
	Result$=Result$+"==> Face Front: "+CNTFront+"  Face Back: "+CNTBack+"  Edge: "+cntLine3D + " Tim-Vert: " + t2 
	;===> 
	Return Result$
	;===> 
End Function 
;=======================
;
Function SHWLine3D()
	;===>
	Color 0,255,0
	;===>
	For a=0 To cntLine3D-1
		Line3D( Line3DAX(a), Line3DAY(a), Line3DAZ(a), Line3DBX(a), Line3DBY(a), Line3DBZ(a))
	Next
	cntLine3D=0
	;===>
	Color 255,255,255
	;===>
End Function
;=======================
; Creazione immagine ombra
; Fast2 ?
Function ShadowVolumeStenciBuffer_orig(ShowVol)
	EntityColor SHWSpriteFront, 5, 5, 5
	EntityAlpha SHWSpriteFront, 0.3
	;===>
	;SetBuffer  TextureBuffer(ShwTex1)
	;Cls 
	SetBuffer BackBuffer()
	;======================================================================
	;PASS 1
	;===>
	;Render object modal standard
	;===>
	HideEntity SHWSpriteFront
	;colour buffer OFF
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CCW)
	SetRenderState( Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True );
	SetRenderState( Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_ONE );
	SetRenderState( Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_ONE );
	;lighting ON
	SetRenderState( Direct3DDevice7, D3DRS_AMBIENT, AMB_LIGHT );
	SetRenderState( Direct3DDevice7, D3DRS_LIGHTING, True );
	;depth buffer ON (Write+test)
	SetRenderState( Direct3DDevice7, D3DRS_ZENABLE, True );
	SetRenderState( Direct3DDevice7, D3DRS_ZWRITEENABLE, True );
	;stencil buffer OFF
	SetRenderState( Direct3DDevice7, D3DRS_STENCILENABLE, False );
	DeviceClear(Direct3DDevice7, 7, $00008080, 1, 0)
	CameraClsMode Camera, True, True
	;===>
	If ShowVol Then
		ShowEntity MeshFront
		EntityColor MeshFront, 255, 0,0
		EntityFX MeshFront,1;+16
	Else
		HideEntity MeshFront
	EndIf
	;===>
	ShowEntity scena
	;===>
	RenderWorld
	;===>
	EntityColor MeshFront,10,0,0
	EntityFX MeshFront,1
	;===>
	;======================================================================
	;PASS 2
	;===>
	CameraClsMode Camera, False, False
	HideEntity scena
	ShowEntity MeshFront
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, True)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_ALWAYS)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILREF, 1)
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_ZERO)
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_ONE)
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CW)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_INCR)
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_DECR)
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CCW)
	RenderWorld
	;===>
	HideEntity MeshFront
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL)
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_ONE )
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_ONE )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, True)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True)
	ShowEntity SHWSpriteFront
	;===>
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, False)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True)
	HideEntity SHWSpriteFront

End Function

Function ShadowVolumeStenciBuffer(ShowVol)
	EntityColor SHWSpriteFront, 5, 5, 5
	EntityAlpha SHWSpriteFront, 0.3
	;===>
	SetBuffer BackBuffer()
	;===>
	HideEntity SHWSpriteFront
	;======================================================================
	;PASS 1
	;===>
	;Render object modal standard
	;===>
	;colour buffer OFF
	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE, True) 
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, False)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, False)
	DeviceClear(Direct3DDevice7, 7,$00008080,1,0)
	CameraClsMode Camera, True, True
	;===>
	If ShowVol Then
		ShowEntity MeshFront
		EntityColor MeshFront, 255, 0,0
		EntityFX MeshFront,1;+16
	Else
		HideEntity MeshFront
	EndIf
	;===>
	ShowEntity scena
	;===>
	RenderWorld
	;===>
	HideEntity scena
	EntityColor MeshFront,10,0,0
	EntityFX MeshFront,1
	;===>
	;======================================================================
	;PASS 2
	;===>
	CameraClsMode Camera, False, False
	ShowEntity MeshFront
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE,False)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE,True)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_ALWAYS)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILREF, 1)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILMASK,$ffffffff)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILWRITEMASK,$ffffffff)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True)
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_ZERO)
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_ONE)
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CCW)
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CW)
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CCW)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR)
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE,     True )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE,    False )
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, False )			
	;===>
	;HideEntity MeshFront
	SetRenderState(Direct3DDevice7, D3DRS_ZENABLE,       False )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, True )
	SetRenderState(Direct3DDevice7, D3DRS_FOGENABLE, False)	

	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True )
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA )
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA )

	SetRenderState(Direct3DDevice7, D3DRS_STENCILREF,  1 )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP )
	;===>
	ShowEntity SHWSpriteFront
	RenderWorld
	;===>
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, False)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True)
	HideEntity SHWSpriteFront
	RenderWorld

End Function