summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/BoundingBox.cpp
blob: 9ea0fa5689170c78c9054f00c40c39b2c9d9d479 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.



#include "VideoBackends/Software/Clipper.h"
#include "VideoBackends/Software/Rasterizer.h"
#include "VideoBackends/Software/SetupUnit.h"
#include "VideoBackends/Software/TransformUnit.h"
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/PixelShaderManager.h"


namespace BoundingBox
{

// External vars
bool active = false;
u16 coords[4] = { 0x80, 0xA0, 0x80, 0xA0 };
u8 posMtxIdx;
u8 texMtxIdx[8];


// Internal vars
static SetupUnit vtxUnit;
static VAT myVat;
static u8 * bufferPos;
static TVtxDesc vertexDesc;
static PortableVertexDeclaration vertexDecl;

// Gets the pointer to the current buffer position
void LOADERDECL SetVertexBufferPosition(VertexLoader* loader)
{
	bufferPos = g_vertex_manager_write_ptr;
}

// Prepares the bounding box for new primitive data
void Prepare(const VAT & vat, int primitive, const TVtxDesc & vtxDesc, const PortableVertexDeclaration & vtxDecl)
{
	if (!active)
		return;

	myVat = vat;
	vertexDesc = vtxDesc;
	vertexDecl = vtxDecl;

	vtxUnit.Init(primitive);

	// Initialize the SW renderer
	static bool SWinit = false;

	if (!SWinit)
	{
		Clipper::Init();
		Rasterizer::Init();
		SWinit = true;
	}

	// Update SW renderer values
	Clipper::SetViewOffset();
	Rasterizer::SetScissor();

	for (u8 i = 0; i < 4; ++i)
	{
		Rasterizer::SetTevReg(i, 0, true, (s16)PixelShaderManager::constants.kcolors[i][0]);
		Rasterizer::SetTevReg(i, 1, true, (s16)PixelShaderManager::constants.kcolors[i][1]);
		Rasterizer::SetTevReg(i, 2, true, (s16)PixelShaderManager::constants.kcolors[i][2]);
		Rasterizer::SetTevReg(i, 3, true, (s16)PixelShaderManager::constants.kcolors[i][3]);

		Rasterizer::SetTevReg(i, 0, false, (s16)PixelShaderManager::constants.colors[i][0]);
		Rasterizer::SetTevReg(i, 1, false, (s16)PixelShaderManager::constants.colors[i][1]);
		Rasterizer::SetTevReg(i, 2, false, (s16)PixelShaderManager::constants.colors[i][2]);
		Rasterizer::SetTevReg(i, 3, false, (s16)PixelShaderManager::constants.colors[i][3]);
	}
}

// Updates the bounding box
void LOADERDECL Update(VertexLoader* loader)
{
	if (!active)
		return;

	// Grab vertex input data and transform to output vertex
	InputVertexData myVertex;
	OutputVertexData * outVertex = vtxUnit.GetVertex();

	// Feed vertex position and matrix
	myVertex.position = Vec3((const float *)bufferPos);
	myVertex.posMtx = vertexDesc.PosMatIdx ? posMtxIdx : g_main_cp_state.matrix_index_a.PosNormalMtxIdx;

	// Transform position
	TransformUnit::TransformPosition(&myVertex, outVertex);

	if (g_main_cp_state.vtx_desc.Normal != NOT_PRESENT)
	{
		// Feed normal input data and transform
		memcpy((u8 *)myVertex.normal, bufferPos + vertexDecl.normals[0].offset, sizeof(float) * 3 * ((myVat.g0.NormalElements) ? 3 : 1));

		TransformUnit::TransformNormal(&myVertex, myVat.g0.NormalElements, outVertex);
	}

	// Feed color input data
	for (int i = 0; i < 2; ++i)
	{
		if (vertexDecl.colors[i].enable)
		{
			u32 color;
			memcpy((u8 *)&color, bufferPos + vertexDecl.colors[i].offset, sizeof(u32));
			*(u32*)myVertex.color[i] = Common::swap32(color);
		}
	}

	// Transform color
	TransformUnit::TransformColor(&myVertex, outVertex);

	// Feed texture matrices
	int idx = 0;

	myVertex.texMtx[0] = (vertexDesc.Tex0MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_a.Tex0MtxIdx;
	myVertex.texMtx[1] = (vertexDesc.Tex1MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_a.Tex1MtxIdx;
	myVertex.texMtx[2] = (vertexDesc.Tex2MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_a.Tex2MtxIdx;
	myVertex.texMtx[3] = (vertexDesc.Tex3MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_a.Tex3MtxIdx;
	myVertex.texMtx[4] = (vertexDesc.Tex4MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_b.Tex4MtxIdx;
	myVertex.texMtx[5] = (vertexDesc.Tex5MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_b.Tex5MtxIdx;
	myVertex.texMtx[6] = (vertexDesc.Tex6MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_b.Tex6MtxIdx;
	myVertex.texMtx[7] = (vertexDesc.Tex7MatIdx) ? texMtxIdx[idx++] : g_main_cp_state.matrix_index_b.Tex7MtxIdx;

	// Feed texture coordinate data
	for (int i = 0; i < 8; ++i)
	{
		if (vertexDecl.texcoords[i].enable)
			memcpy((u8 *)&myVertex.texCoords[i], bufferPos + vertexDecl.texcoords[i].offset, sizeof(float) * 2);
	}

	// Transform texture coordinate
	TransformUnit::TransformTexCoord(&myVertex, outVertex, false);

	// Render the vertex in SW to calculate bbox
	vtxUnit.SetupVertex();
}

// Save state
void DoState(PointerWrap &p)
{
	p.Do(active);
	p.Do(coords);
}

} // namespace BoundingBox