// File: /workspace/github_cpp_makefile_star2_O1/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 0x9f1c
cmpl $-0x1, %eax
je 0xea65
movl %eax, %r14d
movl $0x1, %r8d
movl $0x810, %r13d           # imm = 0x810
leal 0x1(%r14), %r9d
leaq 0x20911f8(%rip), %rax   # 0x209f774
cmpl (%rax), %r9d
jae 0xea4e
leaq 0x20911f4(%rip), %rax   # 0x209f780
movq (%rax), %rax
movslq %r14d, %rcx
imulq $0x810, %rcx, %rdx      # imm = 0x810
leaq (%rax,%rdx), %r15
movslq %r9d, %rsi
imulq $0x810, %rsi, %r12      # imm = 0x810
addq %rax, %r12
andb $0x7, %cl
movl $0x1, %edi
shll %cl, %edi
sarl $0x3, %r14d
movl %edi, %ecx
notb %cl
movb %cl, 0x7(%rsp)
leaq (%rax,%rdx), %rbp
addq $0x820, %rbp            # imm = 0x820
movq %r14, 0x60(%rsp)
movl %edi, 0x44(%rsp)
movl %r9d, %ecx
andb $0x7, %cl
movl $0x1, %eax
shll %cl, %eax
movl %eax, 0x14(%rsp)
movl %r9d, %eax
sarl $0x3, %eax
movl (%r15), %ecx
testq %rcx, %rcx
movl %eax, 0x48(%rsp)
je 0xe623
movl %eax, %edx
xorl %esi, %esi
xorl %eax, %eax
movl 0x14(%rsp), %r10d
movq 0x10(%r15,%rsi,8), %rdi
movq 0x28(%rdi), %rdi
movzbl (%rdi,%rdx), %edi
testl %edi, %r10d
movzbl %al, %eax
cmovnel %r8d, %eax
incq %rsi
cmpq %rsi, %rcx
jne 0xe602
jmp 0xe625
xorl %eax, %eax
movl (%r12), %ecx
testq %rcx, %rcx
je 0xe653
xorl %edx, %edx
movl 0x44(%rsp), %edi
movq (%rbp,%rdx,8), %rsi
movq 0x28(%rsi), %rsi
movzbl (%rsi,%r14), %esi
testl %esi, %edi
movzbl %al, %eax
cmovnel %r8d, %eax
incq %rdx
cmpq %rdx, %rcx
jne 0xe634
testb $0x1, %al
je 0xea35
movl %r9d, 0x8(%rsp)
movq %r15, 0x50(%rsp)
movq %r12, 0x58(%rsp)
xorl %eax, %eax
xorl %ecx, %ecx
movl %ecx, 0x18(%rsp,%rax,4)
leaq (%rax,%rax,2), %rsi
movl %ecx, 0x28(%rsp,%rsi,4)
movq $0x0, 0x20(%rsp,%rsi,4)
movq 0x50(%rsp,%rax,8), %rcx
movl (%rcx), %edx
testq %rdx, %rdx
je 0xe6f9
leaq (%rsp,%rsi,4), %rsi
addq $0x20, %rsi
xorl %edi, %edi
movq 0x10(%rcx,%rdi,8), %r8
movq 0x18(%r8), %r9
movslq 0x4(%r9), %r8
testq %r8, %r8
jle 0xe6f1
movsd (%rsi), %xmm1
movss 0x8(%rsi), %xmm0
movl 0x18(%rsp,%rax,4), %r10d
leaq (,%r8,4), %r11
leaq (%r11,%r11,2), %r11
xorl %ebx, %ebx
movsd 0x8(%r9,%rbx), %xmm2
addps %xmm2, %xmm1
addss 0x10(%r9,%rbx), %xmm0
addq $0xc, %rbx
cmpq %rbx, %r11
jne 0xe6c7
addl %r10d, %r8d
movlps %xmm1, (%rsi)
movss %xmm0, 0x8(%rsi)
movl %r8d, 0x18(%rsp,%rax,4)
incq %rdi
cmpq %rdx, %rdi
jne 0xe699
leaq 0x1(%rax), %rcx
testq %rax, %rax
movq %rcx, %rax
je 0xe66c
movl 0x1c(%rsp), %eax
movl $0x17, %ecx
orl 0x18(%rsp), %eax
je 0xe884
xorl %ebx, %ebx
xorps %xmm0, %xmm0
cvtsi2ssl 0x18(%rsp,%rbx,4), %xmm0
leaq (%rbx,%rbx,2), %rdx
cvtss2sd %xmm0, %xmm0
movsd 0x69b9(%rip), %xmm1     # 0x150f0
divsd %xmm0, %xmm1
cvtps2pd 0x20(%rsp,%rdx,4), %xmm0
movapd %xmm1, %xmm2
unpcklpd %xmm1, %xmm2            # xmm2 = xmm2[0],xmm1[0]
mulpd %xmm0, %xmm2
cvtpd2ps %xmm2, %xmm0
movlpd %xmm0, 0x20(%rsp,%rdx,4)
xorps %xmm0, %xmm0
cvtss2sd 0x28(%rsp,%rdx,4), %xmm0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x28(%rsp,%rdx,4)
movl $0x0, 0xc(%rsp,%rbx,4)
movq 0x50(%rsp,%rbx,8), %rax
movl (%rax), %ecx
testq %rcx, %rcx
je 0xe80b
leaq (%rsp,%rdx,4), %rdx
addq $0x20, %rdx
xorl %esi, %esi
movq 0x10(%rax,%rsi,8), %rdi
movq 0x18(%rdi), %rdi
movslq 0x4(%rdi), %r8
testq %r8, %r8
jle 0xe803
movss (%rdx), %xmm1
movss 0x4(%rdx), %xmm3
movss 0xc(%rsp,%rbx,4), %xmm2
shlq $0x2, %r8
leaq (%r8,%r8,2), %r8
xorl %r9d, %r9d
movss 0x8(%rdi,%r9), %xmm4
subss %xmm1, %xmm4
movss 0xc(%rdi,%r9), %xmm5
subss %xmm3, %xmm5
movss 0x10(%rdi,%r9), %xmm6
subss %xmm0, %xmm6
mulss %xmm5, %xmm5
mulss %xmm4, %xmm4
addss %xmm5, %xmm4
mulss %xmm6, %xmm6
addss %xmm4, %xmm6
maxss %xmm6, %xmm2
addq $0xc, %r9
cmpq %r9, %r8
jne 0xe7bb
movss %xmm2, 0xc(%rsp,%rbx,4)
incq %rsi
cmpq %rcx, %rsi
jne 0xe78f
movss 0xc(%rsp,%rbx,4), %xmm0
ucomiss 0x392c(%rip), %xmm0     # 0x12144
jb 0xe820
sqrtss %xmm0, %xmm0
jmp 0xe825
callq 0x3440
movss %xmm0, 0xc(%rsp,%rbx,4)
leaq 0x1(%rbx), %rax
testq %rbx, %rbx
movq %rax, %rbx
je 0xe71e
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
ucomisd 0x6a14(%rip), %xmm0     # 0x15290
jb 0xe891
sqrtsd %xmm0, %xmm0
jmp 0xe896
movl $0x1, %r8d
movl 0x8(%rsp), %r9d
jmp 0xe90c
callq 0x31a0
movl $0x1, %r8d
movl 0x8(%rsp), %r9d
movl $0x17, %ecx
xorps %xmm1, %xmm1
cvtsd2ss %xmm0, %xmm1
movss 0xc(%rsp), %xmm0
movss 0x10(%rsp), %xmm2
movaps %xmm1, %xmm4
subss %xmm0, %xmm4
subss %xmm2, %xmm4
maxss 0x3878(%rip), %xmm4     # 0x12144
leaq 0x2090ee1(%rip), %rax   # 0x209f7b4
movl (%rax), %eax
xorps %xmm3, %xmm3
cvtsi2sd %rax, %xmm3
cvtss2sd %xmm4, %xmm4
addsd 0x6ba7(%rip), %xmm3     # 0x15490
ucomisd %xmm3, %xmm4
jae 0xe90c
addss %xmm1, %xmm0
addss %xmm2, %xmm0
cvtss2sd %xmm0, %xmm0
ucomisd %xmm0, %xmm3
movl $0x0, %ecx
movl $0xd, %eax
cmoval %eax, %ecx
cmpl $0x17, %ecx
je 0xe9cf
cmpl $0xd, %ecx
je 0xea35
cmpl $0x0, (%r15)
movsd 0x6b76(%rip), %xmm0     # 0x154a0
je 0xe9b0
xorl %ebx, %ebx
movss 0x6b7a(%rip), %xmm0     # 0x154b4
cmpl $0x0, (%r12)
je 0xe98b
xorl %r14d, %r14d
movaps %xmm0, %xmm1
leaq 0x20(%rsp), %r13
movss %xmm1, 0x4c(%rsp)
movq 0x10(%r15,%rbx,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x20(%rsp)
movq (%rbp,%r14,8), %rax
movq 0x18(%rax), %rax
movq %rax, 0x28(%rsp)
movq %r13, %rdi
callq 0xd4b7
minss 0x4c(%rsp), %xmm0
incq %r14
movl (%r12), %eax
movaps %xmm0, %xmm1
cmpq %rax, %r14
jb 0xe94c
incq %rbx
movl (%r15), %eax
cmpq %rax, %rbx
jb 0xe93a
cvtss2sd %xmm0, %xmm0
movq 0x60(%rsp), %r14
movl $0x1, %r8d
movl $0x810, %r13d           # imm = 0x810
movl 0x8(%rsp), %r9d
leaq 0x2090dfd(%rip), %rax   # 0x209f7b4
movl (%rax), %eax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
addsd 0x6ac7(%rip), %xmm1     # 0x15490
ucomisd %xmm1, %xmm0
jb 0xea35
callq 0xa191
cmpl $0x0, (%r15)
movl 0x14(%rsp), %esi
je 0xe9ff
movl 0x48(%rsp), %eax
notb %sil
xorl %ecx, %ecx
movq 0x10(%r15,%rcx,8), %rdx
movq 0x28(%rdx), %rdx
andb %sil, (%rdx,%rax)
incq %rcx
movl (%r15), %edx
cmpq %rdx, %rcx
jb 0xe9e7
cmpl $0x0, (%r12)
movb 0x7(%rsp), %dl
je 0xea25
xorl %eax, %eax
movq (%rbp,%rax,8), %rcx
movq 0x28(%rcx), %rcx
andb %dl, (%rcx,%r14)
incq %rax
movl (%r12), %ecx
cmpq %rcx, %rax
jb 0xea0c
callq 0xa1a2
movl $0x1, %r8d
movl 0x8(%rsp), %r9d
incl %r9d
addq %r13, %r12
addq %r13, %rbp
leaq 0x2090d2f(%rip), %rax   # 0x209f774
cmpl (%rax), %r9d
jb 0xe5d4
callq 0x9f1c
movl $0x1, %r8d
movl %eax, %r14d
cmpl $-0x1, %eax
jne 0xe571
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq