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.
; 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