Softbody port

BlitzMax Forums/BlitzMax Programming/Softbody port

I did a port of a softbody simulation found here

http://panoramix.ift.uni.wroc.pl/~MAQ/eng/
Can anybody tell me why the frame rate is so low

SetGraphicsDriver GLMax2DDriver()

Global SCRSIZE:Int = 7	
		
Global NUMP:Int = 20				
Global NUMS:Int = (NUMP+1)		
Global MASS:Float = 1.0				
Global BALLRADIUS:Float = 0.516	
Global KS:Float = 755.0		
Global KD:Float = 35.0				
Global GY:Float = -10.0
Global DT:Float = 0.005
Global FINAL_PRESSURE:Float = 45.0
Global Pressure:Float = 0
'/* Mouse */

Global windW:Int=380
Global windH:Int=380

Graphics windW,windH
Print "h"
Global MD:Int = 0
Global xMouse:Float  
Global yMouse:Float
Global closest_i:Int=1				

'/* Structure of the point */
Type CPoint2D

	Field x:Float = 0
	Field y:Float = 0
	Field vx:Float = 0           		
	Field vy:Float = 0		
	Field fx:Float = 0
	Field fy:Float = 0
				
End Type



'/* Structure of the springs */
Type CSpring
  	Field i:Int = 0 
	Field j:Int = 0
	Field length:Float = 0
	Field nx:Float = 0
	Field ny:Float = 0				          		  
End Type

 
'/* There we will keep an Object */

Global myPoints:CPoint2d[NUMP]
Global mySprings:CSpring[NUMS]


'/* Add New spring */4
Function AddSpring(Pii:Int , i:Int , j:Int )

	mySprings[Pii] = New CSpring 
	mySprings[Pii].i = i	
	mySprings[Pii].j = j
	mySprings[Pii].length = Sqr((myPoints[ i ].x - myPoints[ j ].x)*(myPoints[ i ].x - myPoints[ j ].x)..
						+ 	(myPoints[ i ].y - myPoints[ j ].y)*(myPoints[ i ].y - myPoints[ j ].y) )
End Function









'/* Force Calculation Subroutine */
Function AccumulateForces()

	Local i:Int 
   	Local x1:Float
	Local x2:Float
	Local y1:Float
	Local y2:Float
	Local r12d:Float		'// length of p1 - p2 vector
	Local vx12:Float		'// vx1 - vx2
	Local vy12:Float		'// vy1 - vy2
	Local f:Float			'// hooke force value
	Local Fx:Float
	Local Fy:Float			'// force vector
	Local volume:Float = 0	'// volume of the body
	Local pressurev:Float	'// pressure force value

	'/* gravity */
	
	For i = 0 To NUMP-1

		myPoints[i].fx = 0
		Local press:Float
		If (Pressure - FINAL_PRESSURE) <= 0 Then
			press = 0
		Else
			
			press = 1
		End If
		
		
		myPoints[i].fy = MASS * GY * press

		'Print myPoints[i].fy
		'!! Note IF after IF !!
		'/* user clicked (mouse spring) */
		If i=closest_i And MD = 1 Then 		'// closest point only	'// If user clicked
			
			x1 = myPoints[ i ].x			'// get points coords.
			y1 = myPoints[ i ].y
			x2 = xMouse
			y2 = yMouse

			r12d = Sqr ( (x1 - x2) *(x1 - x2)  +  (y1 - y2) * (y1 - y2) )
															'// square
															'// root  of the distance
			f = (r12d -  2.2) * 22 + (myPoints[ i ].vx * (x1 - x2) + myPoints[ i ].y * (y1 - y2)) * 54 / r12d

			'// calculate spring force
			Fx = ((x1 - x2) / r12d ) * f
			Fy = ((y1 - y2) / r12d ) * f

			'// accumulate force
			myPoints[i].fx :- Fx
			myPoints[i].fy :- Fy

		End If
	Next


	'/* spring force */
	 For i = 0 To NUMS-2
			
			x1 = myPoints[ mySprings[i].i ].x	
			y1 = myPoints[ mySprings[i].i ].y
			x2 = myPoints[ mySprings[i].j ].x	
			y2 = myPoints[ mySprings[i].j ].y
			
			r12d = Sqr(( (x1 - x2) *(x1 - x2) ) + ( (y1 - y2) * (y1 - y2) ))	'// square
										'// root  of the distance
			If r12d > 0 Then
			
				vx12 = myPoints[ mySprings[i].i ].vx - myPoints[ mySprings[i].j ].vx
				
				
				vy12 = myPoints[ mySprings[i].i ].vy - myPoints[ mySprings[i].j ].vy
				
				f = ((r12d -  mySprings[i].length) * KS) + (vx12 * (x1 - x2) + vy12 * (y1 - y2)) * KD / r12d

				Fx = ((x1 - x2) / r12d ) * f
				Fy = ((y1 - y2) / r12d ) * f

				myPoints[ mySprings[i].i  ].fx :- Fx
				myPoints[ mySprings[i].i  ].fy :- Fy

				myPoints[  mySprings[i].j  ].fx :+ Fx
				myPoints[  mySprings[i].j  ].fy :+ Fy
				
			End If

			'/* Calculate normal vectors To springs */
			mySprings[i].nx =  (y1 - y2) / r12d
			mySprings[i].ny =  -(x1 - x2) / r12d
			
			
	Next
	

	
	'/* pressure force */
	'/* Calculate Volume of the Ball (Gauss Theorem) */
	
	For i = 0 To NUMS-2
		x1 = myPoints[ mySprings[i].i ].x	
		y1 = myPoints[ mySprings[i].i ].y
		x2 = myPoints[ mySprings[i].j ].x	
		y2 = myPoints[ mySprings[i].j ].y
		r12d = Sqr( (x1 - x2) *(x1 - x2)  +  (y1 - y2) * (y1 - y2) )	'// square
														'// root  of the distance
		volume :+ 0.5 * Abs(x1 - x2) * Abs(mySprings[i].nx) * (r12d)

	Next

	
	For i = 0 To NUMS-2 
		

		x1 = myPoints[ mySprings[i].i ].x	
		y1 = myPoints[ mySprings[i].i ].y
		x2 = myPoints[ mySprings[i].j ].x	
		y2 = myPoints[ mySprings[i].j ].y
		r12d = Sqr( (x1 - x2) *(x1 - x2)  +  (y1 - y2) * (y1 - y2) )'	// square
														'// root  of the distance
		pressurev = r12d * Pressure * (1.0/volume)
	  
		myPoints[ mySprings[i].i ].fx :+ mySprings[ i ].nx * pressurev
		myPoints[ mySprings[i].i ].fy :+ mySprings[ i ].ny * pressurev
		myPoints[ mySprings[i].j ].fx :+ mySprings[ i ].nx * pressurev
		myPoints[ mySprings[i].j ].fy :+ mySprings[ i ].ny * pressurev
		
	Next
End Function



'/**
' * Euler Integrator
' */

Function IntegrateEuler()

	Local i:Int
 	Local dry:Float
	Local drx:Float			'// dr For Euler integration
	
	'/* Euler Integrator (second Newton's law) */
	
	For i = 0 To NUMP-1
		
		
	   	'/* x */
		myPoints[i].vx = myPoints[i].vx + ( myPoints[i].fx / MASS )* DT
		drx = myPoints[i].vx * DT

		'/* Boundaries  X */
		If (myPoints[i].x + drx < -SCRSIZE) Then
		
			drx = -SCRSIZE - myPoints[ i ].x
		   	myPoints[i].vx = - 0.1 *myPoints[i].vx
		   	myPoints[i].vy = 0.95 *myPoints[i].vy
		
		'/* Boundaries  X */
		Else If(myPoints[i].x + drx > SCRSIZE) Then
		 
			drx = SCRSIZE - myPoints[ i ].x
		   	myPoints[i].vx = - 0.1 *myPoints[i].vx
		   	myPoints[i].vy = 0.95 *myPoints[i].vy

		End If
		
		
		myPoints[i].x = myPoints[i].x + drx

	   	'/* y */
		myPoints[i].vy = myPoints[i].vy + myPoints[i].fy * DT
		dry = myPoints[i].vy * DT

		'/* Boundaries  Y */
		If(myPoints[i].y + dry < -SCRSIZE)
	
			dry = -SCRSIZE - myPoints[ i ].y
		   	myPoints[i].vy = - 0.1 *myPoints[i].vy
		   	myPoints[i].vx = 0.95 *myPoints[i].vx
		
		'/* Boundaries  Y */
		Else If(myPoints[i].y + dry > SCRSIZE)
		
			dry = SCRSIZE - myPoints[ i ].y
		   	myPoints[i].vy = - 0.1 *myPoints[i].vy
		
		End If

		myPoints[i].y = myPoints[i].y + dry


		'/* fast chek If outside */
		If(myPoints[i].x > SCRSIZE) Then myPoints[i].x = SCRSIZE
			
		If(myPoints[i].y > SCRSIZE) Then myPoints[i].y = SCRSIZE
			
		If(myPoints[i].x < -SCRSIZE) Then myPoints[i].x = -SCRSIZE
			
		If(myPoints[i].y < -SCRSIZE) Then myPoints[i].y = -SCRSIZE
			
		'Print i 
	 Next
  
