// File: FreeSlave[P]vhlt/hlrad/lightmap.cpp
// Function: TranslateTexToTex(int, int, int, matrix_t&, matrix_t&)
static bool TranslateTexToTex (int facenum, int edgenum, int facenum2, matrix_t &m, matrix_t &m_inverse)
	// This function creates a matrix that can translate texture coords in face1 into texture coords in face2.
	// It keeps all points in the common edge invariant. For example, if there is a point in the edge, and in the texture of face1, its (s,t)=(16,0), and in face2, its (s,t)=(128,64), then we must let matrix*(16,0,0)=(128,64,0)
{
	matrix_t worldtotex;
	matrix_t worldtotex2;
	dedge_t *e;
	int i;
	dvertex_t *vert[2];
	vec3_t face_vert[2];
	vec3_t face2_vert[2];
	vec3_t face_axis[2];
	vec3_t face2_axis[2];
	const vec3_t v_up = {0, 0, 1};
	vec_t len;
	vec_t len2;
	matrix_t edgetotex, edgetotex2;
	matrix_t inv, inv2;

	TranslateWorldToTex (facenum, worldtotex);
	TranslateWorldToTex (facenum2, worldtotex2);

	e = &g_dedges[edgenum];
	for (i = 0; i < 2; i++)
	{
		vert[i] = &g_dvertexes[e->v[i]];
		ApplyMatrix (worldtotex, vert[i]->point, face_vert[i]);
		face_vert[i][2] = 0; // this value is naturally close to 0 assuming that the edge is on the face plane, but let's make this more explicit.
		ApplyMatrix (worldtotex2, vert[i]->point, face2_vert[i]);
		face2_vert[i][2] = 0;
	}

	VectorSubtract (face_vert[1], face_vert[0], face_axis[0]);
	len = VectorLength (face_axis[0]);
	CrossProduct (v_up, face_axis[0], face_axis[1]);
	if (CalcMatrixSign (worldtotex) < 0.0) // the three vectors s, t, facenormal are in reverse order
	{
		VectorInverse (face_axis[1]);
	}

	VectorSubtract (face2_vert[1], face2_vert[0], face2_axis[0]);
	len2 = VectorLength (face2_axis[0]);
	CrossProduct (v_up, face2_axis[0], face2_axis[1]);
	if (CalcMatrixSign (worldtotex2) < 0.0)
	{
		VectorInverse (face2_axis[1]);
	}

	VectorCopy (face_axis[0], edgetotex.v[0]); // / v[0][0] v[1][0] \ is a rotation (possibly with a reflection by the edge)
	VectorCopy (face_axis[1], edgetotex.v[1]); // \ v[0][1] v[1][1] / 
	VectorScale (v_up, len, edgetotex.v[2]); // encode the length into the 3rd value of the matrix
	VectorCopy (face_vert[0], edgetotex.v[3]); // map (0,0) into the origin point

	VectorCopy (face2_axis[0], edgetotex2.v[0]);
	VectorCopy (face2_axis[1], edgetotex2.v[1]);
	VectorScale (v_up, len2, edgetotex2.v[2]);
	VectorCopy (face2_vert[0], edgetotex2.v[3]);

	if (!InvertMatrix (edgetotex, inv) || !InvertMatrix (edgetotex2, inv2))
	{
		return false;
	}
	MultiplyMatrix (edgetotex2, inv, m);
	MultiplyMatrix (edgetotex, inv2, m_inverse);

	return true;
}

