// File: /workspace/github_cpp_makefile_star2_O3/FreeSlave[P]vhlt/hlvis/flow.cpp
// Function: MaxDistVis(int)
void	MaxDistVis(int unused)
{
	int i, j, k, m;
	int a, b, c, d;
	leaf_t	*l;
	leaf_t	*tl;
	plane_t	*boundary = NULL;
	vec3_t delta;

	float new_dist;

	unsigned offset_l;
	unsigned bit_l;

	unsigned offset_tl;
	unsigned bit_tl;
	
	while(1)
	{
		i = GetThreadWork();
		if (i == -1)
			break;

		l = &g_leafs[i];

		for(j = i + 1, tl = g_leafs + j; j < g_portalleafs; j++, tl++)
		{
#ifdef HLVIS_MAXDIST_NEW

			offset_l = i >> 3;
			bit_l = (1 << (i & 7));

			offset_tl = j >> 3;
			bit_tl = (1 << (j & 7));

			{
				bool visible = false;
				for (k = 0; k < l->numportals; k++)
				{
					if (l->portals[k]->visbits[offset_tl] & bit_tl)
					{
						visible = true;
					}
				}
				for (m = 0; m < tl->numportals; m++)
				{	
					if (tl->portals[m]->visbits[offset_l] & bit_l)
					{
						visible = true;
					}
				}
				if (!visible)
				{
					goto NoWork;
				}
			}
			
			// rough check
			{
				vec3_t v;
				vec_t dist;
				const winding_t *w;
				const leaf_t *leaf[2] = {l, tl};
				vec3_t center[2];
				vec_t radius[2];
				int count[2];
				for (int side = 0; side < 2; side++)
				{
					count[side] = 0;
					VectorClear (center[side]);
					for (a = 0; a < leaf[side]->numportals; a++)
					{
						w = leaf[side]->portals[a]->winding;
						for (b = 0; b < w->numpoints; b++)
						{
							VectorAdd (w->points[b], center[side], center[side]);
							count[side]++;
						}
					}
				}
				if (!count[0] && !count[1])
				{
					goto Work;
				}
				for (int side = 0; side < 2; side++)
				{
					VectorScale (center[side], 1.0 / (vec_t)count[side], center[side]);
					radius[side] = 0;
					for (a = 0; a < leaf[side]->numportals; a++)
					{
						w = leaf[side]->portals[a]->winding;
						for (b = 0; b < w->numpoints; b++)
						{
							VectorSubtract (w->points[b], center[side], v);
							dist = DotProduct (v, v);
							radius[side] = qmax (radius[side], dist);
						}
					}
					radius[side] = sqrt (radius[side]);
				}
				VectorSubtract (center[0], center[1], v);
				dist = VectorLength (v);
				if (qmax (dist - radius[0] - radius[1], 0) >= g_maxdistance - ON_EPSILON)
				{
					goto Work;
				}
				if (dist + radius[0] + radius[1] < g_maxdistance - ON_EPSILON)
				{
					goto NoWork;
				}
			}

			// exact check
			{
				vec_t mindist = 9999999999;
				vec_t dist;
				for (k = 0; k < l->numportals; k++)
				{
					for (m = 0; m < tl->numportals; m++)
					{
						const winding_t *w[2];
						w[0] = l->portals[k]->winding;
						w[1] = tl->portals[m]->winding;
						dist = WindingDist (w);
						mindist = qmin (dist, mindist);
					}
				}
				if (mindist >= g_maxdistance - ON_EPSILON)
				{
					goto Work;
				}
				else
				{
					goto NoWork;
				}
			}
#else
			if(j == i)		// Ideally, should never be true
			{
				continue;
			}

			// If they already can't see each other, no use checking
			if(DisjointLeafVis(i, j))
			{
				continue;
			}

			new_dist = GetShortestDistance(l, tl);

			if(new_dist <= g_maxdistance)
				continue;

			// Try out our NEW, IMPROVED ALGORITHM!!!!
			
			// Get a portal on Leaf 1 that completely seperates the two leafs
			/*split = GetSplitPortal(l, tl);

			if(!split)
				continue;

			// We have a split, so create the bounds
			GetPortalBounds(split, &boundary);

			// Now get the dot product for all points on the other leaf
			max_dist = 999999999.999;

			/// Do the first check if mode is >= 2
			if(g_mdmode >= 2)
			{
				for(k = 0; k < tl->numportals; k++)
				{
					for(m = 0; m < tl->portals[k]->winding->numpoints; m++)
					{
						for(n = 0; n < split->winding->numpoints; n++) // numpoints of split portals = number of boundaries
						{
							dist = DotProduct(tl->portals[k]->winding->points[m], boundary[n].normal) - boundary[n].dist;
	
							if(dist < -ON_EPSILON)
							{
								// Outside boundaries
								//max_dot = MaxDotProduct(tl->portals[k]->winding->points[m], boundary, split->winding->numpoints);

								//max_dist = qmin(max_dist, max_dot);

								// Break so we don't do inside boundary check
								break;
							}
						}
						if(n < split->winding->numpoints)
							continue;

						// We found a point that's inside all the boundries!
						new_dist = DotProduct(tl->portals[k]->winding->points[m], split->plane.normal) - split->plane.dist;

						max_dist = qmin(max_dist, new_dist);
					}
				}
			}

			// This is now a special check.  If Leaf 2 has a split plane, we generate a polygon by clipping the plane
			// with the borders.  We then get the minimum dot products.  If more than one split plane, use intersection.
			// Only do this is g_mdmode is 3
			if(g_mdmode >= 3)	// For future mode expansion
			{
				new_dist = CalcSplitsAndDotProducts(&split->plane, tl, l, boundary, split->winding->numpoints);

				max_dist = qmin(max_dist, new_dist);
			}*/

			// Third and final check.  If the whole of leaf2 is outside of leaf1 boundaries, this one will catch it
			// Basic "every point to every point" type of deal :)
			// This is done by default all the time
			for(a = 0; a < l->numportals; a++)
			{
				for(b = 0; b < tl->numportals; b++)
				{
					for(c = 0; c < l->portals[a]->winding->numpoints; c++)
					{
						for(d = 0; d < tl->portals[b]->winding->numpoints; d++)
						{
							VectorSubtract(l->portals[a]->winding->points[c], tl->portals[b]->winding->points[d], delta);

							if(VectorLength(delta) <= g_maxdistance)
								goto NoWork;
						}
					}
				}
			}
#endif

#ifdef HLVIS_MAXDIST_NEW
Work:
			ThreadLock ();
			for (k = 0; k < l->numportals; k++)
			{
				l->portals[k]->visbits[offset_tl] &= ~bit_tl;
			}
			for (m = 0; m < tl->numportals; m++)
			{
				tl->portals[m]->visbits[offset_l] &= ~bit_l;
			}
			ThreadUnlock ();
#else
			offset_l = i >> 3;
			bit_l = (1 << (i & 7));

			offset_tl = j >> 3;
			bit_tl = (1 << (j & 7));

			for(k = 0; k < l->numportals; k++)
			{
				for(m = 0; m < tl->numportals; m++)
				{
					if(l->portals[k]->status != stat_none)
						l->portals[k]->visbits[offset_tl] &= ~bit_tl;
					else
						l->portals[k]->mightsee[offset_tl] &= ~bit_tl;
					
					if(tl->portals[m]->status != stat_none)
						tl->portals[m]->visbits[offset_l] &= ~bit_l;
					else
						tl->portals[m]->mightsee[offset_l] &= ~bit_l;
				}
			}
#endif
			
NoWork:
			continue;	// Hack to keep label from causing compile error
		}
	}

	// Release potential memory
	if(boundary)
		delete [] boundary;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
callq 0x9e2c
cmpl $-0x1, %eax
je 0xe650
leaq 0x20(%rsp), %rdi
leal 0x1(%rax), %esi
leaq 0x20915ce(%rip), %rcx   # 0x209f764
cmpl (%rcx), %esi
jae 0xe63d
leaq 0x20915cb(%rip), %rcx   # 0x209f770
movq (%rcx), %r8
movslq %eax, %rcx
imulq $0x810, %rcx, %rdx      # imm = 0x810
leaq (%r8,%rdx), %r15
movl %esi, %r9d
movslq %esi, %rsi
imulq $0x810, %rsi, %r12      # imm = 0x810
movl %r9d, %esi
addq %r8, %r12
andb $0x7, %cl
movl $0x1, %r11d
shll %cl, %r11d
sarl $0x3, %eax
movl %r11d, %ecx
notb %cl
movb %cl, 0xb(%rsp)
leaq (%r8,%rdx), %r14
addq $0x820, %r14            # imm = 0x820
movq %rax, 0x10(%rsp)
movl %r11d, 0xc(%rsp)
movl %esi, %ecx
andb $0x7, %cl
movl $0x1, %ebp
shll %cl, %ebp
movl %esi, 0x40(%rsp)
sarl $0x3, %esi
movl (%r15), %ecx
testq %rcx, %rcx
movl %esi, 0x3c(%rsp)
je 0xe23e
movl %esi, %edx
xorl %esi, %esi
xorl %r8d, %r8d
movq 0x10(%r15,%rsi,8), %r9
movq 0x28(%r9), %r9
movzbl (%r9,%rdx), %r9d
testl %r9d, %ebp
setne %r9b
orb %r9b, %r8b
incq %rsi
cmpq %rsi, %rcx
jne 0xe21c
jmp 0xe241
xorl %r8d, %r8d
movl (%r12), %ecx
testq %rcx, %rcx
je 0xe26a
xorl %edx, %edx
movq (%r14,%rdx,8), %rsi
movq 0x28(%rsi), %rsi
movzbl (%rsi,%rax), %esi
testl %esi, %r11d
setne %sil
orb %sil, %r8b
incq %rdx
cmpq %rdx, %rcx
jne 0xe24c
testb $0x1, %r8b
je 0xe61d
movq %r15, 0x50(%rsp)
movq %r12, 0x60(%rsp)
movb $0x1, %al
leaq 0x1c(%rsp), %rcx
movq %rdi, %rdx
leaq 0x50(%rsp), %rsi
xorl %edi, %edi
movl %edi, (%rcx)
movl %edi, 0x8(%rdx)
movq $0x0, (%rdx)
movq (%rsi), %rsi
movl (%rsi), %edi
testq %rdi, %rdi
je 0xe305
xorps %xmm0, %xmm0
xorps %xmm1, %xmm1
xorl %r8d, %r8d
xorl %r9d, %r9d
movq 0x10(%rsi,%r9,8), %r10
movq 0x18(%r10), %r11
movslq 0x4(%r11), %r10
testq %r10, %r10
jle 0xe2fd
leaq (,%r10,4), %rbx
leaq (%rbx,%rbx,2), %rbx
xorl %r13d, %r13d
movsd 0x8(%r11,%r13), %xmm2
addps %xmm2, %xmm0
addss 0x10(%r11,%r13), %xmm1
addq $0xc, %r13
cmpq %r13, %rbx
jne 0xe2d2
addl %r8d, %r10d
movlps %xmm0, (%rdx)
movss %xmm1, 0x8(%rdx)
movl %r10d, (%rcx)
movl %r10d, %r8d
incq %r9
cmpq %rdi, %r9
jne 0xe2b1
leaq 0x18(%rsp), %rcx
leaq 0x2c(%rsp), %rdx
leaq 0x60(%rsp), %rsi
testb $0x1, %al
movl $0x0, %eax
jne 0xe28d
movl 0x18(%rsp), %eax
orl 0x1c(%rsp), %eax
movq 0x10(%rsp), %rax
leaq 0x20(%rsp), %rdi
movl 0xc(%rsp), %r11d
je 0xe5b2
movb $0x1, %r13b
leaq 0x1c(%rsp), %rdx
leaq 0x4c(%rsp), %rbx
movq %rdi, %rsi
leaq 0x50(%rsp), %rcx
xorps %xmm0, %xmm0
cvtsi2ssl (%rdx), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x6d7a(%rip), %xmm2     # 0x150e0
divsd %xmm0, %xmm2
cvtps2pd (%rsi), %xmm0
movapd %xmm2, %xmm1
unpcklpd %xmm2, %xmm1            # xmm1 = xmm1[0],xmm2[0]
mulpd %xmm0, %xmm1
cvtpd2ps %xmm1, %xmm1
movlpd %xmm1, (%rsi)
xorps %xmm0, %xmm0
cvtss2sd 0x8(%rsi), %xmm0
mulsd %xmm2, %xmm0
xorps %xmm2, %xmm2
cvtsd2ss %xmm0, %xmm2
movss %xmm2, 0x8(%rsi)
movq (%rcx), %r9
movl (%r9), %ecx
testq %rcx, %rcx
je 0xe41e
movapd %xmm1, %xmm3
shufps $0x55, %xmm1, %xmm3     # xmm3 = xmm3[1,1],xmm1[1,1]
xorps %xmm0, %xmm0
xorl %edx, %edx
movq 0x10(%r9,%rdx,8), %rsi
movq 0x18(%rsi), %rsi
movslq 0x4(%rsi), %r8
testq %r8, %r8
jle 0xe414
shlq $0x2, %r8
leaq (%r8,%r8,2), %r10
xorl %r8d, %r8d
movss 0x8(%rsi,%r8), %xmm4
movss 0xc(%rsi,%r8), %xmm5
subss %xmm1, %xmm4
subss %xmm3, %xmm5
movss 0x10(%rsi,%r8), %xmm6
subss %xmm2, %xmm6
mulss %xmm5, %xmm5
mulss %xmm4, %xmm4
addss %xmm5, %xmm4
mulss %xmm6, %xmm6
addss %xmm4, %xmm6
maxss %xmm6, %xmm0
addq $0xc, %r8
cmpq %r8, %r10
jne 0xe3ce
movss %xmm0, (%rbx)
incq %rdx
cmpq %rcx, %rdx
jne 0xe3b1
jmp 0xe421
xorps %xmm0, %xmm0
ucomiss 0x3c88(%rip), %xmm0     # 0x120b0
jb 0xe430
sqrtss %xmm0, %xmm0
jmp 0xe444
callq 0x3430
movl 0xc(%rsp), %r11d
leaq 0x20(%rsp), %rdi
movq 0x10(%rsp), %rax
movss %xmm0, (%rbx)
leaq 0x18(%rsp), %rdx
leaq 0x48(%rsp), %rbx
leaq 0x2c(%rsp), %rsi
leaq 0x60(%rsp), %rcx
testb $0x1, %r13b
movl $0x0, %r13d
jne 0xe353
movss 0x28(%rsp), %xmm0
subss 0x34(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
movsd 0x2c(%rsp), %xmm2
subps %xmm2, %xmm1
mulps %xmm1, %xmm1
cvtps2pd %xmm1, %xmm1
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
mulss %xmm0, %xmm0
cvtss2sd %xmm0, %xmm0
addsd %xmm2, %xmm0
sqrtsd %xmm0, %xmm0
xorps %xmm2, %xmm2
cvtsd2ss %xmm0, %xmm2
movss 0x4c(%rsp), %xmm0
movaps %xmm2, %xmm4
subss %xmm0, %xmm4
movss 0x48(%rsp), %xmm3
subss %xmm3, %xmm4
maxss 0x3be1(%rip), %xmm4     # 0x120b0
leaq 0x20912ce(%rip), %rcx   # 0x209f7a4
movl (%rcx), %ecx
xorps %xmm1, %xmm1
cvtsi2sd %rcx, %xmm1
cvtss2sd %xmm4, %xmm4
addsd 0x6f94(%rip), %xmm1     # 0x15480
ucomisd %xmm1, %xmm4
jae 0xe5b2
addss %xmm2, %xmm0
addss %xmm0, %xmm3
xorps %xmm0, %xmm0
cvtss2sd %xmm3, %xmm0
ucomisd %xmm0, %xmm1
ja 0xe61d
movl (%r15), %esi
movsd 0x6f76(%rip), %xmm0     # 0x15490
testl %esi, %esi
je 0xe5ac
movl (%r12), %ecx
xorl %ebx, %ebx
movss 0x6f74(%rip), %xmm0     # 0x154a4
testl %ecx, %ecx
je 0xe583
xorl %r13d, %r13d
movss %xmm0, 0x44(%rsp)
movq 0x10(%r15,%rbx,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x20(%rsp)
movq (%r14,%r13,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x28(%rsp)
callq 0xd340
leaq 0x20(%rsp), %rdi
minss 0x44(%rsp), %xmm0
incq %r13
movl (%r12), %ecx
cmpq %rcx, %r13
jb 0xe537
movl (%r15), %esi
movq 0x10(%rsp), %rax
movl 0xc(%rsp), %r11d
jmp 0xe585
xorl %ecx, %ecx
incq %rbx
movl %esi, %edx
cmpq %rdx, %rbx
jb 0xe530
leaq 0x209120e(%rip), %rcx   # 0x209f7a4
movl (%rcx), %ecx
xorps %xmm1, %xmm1
cvtsi2sd %rcx, %xmm1
addsd 0x6ed8(%rip), %xmm1     # 0x15480
cvtss2sd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jb 0xe61d
callq 0xa0a1
cmpl $0x0, (%r15)
je 0xe5de
movl 0x3c(%rsp), %eax
notb %bpl
xorl %ecx, %ecx
movq 0x10(%r15,%rcx,8), %rdx
movq 0x28(%rdx), %rdx
andb %bpl, (%rdx,%rax)
incq %rcx
movl (%r15), %edx
cmpq %rdx, %rcx
jb 0xe5c6
cmpl $0x0, (%r12)
movq 0x10(%rsp), %rdx
movb 0xb(%rsp), %sil
je 0xe609
xorl %eax, %eax
movq (%r14,%rax,8), %rcx
movq 0x28(%rcx), %rcx
andb %sil, (%rcx,%rdx)
incq %rax
movl (%r12), %ecx
cmpq %rcx, %rax
jb 0xe5f1
callq 0xa0b2
movq 0x10(%rsp), %rax
leaq 0x20(%rsp), %rdi
movl 0xc(%rsp), %r11d
movl 0x40(%rsp), %esi
incl %esi
movl $0x810, %ecx            # imm = 0x810
addq %rcx, %r12
addq %rcx, %r14
leaq 0x209112f(%rip), %rcx   # 0x209f764
cmpl (%rcx), %esi
jb 0xe1f6
callq 0x9e2c
leaq 0x20(%rsp), %rdi
cmpl $-0x1, %eax
jne 0xe18c
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq