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


Seems okayish speed here, at least with the demo settings. Issue with your graphics card?

Dunno, it ran very well here, even in debug mode. (Nice job BTW.)

Works well here as well, even after increasing the poly count.

Thanks everybody for taking the time. I think it must be a Open GL issue with my graphics card.. So now all I have to do is turn this in to a proper physics engine… ; )