End Function 

	

     
'/* Idle Function */
Function Idle()	
	Motion()
	AccumulateForces()
	IntegrateEuler()
    '/**
	  '* Update Pressure (pump an air into the ball)
	  ' */
	  If(Pressure < FINAL_PRESSURE) Then

		Pressure :+ FINAL_PRESSURE/300.0
		'FINAL_PRESSURE/100
	   '	Print"Pressure = "+Pressure
	  End If
	'glutPostRedisplay();
End Function


'/* Reshape Window */
Function Reshape()


	'glClearColor(0.4, 0.0, 0.0, 0.0);
	glMatrixMode (GL_PROJECTION)
	glLoadIdentity ()
	gluOrtho2D(-SCRSIZE, SCRSIZE, -SCRSIZE, SCRSIZE)
	glMatrixMode (GL_MODELVIEW)
	glLoadIdentity()
	glDisable(GL_DEPTH_TEST)


    'glViewport(0, 0, windW, windH)
    'glMatrixMode(GL_PROJECTION)
    'glLoadIdentity()
    'gluOrtho2D(-SCRSIZE, SCRSIZE, -SCRSIZE, SCRSIZE)
    'glMatrixMode(GL_MODELVIEW)
End Function


'/* Mouse Motion */
Function Motion()

	If MouseDown(1) Then
		If MD = 0 Then FindClosestPoint()
		MD = 1
		Local mxf:Float = MouseX()
		Local myf:Float = MouseY()
		Local w:Float = windW
		Local h:Float = windH
		'xMouse = MouseX() 
		xMouse = SCRSIZE * 2.0 * (mxf / w - 0.5)
		yMouse = -SCRSIZE * 2.0 * (myf / h - 0.5)
 	Else
		MD = 0
	End If 
End Function


'/* Visualization */
Function Draw()

	Local i:Int
	glClearColor(1,1,1,0)
	glClear(GL_COLOR_BUFFER_BIT)
	glBegin(GL_POLYGON)
	

	For i=0 To myPoints.length-1
		glColor3f(0.8,0.4,0.4)
		glVertex2f(myPoints[i].x,myPoints[i].y)
	Next 	
	glEnd()

	If MD Then
		

	 	glColor3f(0,0,0)
	 	glBegin(GL_LINES)
		glVertex2f(xMouse,yMouse)
   	  	glVertex2f(myPoints[closest_i].x,myPoints[closest_i].y)
     	glEnd()
		
	End If

	Flip 

End Function





'/* Find point in the model which is closest To mouse click point */

Function FindClosestPoint()

	Local dmin:Float 
	Local mousepointd:Float 
	Local i:Int

	'// find closest point
	Local disA = myPoints[closest_i].x - xMouse
	Local disB = myPoints[closest_i].y - yMouse
	dmin = Sqr((disA*disA) + (disB*disB))

	For i=0 To NUMP-1
				
		disA = myPoints[i].x - xMouse
		disB = myPoints[i].y - yMouse
		mousepointd = Sqr((disA*disA) + (disB*disB))					
							
		If mousepointd < dmin Then
			dmin = mousepointd
			closest_i = i
		End If
	Next
End Function 


'Function CreateBall Object (points & springs) */
Function CreateBall()

	Local  angle:Float = 360.0/NUMP
	
	
	For Local i:Int = 0 To NUMP-1
		' !! Divide with Int !!
		myPoints[i] = New CPoint2d
		
		Local fi:Float = i
		Local h:Float =SCRSIZE
		myPoints[i].y = (BALLRADIUS) * Cos(fi*angle) + h/2
		myPoints[i].x = (BALLRADIUS) * Sin(fi*angle)  
	Next
	
	
	For i = 0 To NUMP-2

		AddSpring(i,i,i+1) 
		  		
	Next 

	AddSpring(i,i,0)
	 
End Function


Local mode,time
CreateBall()
While Not KeyHit( KEY_ESCAPE )
time=MilliSecs()

	Reshape()
	Draw()
	Idle()
	Idle()
	Idle()
	Idle()
	Idle()
	Idle()

Wend