MyCylinder modification

Blitz3D Forums/Blitz3D Programming/MyCylinder modification

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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