ok here's somethin gto play with, until we get a real solution by somebody who's actually knowing what he's doing, so not by me o_O
This is the fixed version of the Linepicking Volume creator. Wit this settings it's working pretty nicely, say about 99.5% correctly, although of course still slow with high poly stuff, but you may try it with some low poly geometry and see. Maybe somebody can add a faster Linepick:
additionally here's the same function, now demonstrating how it could be used in plain Blitz to create Stencil Shadows:
This is the fixed version of the Linepicking Volume creator. Wit this settings it's working pretty nicely, say about 99.5% correctly, although of course still slow with high poly stuff, but you may try it with some low poly geometry and see. Maybe somebody can add a faster Linepick:
;create shadow volume with the help of Linepick: ;----------------------------------------------- ; make silhouette mesh / shadow volume ; works 99%, pretty slow with high poly stuff (linepick exponential slowdown). Graphics3D 640,480,32,2 SetBuffer BackBuffer() Global helper=CreatePivot() Global helper2=CreatePivot() ; you can easily destroy it when editing these parameters :) Global infi#=50 ; length shadow volume Global pick_radius#=0.0001 Global pick_back#=50 ; pick from n behind light Global divi#=3.0 plane=CreatePlane() ; map TranslateEntity plane,0,-5,0 EntityColor plane,0,255,0 Global camera=CreateCamera() TranslateEntity camera,0,0,-12 light=CreateLight() RotateEntity light,45,45,45 ;cube=CreateSphere(5) ;CreateCube() ; object to cast shadow ;cube=CreateCube() ; object to cast shadow ;cube=CreateCylinder(10) ; object to cast shadow cube=CreateCone(10) ; object to cast shadow RotateEntity cube,45,45,0 EntityPickMode cube,2 lime=CreateSphere() ; position of light ScaleEntity lime,0.1,0.1,0.1 PositionEntity lime,4,4,0 While KeyDown(1)=0 a=(a +2) Mod 360 PositionEntity lime,Sin(a)*4.0,4,Cos(a)*4.0 t1=MilliSecs() vol=make_volume(cube,lime) t2=MilliSecs() UpdateWorld RenderWorld() Text 0,0,"tris "+TrisRendered() Text 0,16,"ms "+(t2-t1) Text 0,32,"space=pause" Flip While KeyDown(57) Delay 1 Wend FreeEntity vol Wend End End Function make_volume(source,lite) ; for every triangle create 2 tris in the shadow volume, where one is ; transposed by "infi" in the direction of lightrays TFormPoint EntityX(lite),EntityY(lite),EntityZ(lite),0,source PositionEntity helper2,TFormedX(),TFormedY(),TFormedZ() tri_count=0 vol=CreateMesh() su2=CreateSurface(vol) For s=1 To CountSurfaces(source) su=GetSurface(source,s) For tri=0 To CountTriangles(su)-1 vx0#=VertexX(su,TriangleVertex(su,tri,0)) vy0#=VertexY(su,TriangleVertex(su,tri,0)) vz0#=VertexZ(su,TriangleVertex(su,tri,0)) vx1#=VertexX(su,TriangleVertex(su,tri,1)) vy1#=VertexY(su,TriangleVertex(su,tri,1)) vz1#=VertexZ(su,TriangleVertex(su,tri,1)) vx2#=VertexX(su,TriangleVertex(su,tri,2)) vy2#=VertexY(su,TriangleVertex(su,tri,2)) vz2#=VertexZ(su,TriangleVertex(su,tri,2)) v0=AddVertex(su2,vx0,vy0,vz0) v1=AddVertex(su2,vx1,vy1,vz1) v2=AddVertex(su2,vx2,vy2,vz2) PositionEntity helper,vx0,vy0,vz0 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v0_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) PositionEntity helper,vx1,vy1,vz1 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v1_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) PositionEntity helper,vx2,vy2,vz2 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v2_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) AddTriangle su2, v0 ,v1 ,v1_b AddTriangle su2, v0_b,v0 ,v1_b AddTriangle su2, v1_b,v1,v2_b AddTriangle su2, v1,v2,v2_b AddTriangle su2, v2,v0_b,v2_b AddTriangle su2, v2,v0,v0_b tri_count=tri_count+6 Next Next UpdateNormals vol EntityPickMode vol,2 EntityFX vol,1 EntityColor vol,0,0,255 RotateEntity vol, EntityPitch(source),EntityYaw(source),EntityRoll(source),1 ; vol is now a shadow volume, containing the silhouette and a lot of enclosed, hidden tris. ;Return ; you may return here to watch this state... ; ------------------------------- ; create a copy without the enclosed tris: ; (cosmetics) remx#=EntityX(source) remy#=EntityY(source) remz#=EntityZ(source) rempitch#=EntityPitch(source) remyaw#=EntityYaw(source) remroll#=EntityRoll(source) PointEntity source,lite MoveEntity source,0,0,.1 RotateEntity source, rempitch,remyaw,remroll vol3=CreateMesh() ; this will be the final shadow volume su3=CreateSurface(vol3) PositionEntity helper ,EntityX(lite),EntityY(lite),EntityZ(lite),1 PointEntity helper,source,0 MoveEntity helper,0,0,-pick_back ; check the visibility of every triangle of the shadow volume from one "step" behind the light ; using Linepicks: ; only silhouette tris should be pickable here! (since the source mesh obscures inner parts, ; as well as the silhouette tris will do so - at least in theory o_O) For i=0 To tri_count-1 x0#=VertexX(su2,TriangleVertex(su2,i,0)) y0#=VertexY(su2,TriangleVertex(su2,i,0)) z0#=VertexZ(su2,TriangleVertex(su2,i,0)) x1#=VertexX(su2,TriangleVertex(su2,i,1)) y1#=VertexY(su2,TriangleVertex(su2,i,1)) z1#=VertexZ(su2,TriangleVertex(su2,i,1)) x2#=VertexX(su2,TriangleVertex(su2,i,2)) y2#=VertexY(su2,TriangleVertex(su2,i,2)) z2#=VertexZ(su2,TriangleVertex(su2,i,2)) x#=(x0+x1+x2)/divi ; get a triangles interpolated center point y#=(y0+y1+y2)/divi z#=(z0+z1+z2)/divi TFormPoint(x,y,z,vol,0) he=helper p=LinePick(EntityX#(he),EntityY#(he),EntityZ#(he) ,TFormedX#()-EntityX#(he),TFormedY#()-EntityY#(he),TFormedZ#()-EntityZ#(he),pick_radius#) If (p=vol) If PickedTriangle()=i ; did we pick the tris of the corresponding center point? v0=AddVertex(su3,x0,y0,z0) ; yes, then it must be a silhouette tris v1=AddVertex(su3,x1,y1,z1) v2=AddVertex(su3,x2,y2,z2) AddTriangle(su3,v0,v1,v2) EndIf EndIf Next ; (undo cosmetics) PositionEntity source, remx,remy,remz FreeEntity vol ; release old volume vol=vol3 EntityColor vol,255,0,0 EntityFX vol,1 Or 16 EntityAlpha vol,0.5 RotateEntity vol, EntityPitch(source),EntityYaw(source),EntityRoll(source),1 Return vol End Function
additionally here's the same function, now demonstrating how it could be used in plain Blitz to create Stencil Shadows:
; stencil shadows in plain blitzbasic ; slow as hell due to LinePicks! ; creates a shadow volume with the help of Linepick: ; experimental (please somebody successfully replace LinePick by Coldet rayintersection function) Graphics3D 640,480,32,2 SetBuffer BackBuffer() Global helper=CreatePivot() Global helper2=CreatePivot() Global infi#=50 ; length shadow volume Global pick_radius#=0.0001 Global pick_back#=50 ; pick from n behind light Global divi#=3.0 ;plane=CreatePlane() ; map ;TranslateEntity plane,0,-5,0 ;EntityColor plane,0,255,0 ; better use a nice terrain to show the stencil shadows in action plane=CreateTerrain(64) For j=0 To 63 For i=0 To 63 ModifyTerrain(plane,i,j,Rnd(0.0,1.0)) Next Next ScaleEntity plane,10,7,10 TerrainShading plane,1 TranslateEntity plane,-320,-7,-320 Global camera=CreateCamera() TranslateEntity camera,0,2,-12 TurnEntity camera,10,0,0 light=CreateLight() ;RotateEntity light,45,45,45 ; object to cast shadow (note: highpoly stuff is extremly slow) ; ------------------------------------------------------------- ;cube=CreateSphere(5) cube=CreateCube() ;cube=CreateCylinder(10) ;cube=CreateCone(10) RotateEntity cube,45,45,0 EntityPickMode cube,2 lime=CreateSphere() ; shows position of light ScaleEntity lime,0.1,0.1,0.1 PositionEntity lime,4,4,0 img=CreateImage(GraphicsWidth(),GraphicsHeight()) ; used to mask nonintersection parts While KeyDown(1)=0 a=(a +2) Mod 360 PositionEntity lime,Sin(a)*4.0,4,Cos(a)*4.0 TurnEntity cube,1,2,3 t1=MilliSecs() vol=make_volume(cube,lime) t2=MilliSecs() ; prepare scene for stencil shadow render EntityFX plane,1 EntityFX cube,1 EntityFX lime,1 EntityColor plane,0,0,0 EntityColor cube,0,0,0 HideEntity lime EntityOrder cube,-1 RenderWorld() ; render shadow volume GrabImage(img,0,0) MaskImage img,0,0,0 ClsColor 96,96,96 Cls DrawImage img,0,0 GrabImage(img,0,0) MaskImage img,96,96,96 ; restore scene for normal render EntityOrder cube,0 EntityFX plane,0 EntityFX cube,0 EntityFX lime,0 EntityColor plane,0,255,0 EntityColor cube,255,255,255 ShowEntity lime If KeyDown(57)<>1 Then HideEntity vol RenderWorld() ; render the scene for the audience ; add stencil shadow 2D layer (pixelperfect sprite may be used instead!) DrawImage img,0,0 Text 0,0,"tris "+TrisRendered() Text 0,16,"ms "+(t2-t1) Text 0,32,"space=show volume" Text 0,48,ReadPixel(MouseX(),MouseY()) And $ff Flip FreeEntity vol Wend End Function make_volume(source,lite) ; for every triangle create 2 tris in the shadow volume, where one is ; transposed by "infi" in the direction of lightrays TFormPoint EntityX(lite),EntityY(lite),EntityZ(lite),0,source PositionEntity helper2,TFormedX(),TFormedY(),TFormedZ() tri_count=0 vol=CreateMesh() su2=CreateSurface(vol) For s=1 To CountSurfaces(source) su=GetSurface(source,s) For tri=0 To CountTriangles(su)-1 vx0#=VertexX(su,TriangleVertex(su,tri,0)) vy0#=VertexY(su,TriangleVertex(su,tri,0)) vz0#=VertexZ(su,TriangleVertex(su,tri,0)) vx1#=VertexX(su,TriangleVertex(su,tri,1)) vy1#=VertexY(su,TriangleVertex(su,tri,1)) vz1#=VertexZ(su,TriangleVertex(su,tri,1)) vx2#=VertexX(su,TriangleVertex(su,tri,2)) vy2#=VertexY(su,TriangleVertex(su,tri,2)) vz2#=VertexZ(su,TriangleVertex(su,tri,2)) v0=AddVertex(su2,vx0,vy0,vz0) v1=AddVertex(su2,vx1,vy1,vz1) v2=AddVertex(su2,vx2,vy2,vz2) PositionEntity helper,vx0,vy0,vz0 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v0_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) PositionEntity helper,vx1,vy1,vz1 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v1_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) PositionEntity helper,vx2,vy2,vz2 PointEntity helper,helper2 MoveEntity helper,0,0,-infi v2_b=AddVertex(su2,EntityX(helper),EntityY(helper),EntityZ(helper)) AddTriangle su2, v0 ,v1 ,v1_b AddTriangle su2, v0_b,v0 ,v1_b AddTriangle su2, v1_b,v1,v2_b AddTriangle su2, v1,v2,v2_b AddTriangle su2, v2,v0_b,v2_b AddTriangle su2, v2,v0,v0_b tri_count=tri_count+6 Next Next UpdateNormals vol EntityPickMode vol,2 EntityFX vol,1 EntityColor vol,0,0,255 RotateEntity vol, EntityPitch(source),EntityYaw(source),EntityRoll(source),1 ; vol is now a shadow volume, containing the silhouette and a lot of enclosed, hidden tris. ; ------------------------------- ; create a copy without the enclosed tris: ; (cosmetics) remx#=EntityX(source) remy#=EntityY(source) remz#=EntityZ(source) rempitch#=EntityPitch(source) remyaw#=EntityYaw(source) remroll#=EntityRoll(source) PointEntity source,lite MoveEntity source,0,0,.1 RotateEntity source, rempitch,remyaw,remroll vol3=CreateMesh() ; this will be the final shadow volume su3=CreateSurface(vol3) PositionEntity helper ,EntityX(lite),EntityY(lite),EntityZ(lite),1 PointEntity helper,source,0 MoveEntity helper,0,0,-pick_back ; check the visibility of every triangle of the shadow volume from one "step" behind the light ; using Linepicks: ; only silhouette tris should be pickable here! (since the source mesh obscures inner parts, ; as well as the silhouette tris will do so - at least in theory o_O) For i=0 To tri_count-1 x0#=VertexX(su2,TriangleVertex(su2,i,0)) y0#=VertexY(su2,TriangleVertex(su2,i,0)) z0#=VertexZ(su2,TriangleVertex(su2,i,0)) x1#=VertexX(su2,TriangleVertex(su2,i,1)) y1#=VertexY(su2,TriangleVertex(su2,i,1)) z1#=VertexZ(su2,TriangleVertex(su2,i,1)) x2#=VertexX(su2,TriangleVertex(su2,i,2)) y2#=VertexY(su2,TriangleVertex(su2,i,2)) z2#=VertexZ(su2,TriangleVertex(su2,i,2)) x#=(x0+x1+x2)/divi ; get a triangles interpolated center point y#=(y0+y1+y2)/divi z#=(z0+z1+z2)/divi TFormPoint(x,y,z,vol,0) he=helper p=LinePick(EntityX#(he),EntityY#(he),EntityZ#(he) ,TFormedX#()-EntityX#(he),TFormedY#()-EntityY#(he),TFormedZ#()-EntityZ#(he),pick_radius#) If (p=vol) If PickedTriangle()=i ; did we pick the tris of the corresponding center point? v0=AddVertex(su3,x0,y0,z0) ; yes, then it must be a silhouette tris v1=AddVertex(su3,x1,y1,z1) v2=AddVertex(su3,x2,y2,z2) AddTriangle(su3,v0,v1,v2) EndIf EndIf Next ; (undo cosmetics) PositionEntity source, remx,remy,remz FreeEntity vol ; release old volume vol=vol3 EntityColor vol,128,128,128 EntityFX vol,1 Or 16 EntityAlpha vol,0.5 RotateEntity vol, EntityPitch(source),EntityYaw(source),EntityRoll(source),1 Return vol End Function