// Assembly:
subq $0x208, %rsp            # imm = 0x208
movl %edi, 0x200(%rsp)
movl %esi, 0x1fc(%rsp)
movl %edx, 0x1f8(%rsp)
movq %rcx, 0x1f0(%rsp)
movq %r8, 0x1e8(%rsp)
movq 0x413f1(%rip), %rax     # 0x6dd84
movq %rax, 0xd4(%rsp)
movl 0x413eb(%rip), %eax     # 0x6dd8c
movl %eax, 0xdc(%rsp)
movl 0x200(%rsp), %edi
leaq 0x1b8(%rsp), %rsi
callq 0x5dfe0
movl 0x1f8(%rsp), %edi
leaq 0x188(%rsp), %rsi
callq 0x5dfe0
movslq 0x1fc(%rsp), %rcx
leaq 0x1d39a31(%rip), %rax   # 0x1d66410
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x180(%rsp)
movl $0x0, 0x17c(%rsp)
cmpl $0x2, 0x17c(%rsp)
jge 0x2caf5
movq 0x180(%rsp), %rax
movslq 0x17c(%rsp), %rcx
movzwl (%rax,%rcx,2), %eax
leaq 0x10399ee(%rip), %rcx   # 0x1066410
imulq $0xc, %rax, %rax
addq %rax, %rcx
movslq 0x17c(%rsp), %rax
movq %rcx, 0x160(%rsp,%rax,8)
movslq 0x17c(%rsp), %rax
movq 0x160(%rsp,%rax,8), %rsi
movslq 0x17c(%rsp), %rax
leaq 0x140(%rsp), %rdx
imulq $0xc, %rax, %rax
addq %rax, %rdx
leaq 0x1b8(%rsp), %rdi
callq 0x5d920
movslq 0x17c(%rsp), %rcx
leaq 0x140(%rsp), %rax
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
xorps %xmm0, %xmm0
movss %xmm0, 0x8(%rax)
movslq 0x17c(%rsp), %rax
movq 0x160(%rsp,%rax,8), %rsi
movslq 0x17c(%rsp), %rax
leaq 0x120(%rsp), %rdx
imulq $0xc, %rax, %rax
addq %rax, %rdx
leaq 0x188(%rsp), %rdi
callq 0x5d920
movslq 0x17c(%rsp), %rcx
leaq 0x120(%rsp), %rax
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
xorps %xmm0, %xmm0
movss %xmm0, 0x8(%rax)
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x17c(%rsp)
jmp 0x2c9f9
movss 0x14c(%rsp), %xmm0
subss 0x140(%rsp), %xmm0
movss %xmm0, 0x100(%rsp)
movss 0x150(%rsp), %xmm0
subss 0x144(%rsp), %xmm0
movss %xmm0, 0x104(%rsp)
movss 0x154(%rsp), %xmm0
subss 0x148(%rsp), %xmm0
movss %xmm0, 0x108(%rsp)
movss 0x100(%rsp), %xmm0
mulss 0x100(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movss 0x104(%rsp), %xmm1
mulss 0x104(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
movss 0x108(%rsp), %xmm1
mulss 0x108(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
callq 0x4270
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0xd0(%rsp)
movss 0xd8(%rsp), %xmm0
movss 0x108(%rsp), %xmm2
movss 0xdc(%rsp), %xmm1
mulss 0x104(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x10c(%rsp)
movss 0xdc(%rsp), %xmm0
movss 0x100(%rsp), %xmm2
movss 0xd4(%rsp), %xmm1
mulss 0x108(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x110(%rsp)
movss 0xd4(%rsp), %xmm0
movss 0x104(%rsp), %xmm2
movss 0xd8(%rsp), %xmm1
mulss 0x100(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x114(%rsp)
leaq 0x1b8(%rsp), %rdi
callq 0x5ded0
cvtss2sd %xmm0, %xmm1
xorps %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2ccdf
movss 0x10c(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0x10c(%rsp)
movss 0x110(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0x110(%rsp)
movss 0x114(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0x114(%rsp)
movss 0x12c(%rsp), %xmm0
subss 0x120(%rsp), %xmm0
movss %xmm0, 0xe0(%rsp)
movss 0x130(%rsp), %xmm0
subss 0x124(%rsp), %xmm0
movss %xmm0, 0xe4(%rsp)
movss 0x134(%rsp), %xmm0
subss 0x128(%rsp), %xmm0
movss %xmm0, 0xe8(%rsp)
movss 0xe0(%rsp), %xmm0
mulss 0xe0(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movss 0xe4(%rsp), %xmm1
mulss 0xe4(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
movss 0xe8(%rsp), %xmm1
mulss 0xe8(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
callq 0x4270
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0xcc(%rsp)
movss 0xd8(%rsp), %xmm0
movss 0xe8(%rsp), %xmm2
movss 0xdc(%rsp), %xmm1
mulss 0xe4(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0xec(%rsp)
movss 0xdc(%rsp), %xmm0
movss 0xe0(%rsp), %xmm2
movss 0xd4(%rsp), %xmm1
mulss 0xe8(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0xf0(%rsp)
movss 0xd4(%rsp), %xmm0
movss 0xe4(%rsp), %xmm2
movss 0xd8(%rsp), %xmm1
mulss 0xe0(%rsp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0xf4(%rsp)
leaq 0x188(%rsp), %rdi
callq 0x5ded0
cvtss2sd %xmm0, %xmm1
xorps %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2cec9
movss 0xec(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0xec(%rsp)
movss 0xf0(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0xf0(%rsp)
movss 0xf4(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movss %xmm0, 0xf4(%rsp)
movss 0x100(%rsp), %xmm0
movss %xmm0, 0x9c(%rsp)
movss 0x104(%rsp), %xmm0
movss %xmm0, 0xa0(%rsp)
movss 0x108(%rsp), %xmm0
movss %xmm0, 0xa4(%rsp)
movss 0x10c(%rsp), %xmm0
movss %xmm0, 0xa8(%rsp)
movss 0x110(%rsp), %xmm0
movss %xmm0, 0xac(%rsp)
movss 0x114(%rsp), %xmm0
movss %xmm0, 0xb0(%rsp)
movss 0xd4(%rsp), %xmm0
mulss 0xd0(%rsp), %xmm0
movss %xmm0, 0xb4(%rsp)
movss 0xd8(%rsp), %xmm0
mulss 0xd0(%rsp), %xmm0
movss %xmm0, 0xb8(%rsp)
movss 0xdc(%rsp), %xmm0
mulss 0xd0(%rsp), %xmm0
movss %xmm0, 0xbc(%rsp)
movss 0x140(%rsp), %xmm0
movss %xmm0, 0xc0(%rsp)
movss 0x144(%rsp), %xmm0
movss %xmm0, 0xc4(%rsp)
movss 0x148(%rsp), %xmm0
movss %xmm0, 0xc8(%rsp)
movss 0xe0(%rsp), %xmm0
movss %xmm0, 0x6c(%rsp)
movss 0xe4(%rsp), %xmm0
movss %xmm0, 0x70(%rsp)
movss 0xe8(%rsp), %xmm0
movss %xmm0, 0x74(%rsp)
movss 0xec(%rsp), %xmm0
movss %xmm0, 0x78(%rsp)
movss 0xf0(%rsp), %xmm0
movss %xmm0, 0x7c(%rsp)
movss 0xf4(%rsp), %xmm0
movss %xmm0, 0x80(%rsp)
movss 0xd4(%rsp), %xmm0
mulss 0xcc(%rsp), %xmm0
movss %xmm0, 0x84(%rsp)
movss 0xd8(%rsp), %xmm0
mulss 0xcc(%rsp), %xmm0
movss %xmm0, 0x88(%rsp)
movss 0xdc(%rsp), %xmm0
mulss 0xcc(%rsp), %xmm0
movss %xmm0, 0x8c(%rsp)
movss 0x120(%rsp), %xmm0
movss %xmm0, 0x90(%rsp)
movss 0x124(%rsp), %xmm0
movss %xmm0, 0x94(%rsp)
movss 0x128(%rsp), %xmm0
movss %xmm0, 0x98(%rsp)
leaq 0x9c(%rsp), %rdi
leaq 0x3c(%rsp), %rsi
callq 0x5e120
testb $0x1, %al
jne 0x2d0b8
jmp 0x2d0cb
leaq 0x6c(%rsp), %rdi
leaq 0xc(%rsp), %rsi
callq 0x5e120
testb $0x1, %al
jne 0x2d0d5
movb $0x0, 0x207(%rsp)
jmp 0x2d10e
movq 0x1f0(%rsp), %rdx
leaq 0x6c(%rsp), %rdi
leaq 0x3c(%rsp), %rsi
callq 0x5dbd0
movq 0x1e8(%rsp), %rdx
leaq 0x9c(%rsp), %rdi
leaq 0xc(%rsp), %rsi
callq 0x5dbd0
movb $0x1, 0x207(%rsp)
movb 0x207(%rsp), %al
andb $0x1, %al
addq $0x208, %rsp            # imm = 0x208
retq
nop