本文整理汇总了C++中VertexDecoder::GetDecVtxFmt方法的典型用法代码示例。如果您正苦于以下问题:C++ VertexDecoder::GetDecVtxFmt方法的具体用法?C++ VertexDecoder::GetDecVtxFmt怎么用?C++ VertexDecoder::GetDecVtxFmt使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类VertexDecoder
的用法示例。
在下文中一共展示了VertexDecoder::GetDecVtxFmt方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: SubmitSpline
void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type)
{
VertexDecoder vdecoder;
vdecoder.SetVertexType(vertex_type);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
static u8 buf[65536 * 48]; // yolo
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
u8* indices8 = (u8*)indices;
u16* indices16 = (u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, control_points, index_lower_bound, index_upper_bound);
VertexReader vreader(buf, vtxfmt, vertex_type);
int num_patches_u = count_u - 3;
int num_patches_v = count_v - 3;
// TODO: Do something less idiotic to manage this buffer
SplinePatch* patches = new SplinePatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; ++patch_u) {
for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) {
SplinePatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
if (indices)
vreader.Goto(indices_16bit ? indices16[idx] : indices8[idx]);
else
vreader.Goto(idx);
patch.points[point] = ReadVertex(vreader);
}
patch.type = (type_u | (type_v<<2));
if (patch_u != 0) patch.type &= ~START_OPEN_U;
if (patch_v != 0) patch.type &= ~START_OPEN_V;
if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U;
if (patch_v != num_patches_v-1) patch.type &= ~END_OPEN_V;
}
}
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
SplinePatch& patch = patches[patch_idx];
// TODO: Should do actual patch subdivision instead of just drawing the control points!
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : 1;
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : 1;
const int tile_max_u = (patch.type & END_OPEN_U) ? 3 : 2;
const int tile_max_v = (patch.type & END_OPEN_V) ? 3 : 2;
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
int point_index = tile_u + tile_v*4;
VertexData v0 = patch.points[point_index];
VertexData v1 = patch.points[point_index+1];
VertexData v2 = patch.points[point_index+4];
VertexData v3 = patch.points[point_index+5];
// TODO: Backface culling etc
Clipper::ProcessTriangle(v0, v1, v2);
Clipper::ProcessTriangle(v2, v1, v0);
Clipper::ProcessTriangle(v2, v1, v3);
Clipper::ProcessTriangle(v3, v1, v2);
}
}
}
delete[] patches;
}
示例2: SubmitPrimitive
void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type)
{
// TODO: Cache VertexDecoder objects
VertexDecoder vdecoder;
vdecoder.SetVertexType(vertex_type);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
static u8 buf[65536 * 48]; // yolo
u16 index_lower_bound = 0;
u16 index_upper_bound = vertex_count - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
u8* indices8 = (u8*)indices;
u16* indices16 = (u16*)indices;
if (indices)
GetIndexBounds(indices, vertex_count, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, vertices, index_lower_bound, index_upper_bound);
VertexReader vreader(buf, vtxfmt, vertex_type);
const int max_vtcs_per_prim = 3;
int vtcs_per_prim = 0;
if (prim_type == GE_PRIM_POINTS) vtcs_per_prim = 1;
else if (prim_type == GE_PRIM_LINES) vtcs_per_prim = 2;
else if (prim_type == GE_PRIM_TRIANGLES) vtcs_per_prim = 3;
else if (prim_type == GE_PRIM_RECTANGLES) vtcs_per_prim = 2;
else {
// TODO: Unsupported
}
if (prim_type == GE_PRIM_POINTS || prim_type == GE_PRIM_LINES || prim_type == GE_PRIM_TRIANGLES || prim_type == GE_PRIM_RECTANGLES) {
for (int vtx = 0; vtx < vertex_count; vtx += vtcs_per_prim) {
VertexData data[max_vtcs_per_prim];
for (int i = 0; i < vtcs_per_prim; ++i) {
if (indices)
vreader.Goto(indices_16bit ? indices16[vtx+i] : indices8[vtx+i]);
else
vreader.Goto(vtx+i);
data[i] = ReadVertex(vreader);
if (outside_range_flag)
break;
}
if (outside_range_flag) {
outside_range_flag = false;
continue;
}
switch (prim_type) {
case GE_PRIM_TRIANGLES:
{
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
Clipper::ProcessTriangle(data[0], data[1], data[2]);
Clipper::ProcessTriangle(data[2], data[1], data[0]);
} else if (!gstate.getCullMode())
Clipper::ProcessTriangle(data[2], data[1], data[0]);
else
Clipper::ProcessTriangle(data[0], data[1], data[2]);
break;
}
case GE_PRIM_RECTANGLES:
Clipper::ProcessQuad(data[0], data[1]);
break;
}
}
} else if (prim_type == GE_PRIM_TRIANGLE_STRIP) {
VertexData data[3];
unsigned int skip_count = 2; // Don't draw a triangle when loading the first two vertices
for (int vtx = 0; vtx < vertex_count; ++vtx) {
if (indices)
vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]);
else
vreader.Goto(vtx);
data[vtx % 3] = ReadVertex(vreader);
if (outside_range_flag) {
// Drop all primitives containing the current vertex
skip_count = 2;
outside_range_flag = false;
continue;
}
if (skip_count) {
--skip_count;
continue;
}
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
Clipper::ProcessTriangle(data[0], data[1], data[2]);
Clipper::ProcessTriangle(data[2], data[1], data[0]);
} else if ((!gstate.getCullMode()) ^ (vtx % 2)) {
// We need to reverse the vertex order for each second primitive,
// but we additionally need to do that for every primitive if CCW cullmode is used.
Clipper::ProcessTriangle(data[2], data[1], data[0]);
} else {
Clipper::ProcessTriangle(data[0], data[1], data[2]);
}
//.........这里部分代码省略.........
示例3: SubmitSpline
void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type) {
VertexDecoder vdecoder;
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false;
vdecoder.SetVertexType(vertex_type, options);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
static u8 buf[65536 * 48]; // yolo
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
bool indices_32bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
u8 *indices8 = (u8 *)indices;
u16 *indices16 = (u16 *)indices;
u32 *indices32 = (u32 *)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, control_points, index_lower_bound, index_upper_bound);
VertexReader vreader(buf, vtxfmt, vertex_type);
int num_patches_u = count_u - 3;
int num_patches_v = count_v - 3;
if (patchBufferSize_ < num_patches_u * num_patches_v) {
if (patchBuffer_) {
FreeAlignedMemory(patchBuffer_);
}
patchBuffer_ = (SplinePatch *)AllocateAlignedMemory(num_patches_u * num_patches_v, 16);
patchBufferSize_ = num_patches_u * num_patches_v;
}
SplinePatch *patches = patchBuffer_;
for (int patch_u = 0; patch_u < num_patches_u; ++patch_u) {
for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) {
SplinePatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
if (indices) {
if (indices_32bit) {
vreader.Goto(indices32[idx]);
} else if (indices_16bit) {
vreader.Goto(indices16[idx]);
} else {
vreader.Goto(indices8[idx]);
}
} else {
vreader.Goto(idx);
}
patch.points[point] = ReadVertex(vreader);
}
patch.type = (type_u | (type_v<<2));
if (patch_u != 0) patch.type &= ~START_OPEN_U;
if (patch_v != 0) patch.type &= ~START_OPEN_V;
if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U;
if (patch_v != num_patches_v-1) patch.type &= ~END_OPEN_V;
}
}
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
SplinePatch& patch = patches[patch_idx];
// TODO: Should do actual patch subdivision instead of just drawing the control points!
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : 1;
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : 1;
const int tile_max_u = (patch.type & END_OPEN_U) ? 3 : 2;
const int tile_max_v = (patch.type & END_OPEN_V) ? 3 : 2;
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
int point_index = tile_u + tile_v*4;
VertexData v0 = patch.points[point_index];
VertexData v1 = patch.points[point_index+1];
VertexData v2 = patch.points[point_index+4];
VertexData v3 = patch.points[point_index+5];
// TODO: Backface culling etc
Clipper::ProcessTriangle(v0, v1, v2);
Clipper::ProcessTriangle(v2, v1, v0);
Clipper::ProcessTriangle(v2, v1, v3);
Clipper::ProcessTriangle(v3, v1, v2);
}
}
}
host->GPUNotifyDraw();
}
示例4: SubmitPrimitive
void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type, int *bytesRead)
{
// TODO: Cache VertexDecoder objects
VertexDecoder vdecoder;
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false;
vdecoder.SetVertexType(vertex_type, options);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
if (bytesRead)
*bytesRead = vertex_count * vdecoder.VertexSize();
// Frame skipping.
if (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) {
return;
}
u16 index_lower_bound = 0;
u16 index_upper_bound = vertex_count - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
bool indices_32bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
u8 *indices8 = (u8 *)indices;
u16 *indices16 = (u16 *)indices;
u32 *indices32 = (u32 *)indices;
if (indices)
GetIndexBounds(indices, vertex_count, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, vertices, index_lower_bound, index_upper_bound);
VertexReader vreader(buf, vtxfmt, vertex_type);
const int max_vtcs_per_prim = 3;
int vtcs_per_prim = 0;
switch (prim_type) {
case GE_PRIM_POINTS: vtcs_per_prim = 1; break;
case GE_PRIM_LINES: vtcs_per_prim = 2; break;
case GE_PRIM_TRIANGLES: vtcs_per_prim = 3; break;
case GE_PRIM_RECTANGLES: vtcs_per_prim = 2; break;
}
VertexData data[max_vtcs_per_prim];
// TODO: Do this in two passes - first process the vertices (before indexing/stripping),
// then resolve the indices. This lets us avoid transforming shared vertices twice.
switch (prim_type) {
case GE_PRIM_POINTS:
case GE_PRIM_LINES:
case GE_PRIM_TRIANGLES:
case GE_PRIM_RECTANGLES:
{
for (int vtx = 0; vtx < vertex_count; vtx += vtcs_per_prim) {
for (int i = 0; i < vtcs_per_prim; ++i) {
if (indices) {
if (indices_32bit) {
vreader.Goto(indices32[vtx + i]);
} else if (indices_16bit) {
vreader.Goto(indices16[vtx + i]);
} else {
vreader.Goto(indices8[vtx + i]);
}
} else {
vreader.Goto(vtx+i);
}
data[i] = ReadVertex(vreader);
if (outside_range_flag)
break;
}
if (outside_range_flag) {
outside_range_flag = false;
continue;
}
switch (prim_type) {
case GE_PRIM_TRIANGLES:
{
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
Clipper::ProcessTriangle(data[0], data[1], data[2]);
Clipper::ProcessTriangle(data[2], data[1], data[0]);
} else if (!gstate.getCullMode())
Clipper::ProcessTriangle(data[2], data[1], data[0]);
else
Clipper::ProcessTriangle(data[0], data[1], data[2]);
break;
}
case GE_PRIM_RECTANGLES:
Clipper::ProcessRect(data[0], data[1]);
break;
case GE_PRIM_LINES:
Clipper::ProcessLine(data[0], data[1]);
break;
case GE_PRIM_POINTS:
Clipper::ProcessPoint(data[0]);
break;
}
//.........这里部分代码省略.........
示例5: SubmitBezier
void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
if (prim_type != GE_PATCHPRIM_TRIANGLES) {
// Only triangles supported!
return;
}
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 24;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt();
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
BezierPatch* patches = new BezierPatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; patch_u++) {
for (int patch_v = 0; patch_v < num_patches_v; patch_v++) {
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point%4) + (patch_v * 3 + point/4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = simplified_control_points + idx;
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;
}
}
u8 *decoded2 = decoded + 65536 * 36;
int count = 0;
u8 *dest = decoded2;
// Simple approximation of the real tesselation factor.
// We shouldn't really split up into separate 4x4 patches, instead we should do something that works
// like the splines, so we subdivide across the whole "mega-patch".
if (num_patches_u == 0) num_patches_u = 1;
if (num_patches_v == 0) num_patches_v = 1;
int tess_u = gstate.getPatchDivisionU() / num_patches_u;
int tess_v = gstate.getPatchDivisionV() / num_patches_v;
if (tess_u < 4) tess_u = 4;
if (tess_v < 4) tess_v = 4;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
BezierPatch& patch = patches[patch_idx];
TesselateBezierPatch(dest, count, tess_u, tess_v, patch, origVertType);
}
delete[] patches;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, 0);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
示例6: SubmitSpline
void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
if (prim_type != GE_PATCHPRIM_TRIANGLES) {
// Only triangles supported!
return;
}
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 24;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt();
// TODO: Do something less idiotic to manage this buffer
SimpleVertex **points = new SimpleVertex *[count_u * count_v];
// Make an array of pointers to the control points, to get rid of indices.
for (int idx = 0; idx < count_u * count_v; idx++) {
if (indices)
points[idx] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
points[idx] = simplified_control_points + idx;
}
u8 *decoded2 = decoded + 65536 * 36;
int count = 0;
u8 *dest = decoded2;
SplinePatchLocal patch;
patch.type_u = type_u;
patch.type_v = type_v;
patch.count_u = count_u;
patch.count_v = count_v;
patch.points = points;
TesselateSplinePatch(dest, count, patch, origVertType);
delete[] points;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, 0);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
示例7: SubmitBezier
void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
if (prim_type != GE_PATCHPRIM_TRIANGLES) {
// Only triangles supported!
return;
}
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 24;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt();
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
BezierPatch* patches = new BezierPatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; patch_u++) {
for (int patch_v = 0; patch_v < num_patches_v; patch_v++) {
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point%4) + (patch_v * 3 + point/4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = simplified_control_points + idx;
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;
}
}
u8 *decoded2 = decoded + 65536 * 36;
int count = 0;
u8 *dest = decoded2;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
BezierPatch& patch = patches[patch_idx];
TesselateBezierPatch(dest, count, patch, origVertType);
}
delete[] patches;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, -1, 0);
Flush();
}
示例8: NormalizeVertices
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
// The implementation is initially a bit inefficient but shouldn't be a big deal.
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) {
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
// implementation of the vertex decoder.
VertexDecoder *dec = GetVertexDecoder(vertType);
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
// OK, morphing eliminated but bones still remain to be taken care of.
// Let's do a partial software transform where we only do skinning.
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
SimpleVertex *sverts = (SimpleVertex *)outPtr;
const u8 defaultColor[4] = {
(u8)gstate.getMaterialAmbientR(),
(u8)gstate.getMaterialAmbientG(),
(u8)gstate.getMaterialAmbientB(),
(u8)gstate.getMaterialAmbientA(),
};
// Let's have two separate loops, one for non skinning and one for skinning.
if ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
float nrm[3], pos[3];
float bnrm[3], bpos[3];
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm(nrm);
} else {
nrm[0] = 0;
nrm[1] = 0;
nrm[2] = 1.0f;
}
reader.ReadPos(pos);
// Apply skinning transform directly
float weights[8];
reader.ReadWeights(weights);
// Skinning
Vec3f psum(0,0,0);
Vec3f nsum(0,0,0);
for (int i = 0; i < numBoneWeights; i++) {
if (weights[i] != 0.0f) {
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix+i*12);
Vec3f tpos(bpos);
psum += tpos * weights[i];
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix+i*12);
Vec3f tnorm(bnrm);
nsum += tnorm * weights[i];
}
}
sv.pos = psum;
sv.nrm = nsum;
}
} else {
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
} else {
sv.uv[0] = 0; // This will get filled in during tesselation
sv.uv[1] = 0;
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm((float *)&sv.nrm);
} else {
sv.nrm.x = 0;
sv.nrm.y = 0;
sv.nrm.z = 1.0f;
}
reader.ReadPos((float *)&sv.pos);
}
}
//.........这里部分代码省略.........
示例9: SubmitSpline
void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, u32 prim_type, u32 vertex_type)
{
Flush();
if (prim_type != GE_PATCHPRIM_TRIANGLES) {
// Only triangles supported!
return;
}
// We're not actually going to decode, only reshuffle.
VertexDecoder vdecoder;
vdecoder.SetVertexType(vertex_type);
int undecodedVertexSize = vdecoder.VertexSize();
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
u8* indices8 = (u8*)indices;
u16* indices16 = (u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertex_type, &index_lower_bound, &index_upper_bound);
int num_patches_u = count_u - 3;
int num_patches_v = count_v - 3;
// TODO: Do something less idiotic to manage this buffer
HWSplinePatch* patches = new HWSplinePatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; ++patch_u) {
for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) {
HWSplinePatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
if (indices)
patch.points[point] = (u8 *)control_points + undecodedVertexSize * (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = (u8 *)control_points + undecodedVertexSize * idx;
}
patch.type = (type_u | (type_v<<2));
if (patch_u != 0) patch.type &= ~START_OPEN_U;
if (patch_v != 0) patch.type &= ~START_OPEN_V;
if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U;
if (patch_v != num_patches_v-1) patch.type &= ~END_OPEN_V;
}
}
u8 *decoded2 = decoded + 65536 * 24;
int count = 0;
u8 *dest = decoded2;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
HWSplinePatch& patch = patches[patch_idx];
// TODO: Should do actual patch subdivision instead of just drawing the control points!
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : 1;
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : 1;
const int tile_max_u = (patch.type & END_OPEN_U) ? 3 : 2;
const int tile_max_v = (patch.type & END_OPEN_V) ? 3 : 2;
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
int point_index = tile_u + tile_v*4;
u8 *v0 = patch.points[point_index];
u8 *v1 = patch.points[point_index+1];
u8 *v2 = patch.points[point_index+4];
u8 *v3 = patch.points[point_index+5];
// TODO: Insert UVs where applicable. Actually subdivide.
CopyTriangle(dest, v0, v1, v2, undecodedVertexSize);
CopyTriangle(dest, v2, v1, v0, undecodedVertexSize);
CopyTriangle(dest, v2, v1, v3, undecodedVertexSize);
CopyTriangle(dest, v3, v1, v2, undecodedVertexSize);
count += 12;
}
}
}
delete[] patches;
u32 vertTypeWithoutIndex = vertex_type & ~GE_VTYPE_IDX_MASK;
SubmitPrim(decoded2, 0, GE_PRIM_TRIANGLES, count, vertTypeWithoutIndex, GE_VTYPE_IDX_NONE, 0);
Flush();
}