OK, I have solved a few issues. Still not perfect, and the ripples it does provide are tawdry affairs, so you will be able to improve on this. Use the F key to select the ripple scheme - nothing special, just some values I was playing with. The A key autoincrements ripple values, Ins/Del, Home/End and Page Up/Page Down keys manually alter the ripples, +/- on the numeric pad changes the depth and the R key resets. The space key just rotates the cylinder so you get an external view of the distortion applied.
Edit. BTW Although not particularly noticeable in this code, if you do see bad normals being generated, then it may be partly due to the use of scalemesh so you could use scaleentity instead. I have not made that change here though as the twisting you do for your tunnel effect introduces enough irregularity to stop this occuring for the most part. I think it is a problem with updatenormals.
Edit. BTW Although not particularly noticeable in this code, if you do see bad normals being generated, then it may be partly due to the use of scalemesh so you could use scaleentity instead. I have not made that change here though as the twisting you do for your tunnel effect introduces enough irregularity to stop this occuring for the most part. I think it is a problem with updatenormals.
; ID: 939 ; Author: Olive ; Date: 2004-02-20 07:58:15 ; Title: Tunnel Effect ; Description: A tunnel effect like in demos ; CreateMyCylinder Example ; ---------------------- ; By Pigmin (alias Olive) 02-20-2004 ; ; pigmin@... ; ; meet me at www.blitz3dfr.com (forum section) ; ; ; ; With wonderfull function : ; ; CreateMyCylinder ; ---------------------- ; By: Todd Riggins 12-22-2003 ; ; a CreateCylinder blitz-like function. Does the Same thing. Just wanted to do ; this to see how to actaully create a cylinder with the addvertex/addtriangle ; commands. Just thought I would share. ; ----------------- ; 2004-2-19 1:10:00 ; - Added ring segments. Ring Segment param of zero acts like the ; blitz-like Function. IE: no ring segments. ; - The added ring segments adds vertices to help bend cylinder tunnels or angle ; pipe meshs. Ofcoarse, you will need to add your own code to manipulate the ; cylinder's vertices. ; 2004-2-18 21:00:00 ; - Fixed normal vectors problem: Needed to have cylinder ends as seperate surface ; ; Left sphere is created by the CreateMyCylinder function. ; Right sphere is created by blitz's CreateCylinder command. ; ; Controls: ; - Use mouse to rotate the cylinders ; - wireframe toggle ; - Esc key to escape ; rediminsionable arrays Dim tRing(0) Dim bRing(0) Type TCtrlPoint Field x# Field y# End Type Const MAX_CTRL_POINTS = 24 Const TWIST# = 30 Global CtrlPoints.TCtrlPoint[MAX_CTRL_POINTS] Global CtrlPointsPhase% = 0 Global CtrlPointsPhase2% = 0 Graphics3D 640,480,0,2 SetBuffer BackBuffer() AmbientLight 32,0,0 camera=CreateCamera() CameraClsColor camera, 255,0,0 CameraRange camera,.1,1000 light=CreateLight() RotateEntity light,45,0,0 ; enter how many segments the sphere has Global vsegs=24 Global rsegs=MAX_CTRL_POINTS ;Texture tex=CreateTexture(32,32,1+8) : ScaleTexture tex,.25,.25 SetBuffer(TextureBuffer(tex)) colR = 128 For j = 0 To 31 Step 8 colR = 64 - colR For i = 0 To 31 Step 8 colR = 64 - colR Color colR,colR,colR Rect(i,j,8,8,1) Next Next SetBuffer (BackBuffer()) ;Texture2 tex2=CreateTexture(64,64,1+4+8) : ScaleTexture tex2,.1,.25 SetBuffer(TextureBuffer(tex2)) For j = 0 To 16 colR = Rand(10,64) colG = Rand(0,128) colB = Rand(0,180) Color colR,colG,colB Rect(Rand(0,63),Rand(0,63),Rand(1,2),Rand(1,31)) Rect(Rand(0,63),Rand(0,63),Rand(1,31),Rand(1,2)) Next SetBuffer (BackBuffer()) TextureBlend tex,2 TextureBlend tex2,3 ; Create Cylinder manually mycylinder=CreateMyCylinder(vsegs,rsegs,False,0) ScaleMesh mycylinder,6,40,6 RotateMesh mycylinder,90,0,0 FlipMesh mycylinder PositionEntity mycylinder,0,0,40 EntityTexture mycylinder,tex,0,0 EntityTexture mycylinder,tex2,0,1 mycylindercopy = CopyMesh(mycylinder) HideEntity mycylindercopy ;allocate control points For i = 0 To MAX_CTRL_POINTS CtrlPoints[i] = New TCtrlPoint CtrlPoints[i]\x# = (i*260/MAX_CTRL_POINTS) CtrlPoints[i]\y# = (i*460/MAX_CTRL_POINTS) Next xx#=0 cnt#=0 freqX = 1 freqY = 4 rippx# = 0.0 rippy# = 0.0 rippz# = 0.0 depth# = 2.0 While Not KeyDown( 1 ) If (Not Rand(0,200)) freqY = Rand(0,4) EndIf If (Not Rand(0,400)) freqX = Rand(1,4) EndIf CtrlPointsPhase = CtrlPointsPhase + freqX CtrlPointsPhase2 = CtrlPointsPhase2 + freqY cnt=wrapvalue(cnt#+.01*(freqX+freqY)*.5,0,1) PositionTexture Tex,0,cnt# PositionTexture Tex2,cnt#,cnt# If KeyHit(19) Then ; R rippx=0 : rippy=0 : rippz=0 EndIf If KeyDown(29) Then Multiplier#=1 Else Multiplier#=0.1 rippx=rippx+(KeyDown(210)-KeyDown(211))*multiplier ; ins/del rippy=rippy+(KeyDown(199)-KeyDown(207))*multiplier ; home/end rippz=rippz+(KeyDown(201)-KeyDown(209))*multiplier ; page up/page down depth=depth+(KeyDown(078)-KeyDown(074))*multiplier ; numeric +/- If KeyHit(30) Then autoinc=Not autoinc If autoinc Then rippx=rippx+multiplier rippy=rippy+multiplier rippz=rippz+multiplier EndIf form=(form+KeyHit(33)) Mod 4 Tunnel_effect(mycylinder,mycylindercopy,CtrlPointsPhase,CtrlPointsPhase2,rippx,rippy,rippz,cnt*360,depth,form) If KeyHit(17) Then wire=Not wire : WireFrame wire If KeyDown(57) Then RotateEntity mycylinder,-90,0,0 Else RotateEntity mycylinder,0,0,0 RenderWorld Color 255,255,255 Text 0,0,"Ripple x "+RippX+" Ripple Y "+RippY+" Ripple Z "+RippZ+" Depth "+Depth+" Form "+form Flip Wend End Function Tunnel_Effect(mesh, mesh_original, phase, phase2, fx#, fy#, fz#, offset#, depth#, form) Local v# cntsurf = CountSurfaces(mesh) surf=GetSurface(mesh,cntsurf) surf_original=GetSurface(mesh_original,cntsurf) cnt=CountVertices(surf) For s=0 To rsegs deltax# = Cos(wrapvalue(Ctrlpoints[s]\x# + phase,0,360))*(TWIST#/(s+1)) deltay# = Sin(wrapvalue(Ctrlpoints[s]\y# + phase2,0,360))*(TWIST#/(s+1)) firstVertice = s*(vsegs+1) endVertice = firstVertice + vsegs For a=firstVertice To endVertice x#=VertexX#(surf_original,a) y#=VertexY#(surf_original,a) z#=VertexZ#(surf_original,a) Select form Case 0 addx#=Sin(wrapvalue(z*x*fx+offset,0,360))*depth addy#=Cos(wrapvalue(z*y*fy+offset,0,360))*depth Case 1 If a=endVertice Then v=firstVertice Else v=a ; mind the gap ! addx#=Sin(wrapvalue(v*fx,0,360))*depth addy#=Cos(wrapvalue(v*fy,0,360))*depth Case 2 addx#=Cos(wrapvalue(x*fx+offset,0,360))*depth addy#=Sin(wrapvalue(y*fy+offset,0,360))*depth addz#=-addx Case 3 inc=inc+1 : v = (inc Mod vsegs)*S ; mind the gap ! addx#=Sin(wrapvalue(v*fx+offset,0,360))*depth addy#=-Cos(wrapvalue(v*fy+offset,0,360))*depth addz#=Sin(-wrapvalue(v*fz+offset,0,360))*depth End Select mag#=Sqr(x*x+y*y+z*z) x#=x#+addx*(x/mag)+deltax y#=y#+addy*(y/mag)+deltay z#=z#+addz*(z/mag) VertexCoords surf,a,x#,y#,z# Next Next UpdateNormals mesh End Function Function wrapvalue#(value#,lo#,hi#) i=Floor(value/(hi-lo)) r#=i*(hi-lo) Return (value-r)+lo End Function ; --------------------------------------------------------- Function CreateMyCylinder(verticalsegments,ringsegments=0,solid=True,parent=0) Local tr,tl,br,bl; side of cylinder Local ts0,ts1,newts; top side vertexs Local bs0,bs1,newbs; bottom side vertexs If verticalsegments<3 Or verticalsegments>100 Then Return 0 If ringsegments<0 Or ringsegments>100 Then Return 0 thiscylinder=CreateMesh(parent) thissurf=CreateSurface(thiscylinder) If solid=True thissidesurf=CreateSurface(thiscylinder) EndIf div#=Float(360.0/(verticalsegments)) height#=1.0 ringSegmentHeight#=(height#*2.0)/(ringsegments+1) upos#=1.0 udiv#=Float(1.0/(verticalsegments)) vpos#=1.0 vdiv#=Float(1.0/(ringsegments+1)) SideRotAngle#=90 ; re-diminsion arrays to hold needed memory. ; this is used just for helping to build the ring segments... Dim tRing(verticalsegments) Dim bRing(verticalsegments) ;render end caps if solid If solid=True XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) ts0=AddVertex(thissidesurf,XPos#,height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) bs0=AddVertex(thissidesurf,XPos#,-height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) SideRotAngle#=SideRotAngle#+div# XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) ts1=AddVertex(thissidesurf,XPos#,height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) bs1=AddVertex(thissidesurf,XPos#,-height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) For i=1 To (verticalsegments-2) SideRotAngle#=SideRotAngle#+div# XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) newts=AddVertex(thissidesurf,XPos#,height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) newbs=AddVertex(thissidesurf,XPos#,-height,ZPos#,XPos#/2.0+0.5,ZPos#/2.0+0.5) AddTriangle(thissidesurf,ts0,ts1,newts) AddTriangle(thissidesurf,newbs,bs1,bs0) If i<(verticalsegments-2) ts1=newts bs1=newbs EndIf Next EndIf ; ----------------------- ; middle part of cylinder thisHeight#=height# ; top ring first SideRotAngle#=90 XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) thisUPos#=upos# thisVPos#=0 tRing(0)=AddVertex(thissurf,XPos#,thisHeight,ZPos#,thisUPos#,thisVPos#) For i=0 To (verticalsegments-1) If i<(verticalsegments-1) Then SideRotAngle#=SideRotAngle#+div# Else Siderotangle#=90 XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) thisUPos#=thisUPos#-udiv# tRing(i+1)=AddVertex(thissurf,XPos#,thisHeight,ZPos#,thisUPos#,thisVPos#) Next For ring=0 To (ringsegments) ; decrement vertical segment thisHeight=thisHeight-ringSegmentHeight# ; now bottom ring SideRotAngle#=90 XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) thisUPos#=upos# thisVPos#=thisVPos#+vdiv# bRing(0)=AddVertex(thissurf,XPos#,thisHeight,ZPos#,thisUPos#,thisVPos#) For i=0 To (verticalsegments-1) If i<(verticalsegments-1) Then SideRotAngle#=SideRotAngle#+div# Else Siderotangle#=90 XPos#=-Cos(SideRotAngle#) ZPos#=Sin(SideRotAngle#) thisUPos#=thisUPos#-udiv# bRing(i+1)=AddVertex(thissurf,XPos#,thisHeight,ZPos#,thisUPos#,thisVPos#) Next ; Fill in ring segment sides with triangles For v=1 To (verticalsegments) tl=tRing(v) tr=tRing(v-1) bl=bRing(v) br=bRing(v-1) AddTriangle(thissurf,tl,tr,br) AddTriangle(thissurf,bl,tl,br) Next ; make bottom ring segmentthe top ring segment for the next loop. For v=0 To (verticalsegments) tRing(v)=bRing(v) Next Next UpdateNormals thiscylinder Return thiscylinder End Function