// File: /workspace/github_cpp_makefile_star2_O2/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 $0x58, %rsp
pushq $0x1
popq %rbx
leaq 0x2091330(%rip), %rbp   # 0x209d774
xorl %r12d, %r12d
callq 0x8a18
cmpl $-0x1, %eax
je 0xc849
leaq 0x2091324(%rip), %rcx   # 0x209d780
movq (%rcx), %rdx
movslq %eax, %rcx
imulq $0x810, %rcx, %r14      # imm = 0x810
addq %rdx, %r14
leal 0x1(%rax), %esi
movslq %esi, %rcx
imulq $0x810, %rcx, %r15      # imm = 0x810
movl %eax, %edi
andb $0x7, %al
movl %ebx, %r8d
movl %eax, %ecx
shll %cl, %r8d
addq %rdx, %r15
sarl $0x3, %edi
movq %rdi, 0x38(%rsp)
movl %r8d, 0x2c(%rsp)
movl %r8d, %eax
notb %al
movb %al, 0x3(%rsp)
cmpl (%rbp), %esi
jae 0xc447
movl %esi, %edi
movl %esi, 0x28(%rsp)
movl %esi, %ecx
andb $0x7, %cl
movl %ebx, %r13d
shll %cl, %r13d
sarl $0x3, %edi
movl (%r14), %ecx
xorl %edx, %edx
xorl %eax, %eax
cmpq %rdx, %rcx
je 0xc4df
movq 0x10(%r14,%rdx,8), %rsi
movq 0x28(%rsi), %rsi
movzbl (%rsi,%rdi), %esi
testl %esi, %r13d
setne %sil
orb %sil, %al
incq %rdx
jmp 0xc4be
movq %rdi, 0x50(%rsp)
movl (%r15), %ecx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0xc510
movq 0x10(%r15,%rdx,8), %rsi
movq 0x28(%rsi), %rsi
movq 0x38(%rsp), %rdi
movzbl (%rsi,%rdi), %esi
testl %esi, 0x2c(%rsp)
setne %sil
orb %sil, %al
incq %rdx
jmp 0xc4e9
testb $0x1, %al
je 0xc837
movq %r14, 0x40(%rsp)
movq %r15, 0x48(%rsp)
xorl %eax, %eax
cmpq $0x2, %rax
je 0xc5af
andl $0x0, 0x8(%rsp,%rax,4)
imulq $0xc, %rax, %rcx
addq %rsp, %rcx
addq $0x10, %rcx
andl $0x0, 0x8(%rcx)
andq $0x0, (%rcx)
movq 0x40(%rsp,%rax,8), %rdx
movl (%rdx), %esi
xorps %xmm0, %xmm0
xorps %xmm1, %xmm1
xorl %edi, %edi
xorl %r8d, %r8d
cmpq %rsi, %r8
je 0xc5a7
movq 0x10(%rdx,%r8,8), %r9
movq 0x18(%r9), %r9
movl 0x4(%r9), %r10d
testl %r10d, %r10d
cmovlel %r12d, %r10d
imulq $0xc, %r10, %r10
xorl %r11d, %r11d
cmpq %r11, %r10
je 0xc5a2
movsd 0x8(%r9,%r11), %xmm2
addps %xmm2, %xmm0
movlps %xmm0, (%rcx)
addss 0x10(%r9,%r11), %xmm1
movss %xmm1, 0x8(%rcx)
incl %edi
movl %edi, 0x8(%rsp,%rax,4)
addq $0xc, %r11
jmp 0xc578
incq %r8
jmp 0xc558
incq %rax
jmp 0xc524
movl 0xc(%rsp), %eax
orl 0x8(%rsp), %eax
je 0xc7e3
xorl %ebp, %ebp
cmpq $0x2, %rbp
je 0xc6b5
cvtsi2ssl 0x8(%rsp,%rbp,4), %xmm0
imulq $0xc, %rbp, %rax
cvtss2sd %xmm0, %xmm0
movsd 0x6a71(%rip), %xmm2     # 0x13050
divsd %xmm0, %xmm2
cvtps2pd 0x10(%rsp,%rax), %xmm0
movapd %xmm2, %xmm1
unpcklpd %xmm2, %xmm1            # xmm1 = xmm1[0],xmm2[0]
mulpd %xmm0, %xmm1
cvtpd2ps %xmm1, %xmm1
movlpd %xmm1, 0x10(%rsp,%rax)
cvtss2sd 0x18(%rsp,%rax), %xmm0
mulsd %xmm2, %xmm0
cvtsd2ss %xmm0, %xmm2
movss %xmm2, 0x18(%rsp,%rax)
movq 0x40(%rsp,%rbp,8), %rax
movl (%rax), %ecx
movapd %xmm1, %xmm3
shufps $0x55, %xmm1, %xmm3     # xmm3 = xmm3[1,1],xmm1[1,1]
xorps %xmm0, %xmm0
xorl %edx, %edx
cmpq %rcx, %rdx
je 0xc693
movq 0x10(%rax,%rdx,8), %rsi
movq 0x18(%rsi), %rsi
movl 0x4(%rsi), %edi
testl %edi, %edi
cmovlel %r12d, %edi
imulq $0xc, %rdi, %rdi
xorl %r8d, %r8d
cmpq %r8, %rdi
je 0xc68e
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
movss %xmm0, 0x30(%rsp,%rbp,4)
addq $0xc, %r8
jmp 0xc644
incq %rdx
jmp 0xc626
ucomiss 0x39d6(%rip), %xmm0     # 0x10070
jb 0xc6a2
sqrtss %xmm0, %xmm0
jmp 0xc6a7
callq 0x3440
movss %xmm0, 0x30(%rsp,%rbp,4)
incq %rbp
jmp 0xc5bf
movss 0x18(%rsp), %xmm0
subss 0x24(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
movsd 0x1c(%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
cvtsd2ss %xmm0, %xmm2
movss 0x30(%rsp), %xmm0
movss 0x34(%rsp), %xmm1
movaps %xmm2, %xmm4
subss %xmm0, %xmm4
subss %xmm1, %xmm4
maxss 0x395b(%rip), %xmm4     # 0x10070
leaq 0x2091098(%rip), %rax   # 0x209d7b4
movl (%rax), %eax
cvtsi2sd %rax, %xmm3
cvtss2sd %xmm4, %xmm4
addsd 0x6ca1(%rip), %xmm3     # 0x133d0
ucomisd %xmm3, %xmm4
pushq $0x1
popq %rbx
leaq 0x2091037(%rip), %rbp   # 0x209d774
jae 0xc7e3
addss %xmm2, %xmm0
addss %xmm0, %xmm1
cvtss2sd %xmm1, %xmm0
ucomisd %xmm0, %xmm3
ja 0xc837
xorl %ebp, %ebp
movss 0x6c91(%rip), %xmm0     # 0x133f4
movss %xmm0, 0x4(%rsp)
movl (%r14), %eax
cmpq %rax, %rbp
jae 0xc7b7
xorl %ebx, %ebx
movl (%r15), %eax
cmpq %rax, %rbx
jae 0xc7b2
movq 0x10(%r14,%rbp,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0x10(%r15,%rbx,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
leaq 0x10(%rsp), %rdi
callq 0xb8ac
minss 0x4(%rsp), %xmm0
incq %rbx
movss %xmm0, 0x4(%rsp)
jmp 0xc773
incq %rbp
jmp 0xc769
leaq 0x2090ff6(%rip), %rax   # 0x209d7b4
movl (%rax), %eax
cvtsi2sd %rax, %xmm0
cvtss2sd 0x4(%rsp), %xmm1
addsd 0x6bfd(%rip), %xmm0     # 0x133d0
ucomisd %xmm0, %xmm1
pushq $0x1
popq %rbx
leaq 0x2090f93(%rip), %rbp   # 0x209d774
jb 0xc837
callq 0x8c3c
notb %r13b
xorl %eax, %eax
movb 0x3(%rsp), %sil
movq 0x50(%rsp), %rdx
movl (%r14), %ecx
cmpq %rcx, %rax
jae 0xc811
movq 0x10(%r14,%rax,8), %rcx
movq 0x28(%rcx), %rcx
andb %r13b, (%rcx,%rdx)
incq %rax
jmp 0xc7f7
xorl %eax, %eax
movl (%r15), %ecx
cmpq %rcx, %rax
jae 0xc832
movq 0x10(%r15,%rax,8), %rcx
movq 0x28(%rcx), %rcx
movq 0x38(%rsp), %rdx
andb %sil, (%rcx,%rdx)
incq %rax
jmp 0xc813
callq 0x8c4d
movl 0x28(%rsp), %esi
incl %esi
addq $0x810, %r15            # imm = 0x810
jmp 0xc49e
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq