
	.align	4
	.thumb
	.include	"obj_kollision.i"

;****************************	
;*
;* n_over_2
;*
;* r0 = n
;* r1 = (n over 2)
;*	  

	.global		n_over_2
	.type		n_over_2,function
  
n_over_2
       
	; n*(n-1)/2
       
       	sub	r1,r0,#1		
       	mul	r1,r0
       	asr	r1,r1,#1
       	
  	bx	lr

;****************************	
;*
;* get_poly_middle_th
;*
;* r0 = anzahl punkte von Polygon
;* r1 = &punkte von Polygon (punkte immer 16Bit)
;*	
;* return:
;*
;* r5 = mittelpunktx
;* r6 = mittelpunkty
;*

	.global		get_poly_middle_th
	.type		get_poly_middle_th,function

get_poly_middle_th
	
	mov	r8,lr
	push	{r0-r4,r7}
	
	mov	r5,#0
	mov	r6,#0
	
	mov	r7,r0
	
fall_pointsm

	ldmia	r1!,{r4}	;x:y	!LE also y:x
	
	asr	r2,r4,#16	;x
	lsl	r3,r4,#16
	asr	r3,r3,#16	;y
	
	add	r5,r5,r3
	add	r6,r6,r2

	sub	r0,r0,#1
	bne	fall_pointsm	
	
	addr	r4,fdiv		;divfunk
	
	mov	r0,r5		;x
	mov	r1,r7		;  / count
	
	
	mov	r3,pc
	add	r3,r3,#5	;+2befehle | 1
	mov	lr,r3
	bx	r4
	
	
	mov	r5,r0		;xm
	
	mov	r0,r6		;y
	mov	r1,r7		;  / count
	
	mov	r3,pc
	add	r3,r3,#5	;+2befehle | 1
	mov	lr,r3
	bx	r4

	mov	r6,r0		;ym
	
	pop	{r0-r4,r7}
	bx	r8
	
;****************************
;*
;* get_poly_radius_th
;*
;* r0 = anzahl punkte von Polygon
;* r1 = &punkte von Polygon (punkte immer 16Bit)
;*
;* r2 = mittelpunktx
;* r3 = mittelpunkty
;*
;* return:
;*
;* r7 = radius*radius
;*


	.global		get_poly_radius_th
	.type		get_poly_radius_th,function
	
get_poly_radius_th

	push	{r1-r6}
		
	mov	r7,#0
	
fall_points_th	

	ldmia	r1!,{r4}	;x:y	!LE y:x
	
	asr	r6,r4,#16	;x
	lsl	r5,r4,#16
	asr	r5,r5,#16	;y
		
	sub	r5,r2,r5	;xm-x
	sub	r6,r3,r6	;ym-y
	
	mul	r5,r5		;(xm-x)²
	mul	r6,r6		;(ym-y)²
	
	add	r6,r6,r5
	
	cmp	r6,r7
	ble	no_rad_max
	
	mov	r7,r6

no_rad_max
	sub	r0,r0,#1
	bne	fall_points_th
		
	pop	{r1-r6}	
	bx	lr
	
;****************************
;*
;* check_obj_th (test auf spherische kollision, wenn ja teste punkt kollision)
;*
;* r4 = obj1
;* r5 = obj2
;*
;* return:
;*
;* r7 = 0 = no koll / 1 = koll
;*
	
	.global		check_obj_th
	.type		check_obj_th,function
	
check_obj_th

;
	push	{r0-r4,lr}

	ldr	r0,[r4,#OBJ_STRUCT_MX]	
	ldr	r1,[r4,#OBJ_STRUCT_MY]
	ldr	r6,[r4,#OBJ_STRUCT_RAD]
	
	ldr	r2,[r5,#OBJ_STRUCT_MX]	
	ldr	r3,[r5,#OBJ_STRUCT_MY]
	ldr	r7,[r5,#OBJ_STRUCT_RAD]
	
	add	r6,r6,r7	;gesamtradius=radius1+radius2
	mul	r6,r6		;gesamtradius²

	sub	r0,r0,r2	;dx
	sub	r1,r1,r3	;dy
	
	mul	r0,r0		;dx²
	mul	r1,r1		;dy²
	
	add	r0,r0,r1	;dx²+dy²
	
	cmp	r0,r6		;abstand <> minabstand
	bgt	no_sphere_coll

	;****   teste obj1 gegen obj2
	
	push	{r4,r5}
	
	addr	r1,obj_line_test
	mov	r2,pc
	add	r2,r2,#5
	mov	lr,r2
	bx	r1		

	pop	{r4,r5}

	cmp	r7,#1
	beq	no_sphere_coll
	
	;**** teste punkt - obj
	
	bl	pobj_in_obj_th		;punkt von obj1 in obj2
	cmp	r7,#1
	beq	no_sphere_coll
	
	eor	r4,r5
	eor	r5,r4
	eor	r4,r5
	
	bl	pobj_in_obj_th		;punkt von obj2 in obj1

no_sphere_coll	

;no_reverse_test

	pop	{r0-r4}
	pop	{r6}			;lr
	bx	r6
	
;****************************
;*
;* pobj_in_obj_th (teste ob erste punkt von obj1 (r4) in obj2 (r5))
;*
;* ! kein bx
;*
;* r4 = obj1
;* r5 = obj2
;*
;* return:
;*
;* r7 = 0 = no koll / 1 = koll	
	
	
	;.global	pobj_in_obj_th
	;.type		pobj_in_obj_th,function
		
pobj_in_obj_th

	push	{r4,r5,lr}
	
	ldr	r4,[r4,#OBJ_STRUCT_PT]		;&pt obj1
	
	ldr	r0,[r5,#OBJ_STRUCT_ECKEN]
	ldr	r1,[r5,#OBJ_STRUCT_PT]		;punkte von polygon
	ldr	r0,[r0]				;anzahl ecken polygon

	ldmia	r4!,{r2}			;get p1x,p1y von obj1
	
	addr	r7,point_in_poly	
	mov	r5,pc
	add	r5,r5,#5
	mov	lr,r5
	bx	r7	
	
	pop	{r4,r5,pc}

	
;****************************
;*
;* obj_sphere_coll_th (gehe über alle punkte von obj1 und teste ob diese in obj2)
;*
;* ! kein bx
;*
;* r4 = obj1
;* r5 = obj2
;*
;* return:
;*
;* r7 = 0 = no koll / 1 = koll
;*


	.global		obj_sphere_coll_th
	.type		obj_sphere_coll_th,function

obj_sphere_coll_th

	push	{r4,r5,lr}

	ldr	r0,[r4,#OBJ_STRUCT_ECKEN]
	ldr	r6,[r4,#OBJ_STRUCT_PT]		;&pt obj1
	ldr	r4,[r0]				;anzahl ecken obj1

	ldr	r0,[r5,#OBJ_STRUCT_ECKEN]
	ldr	r1,[r5,#OBJ_STRUCT_PT]
	ldr	r0,[r0]				;anzahl ecken obj2



for_all_pobj1

	ldmia	r6!,{r2}	;get px,py

	;**
	
	;* r0 = anzahl punkte von Polygon
	;* r1 = &punkte von Polygon (punkte immer 16Bit)
	;* r2 = x:y
	;*
	;* r7 = 0 nicht in Polygon, 1 in Polygon
	;*
	
	addr	r7,point_in_poly
	mov	r5,pc
	add	r5,r5,#5
	mov	lr,r5
	bx	r7		;check point against obj 2	
	cmp	r7,#1
	beq	pcoll_detected

	
	sub	r4,r4,#1
	bne	for_all_pobj1	
	
	mov	r7,#0		;keine kollision
	
pcoll_detected
	pop	{r4,r5,pc}


;****************************
;*
;* obj_line_x_line_wrapper_function (tested ob line1,line2 kreuzt)
;*
;* !!!läuft in obj_line_x_line hinein!!!
;*
;* r0=x1:y1
;* r1=x2:y2
;* r5=x3:y3
;* r6=x4:y4
;*

	.global		line_x_line_overhead
	.type		line_x_line_overhead,function
	
	.global		obj_line_x_line
	.type		obj_line_x_line,function

line_x_line_overhead


	mov	r9,r0
	mov	r12,r1

	asr	r1,r5,#16			;y1
	lsl	r5,r5,#16
	asr	r0,r5,#16			;x1
	
	asr	r3,r6,#16			;y2
	lsl	r6,r6,#16
	asr	r2,r6,#16			;x2
	
	mov	r6,r9				;r6=r9 (r0)
	
	asr	r5,r6,#16			;y3
	lsl	r6,r6,#16
	asr	r4,r6,#16			;x3
	
	mov	r6,r12				;r6=r12 (r1)
	
	asr	r7,r6,#16			;y4
	lsl	r6,r6,#16
	asr	r6,r6,#16			;x4
	


;****************************
;*
;* obj_line_x_line (tested ob line1,line2 kreuzt)
;*
;* r0=x1
;* r1=y1
;* r2=x2
;* r3=y2
;* r4=x3
;* r5=y3
;* r6=x4
;* r7=y4
;*
;* r10=fdivs
;* r11=schnittpunkt berechnen (wenn <> 0)
;*
;* return:
;* 
;* r2 = xs (bei r11 an)
;* r3 = ys (bei r11 an)
;*
;* r7 = 0 (nicht) / 1 (kreuzen)
;*

	.set	LINE_MAXP	,16

obj_line_x_line

	push	{lr}

	cmp	r0,r4
	bne	nicht_gleich
	cmp	r1,r5
	bne	nicht_gleich
	cmp	r2,r6
	bne	nicht_gleich
	cmp	r3,r7
	bne	nicht_gleich
	b	kreuz
	
nicht_gleich	

	mov	r12,r0
	mov	r0,r11
	cmp	r0,#0
	mov	r0,r12
	bne	x_push			;speichere x1,x2,y1,y2 (r0,r1,r2,r3)
x_push_r
		 
	sub	r3,r3,r1		;y21=y2-y1
	sub	r7,r7,r5		;y43=y4-y3
	sub	r1,r1,r5		;y13=y1-y3
	
	sub	r2,r2,r0		;x21=x2-x1
	sub	r6,r6,r4		;x43=x4-x3
	sub	r0,r0,r4		;x13=x1-x3

	;used r0,r1,r2,r3,r6,r7
	;free r4,r5


	mov	r5,#1
	lsl	r5,r5,#LINE_MAXP
	mov	r12,r5			;r12 = 2^LINE_MAXP
	
	;****

	mov	r4,r7			;y43
	mov	r5,r6			;x43
	
	mul	r4,r2			;y43*x21
	mul	r5,r3			;x43*y21
	
	sub	r4,r4,r5		;(y43*x21) - (x43*y21)
	beq	nokreuz
	
	mov	r8,r4			;den
	
	;test den
	
	mov	r4,r6			;x43
	mov	r5,r7			;y43
	
	mul	r4,r1			;x43*y13
	mul	r5,r0			;y43*x13
	
	sub	r4,r4,r5		;(x43*y13) - (y43*x13)	
	mov	r9,r4			;t1

	mov	r4,r2			;x21
	mov	r5,r3			;y21
	
	mul	r4,r1			;x21*y13
	mul	r5,r0			;y21*x13
	
	sub	r5,r4,r5		;(x21*y13) - (y21*x13)	= t2

	;t1 = (t1*2^n)/den
	;t2 = (t2*2^n)/den
	
	mov	r4,r9
	lsl	r5,r5,#LINE_MAXP		;t2<<LINE_MAXP
	lsl	r0,r4,#LINE_MAXP		;t1<<LINE_MAXP
	
	mov	r1,r8			;/den
	mov	r3,pc
	add	r3,r3,#5
	mov	lr,r3
	bx	r10

	mov	r6,r0			;t1 
	cmp	r0,#0			;if <=0 ot >= 2^LINE_MAXP then nokreuz
	ble	nokreuz
	
	cmp	r0,r12
	bge	nokreuz
	
	mov	r0,r5			;t2
	mov	r1,r8			;/den			
	mov	r3,pc
	add	r3,r3,#5
	mov	lr,r3
	bx	r10

	cmp	r0,#0			;if <=0 ot >= 2^LINE_MAXP then nokreuz
	ble	nokreuz
	
	cmp	r0,r12
	bge	nokreuz

	;**** geschnitten 

kreuz
	mov	r7,r11
	cmp	r7,#0
	bne	x_calc		;schnittpunkt berechnen?
x_calc_r

	mov	r7,#1		;kreuz
	pop	{r0}
	bx	r0
	
	;**** nicht geschnitten
	
nokreuz

	mov	r7,r11
	cmp	r7,#0
	bne	x_redo_stack	;schnittpunkt berechnen? da keiner da mach stack sauber
x_redo_stack_r

	mov	r7,#0		;nix
	pop	{r0}
	bx	r0	


;**** sichere x0,x1,x2,x3

x_push
	push	{r0,r1,r2,r3}
	b	x_push_r


;**** calculiere schnittpunkt
x_calc
	;(r0,r1,r2,r3,r6) = x1,y1,x2,y2t1

	pop	{r0,r1,r2,r3}	

	; xs=x1+(t1*(x2-x1))Sar power
	; ys=y1+(t1*(y2-y1))Sar power
	
	sub	r4,r2,r0		;x21=x2-x1
	sub	r5,r3,r1		;y21=y2-y1
	
	mul	r4,r4,r6		;*t1
	mul	r5,r5,r6		;*t1
	
	asr	r4,r4,#LINE_MAXP
	asr	r5,r5,#LINE_MAXP
	
	add	r2,r4,r0
	add	r3,r5,r1
	
	b	x_calc_r
	
;**** säubere stack bei keinem schnittpunkt

x_redo_stack
	
	add	sp,sp,#4*4
	b	x_redo_stack_r
	
	.pool
	.end