Merge branch 'polyplay'

Conflicts:
	src/mame/drivers/namcos23.c
	src/mame/includes/hng64.h
	src/mame/video/hng64_3d.c
This commit is contained in:
Andrew Gardner 2015-10-06 14:05:48 +02:00
commit fb8f12ef50
9 changed files with 542 additions and 561 deletions

View File

@ -73,3 +73,4 @@ MAME source code should be viewed and edited with your editor set to use four sp
Some parts of the code follow [GNU style](http://www.gnu.org/prep/standards/html_node/Formatting.html); some parts of the code follow [K&R style](https://en.wikipedia.org/wiki/Indent_style#K.26R_style) -- mostly depending on who wrote the original version. **Above all else, be consistent with what you modify, and keep whitespace changes to a minimum when modifying existing source.** For new code, the majority tends to prefer GNU style, so if you don't care much, use that.
All contributors need to either add standard header for license info (on new files) or send us their wish under which of licenses they would like their code to be published under :[BSD-3-Clause](http://spdx.org/licenses/BSD-3-Clause), or for new files in mame/ or mess/, either the [BSD-3-Clause](http://spdx.org/licenses/BSD-3-Clause) license, the [LGPL-2.1+](http://spdx.org/licenses/LGPL-2.1+), or the [GPL-2.0+](http://spdx.org/licenses/GPL-2.0+).

View File

@ -1172,4 +1172,148 @@ int poly_manager<_BaseType, _ObjectData, _MaxParams, _MaxPolys>::zclip_if_less(i
return nextout - outv;
}
template<typename _BaseType, int _MaxParams>
struct frustum_clip_vertex
{
_BaseType x, y, z, w; // A 3d coordinate already transformed by a projection matrix
_BaseType p[_MaxParams]; // Additional parameters to clip
};
template<typename _BaseType, int _MaxParams>
int frustum_clip_w(const frustum_clip_vertex<_BaseType, _MaxParams>* v, int num_vertices, frustum_clip_vertex<_BaseType, _MaxParams>* out)
{
if (num_vertices <= 0)
return 0;
const _BaseType W_PLANE = 0.000001f;
frustum_clip_vertex<_BaseType, _MaxParams> clipv[10];
int clip_verts = 0;
int previ = num_vertices - 1;
for (int i=0; i < num_vertices; i++)
{
int v1_side = (v[i].w < W_PLANE) ? -1 : 1;
int v2_side = (v[previ].w < W_PLANE) ? -1 : 1;
if ((v1_side * v2_side) < 0) // edge goes through W plane
{
// insert vertex at intersection point
_BaseType wdiv = v[previ].w - v[i].w;
if (wdiv == 0.0f) // 0 edge means degenerate polygon
return 0;
_BaseType t = fabs((W_PLANE - v[previ].w) / wdiv);
clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t);
clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t);
clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t);
clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t);
// Interpolate the rest of the parameters
for (int pi = 0; pi < _MaxParams; pi++)
clipv[clip_verts].p[pi] = v[previ].p[pi] + ((v[i].p[pi] - v[previ].p[pi]) * t);
++clip_verts;
}
if (v1_side > 0) // current point is inside
{
clipv[clip_verts] = v[i];
++clip_verts;
}
previ = i;
}
memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts);
return clip_verts;
}
template<typename _BaseType, int _MaxParams>
int frustum_clip(const frustum_clip_vertex<_BaseType, _MaxParams>* v, int num_vertices, frustum_clip_vertex<_BaseType, _MaxParams>* out, int axis, int sign)
{
if (num_vertices <= 0)
return 0;
frustum_clip_vertex<_BaseType, _MaxParams> clipv[10];
int clip_verts = 0;
int previ = num_vertices - 1;
for (int i=0; i < num_vertices; i++)
{
int v1_side, v2_side;
_BaseType* v1a = (_BaseType*)&v[i];
_BaseType* v2a = (_BaseType*)&v[previ];
_BaseType v1_axis, v2_axis;
if (sign) // +axis
{
v1_axis = v1a[axis];
v2_axis = v2a[axis];
}
else // -axis
{
v1_axis = -v1a[axis];
v2_axis = -v2a[axis];
}
v1_side = (v1_axis <= v[i].w) ? 1 : -1;
v2_side = (v2_axis <= v[previ].w) ? 1 : -1;
if ((v1_side * v2_side) < 0) // edge goes through W plane
{
// insert vertex at intersection point
_BaseType wdiv = ((v[previ].w - v2_axis) - (v[i].w - v1_axis));
if (wdiv == 0.0f) // 0 edge means degenerate polygon
return 0;
_BaseType t = fabs((v[previ].w - v2_axis) / wdiv);
clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t);
clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t);
clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t);
clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t);
// Interpolate the rest of the parameters
for (int pi = 0; pi < _MaxParams; pi++)
clipv[clip_verts].p[pi] = v[previ].p[pi] + ((v[i].p[pi] - v[previ].p[pi]) * t);
++clip_verts;
}
if (v1_side > 0) // current point is inside
{
clipv[clip_verts] = v[i];
++clip_verts;
}
previ = i;
}
memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts);
return clip_verts;
}
template<typename _BaseType, int _MaxParams>
int frustum_clip_all(frustum_clip_vertex<_BaseType, _MaxParams>* clip_vert, int num_vertices, frustum_clip_vertex<_BaseType, _MaxParams>* out)
{
num_vertices = frustum_clip_w<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert);
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 0, 0); // W <= -X
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 0, 1); // W <= +X
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 1, 0); // W <= -Y
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 1, 1); // W <= +X
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 2, 0); // W <= -Z
num_vertices = frustum_clip<_BaseType, _MaxParams>(clip_vert, num_vertices, clip_vert, 2, 1); // W <= +Z
out = clip_vert;
return num_vertices;
}
#endif // __POLY_H__

View File

@ -2004,7 +2004,7 @@ ROM_START( buriki )
ROM_END
/* Bios */
GAME( 1997, hng64, 0, hng64, hng64, hng64_state, hng64, ROT0, "SNK", "Hyper NeoGeo 64 Bios", MACHINE_NOT_WORKING|MACHINE_NO_SOUND|MACHINE_IS_BIOS_ROOT )
GAME( 1997, hng64, 0, hng64, hng64, hng64_state, hng64, ROT0, "SNK", "Hyper NeoGeo 64 Bios", MACHINE_NOT_WORKING|MACHINE_NO_SOUND|MACHINE_IS_BIOS_ROOT )
/* Games */
GAME( 1997, roadedge, hng64, hng64, roadedge, hng64_state, hng64_race, ROT0, "SNK", "Roads Edge / Round Trip (rev.B)", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) /* 001 */

View File

@ -1291,17 +1291,18 @@ struct namcos23_render_data
class namcos23_state;
class namcos23_renderer : public poly_manager<float, namcos23_render_data, 4, POLY_MAX_ENTRIES>
class namcos23_renderer : public poly_manager<float, namcos23_render_data, 5, POLY_MAX_ENTRIES>
{
public:
namcos23_renderer(namcos23_state &state);
void render_flush(bitmap_rgb32& bitmap);
void render_scanline(INT32 scanline, const extent_t& extent, const namcos23_render_data& object, int threadid);
float* zBuffer() { return m_zBuffer; }
private:
namcos23_state& m_state;
bitmap_rgb32 m_bitmap;
float* m_zBuffer;
};
typedef namcos23_renderer::vertex_t poly_vertex;
@ -1309,7 +1310,6 @@ typedef namcos23_renderer::vertex_t poly_vertex;
struct namcos23_poly_entry
{
namcos23_render_data rd;
float zkey;
int front;
int vertex_count;
poly_vertex pv[16];
@ -1367,7 +1367,6 @@ struct render_t
int count[2];
namcos23_render_entry entries[2][RENDER_MAX_ENTRIES];
namcos23_poly_entry polys[POLY_MAX_ENTRIES];
namcos23_poly_entry *poly_order[POLY_MAX_ENTRIES];
};
class namcos23_state : public driver_device
@ -1584,10 +1583,13 @@ UINT16 namcos23_state::nthword(const UINT32 *pSource, int offs)
***************************************************************************/
namcos23_renderer::namcos23_renderer(namcos23_state &state)
: poly_manager<float, namcos23_render_data, 4, POLY_MAX_ENTRIES>(state.machine()),
m_state(state),
m_bitmap(state.m_screen->width(), state.m_screen->height())
{}
: poly_manager<float, namcos23_render_data, 5, POLY_MAX_ENTRIES>(state.machine()),
m_state(state),
m_bitmap(state.m_screen->width(), state.m_screen->height())
{
const INT32 bufferSize = state.m_screen->visible_area().width() * state.m_screen->visible_area().height();
m_zBuffer = auto_alloc_array(state.machine(), float, bufferSize);
}
// 3D hardware, to throw at least in part in video/namcos23.c
@ -1883,27 +1885,38 @@ void namcos23_renderer::render_scanline(INT32 scanline, const extent_t& extent,
{
const namcos23_render_data& rd = object;
float w = extent.param[0].start;
float u = extent.param[1].start;
float v = extent.param[2].start;
float l = extent.param[3].start;
float dw = extent.param[0].dpdx;
float du = extent.param[1].dpdx;
float dv = extent.param[2].dpdx;
float dl = extent.param[3].dpdx;
float zz = extent.param[0].start;
float w = extent.param[1].start;
float u = extent.param[2].start;
float v = extent.param[3].start;
float l = extent.param[4].start;
float dz = extent.param[0].dpdx;
float dw = extent.param[1].dpdx;
float du = extent.param[2].dpdx;
float dv = extent.param[3].dpdx;
float dl = extent.param[4].dpdx;
UINT32 *img = &m_bitmap.pix32(scanline, extent.startx);
float* zBuffer = &m_zBuffer[(scanline * m_state.m_screen->visible_area().width()) + extent.startx];
for(int x = extent.startx; x < extent.stopx; x++) {
float z = w ? 1/w : 0;
UINT32 pcol = rd.texture_lookup(*rd.machine, rd.pens, u*z, v*z);
float ll = l*z;
*img = (light(pcol >> 16, ll) << 16) | (light(pcol >> 8, ll) << 8) | light(pcol, ll);
if (zz < *zBuffer)
{
float z = w ? 1/w : 0;
UINT32 pcol = rd.texture_lookup(*rd.machine, rd.pens, u*z, v*z);
float ll = l*z;
*img = (light(pcol >> 16, ll) << 16) | (light(pcol >> 8, ll) << 8) | light(pcol, ll);
*zBuffer = zz;
}
zz += dz;
w += dw;
u += du;
v += dv;
l += dl;
img++;
zBuffer++;
}
}
@ -1928,10 +1941,9 @@ void namcos23_state::render_project(poly_vertex &pv)
// 640/(3.125/3.75) = 768
// 480/(2.34375/3.75) = 768
float w = pv.p[0] ? 1/pv.p[0] : 0;
pv.x = 320 + 768*w*pv.x;
pv.y = 240 - 768*w*pv.y;
pv.p[0] = w;
pv.x = 320 + 768 * pv.x;
pv.y = 240 - 768 * pv.y;
pv.p[1] = 1.0f / pv.p[1];
}
static UINT32 render_texture_lookup_nocache_point(running_machine &machine, const pen_t *pens, float x, float y)
@ -2034,22 +2046,71 @@ void namcos23_state::render_one_model(const namcos23_render_entry *re)
namcos23_poly_entry *p = render.polys + render.poly_count;
p->vertex_count = render.polymgr->zclip_if_less(ne, pv, p->pv, 4, 0.001f);
// Should be unnecessary now that frustum clipping happens, but this still culls polys behind the camera
p->vertex_count = render.polymgr->zclip_if_less(ne, pv, p->pv, 5, 0.001f);
// Project if you don't clip on the near plane
if(p->vertex_count >= 3) {
// Project the eye points
frustum_clip_vertex<float, 3> clipVerts[10];
for(int i=0; i<p->vertex_count; i++) {
render_project(p->pv[i]);
float w = p->pv[i].p[0];
p->pv[i].p[1] *= w;
p->pv[i].p[2] *= w;
p->pv[i].p[3] *= w;
// A basic perspective transform
const float Z = p->pv[i].p[0];
const float projX = p->pv[i].x / Z;
const float projY = p->pv[i].y / Z;
const float near = 0.001f;
const float far = 1000.0f;
const float m22 = -(far / (far-near));
const float m23 = -((far * near) / (far - near));
const float projZ = -(Z * m22) + m23;
// Construct a frustum clipping vert from the NDCoords
clipVerts[i].x = projX;
clipVerts[i].y = projY;
clipVerts[i].z = projZ;
clipVerts[i].w = p->pv[i].p[0];
clipVerts[i].p[0] = p->pv[i].p[1];
clipVerts[i].p[1] = p->pv[i].p[2];
clipVerts[i].p[2] = p->pv[i].p[3];
}
// Clip against all edges of the view frustum
int num_vertices = frustum_clip_all<float, 3>(clipVerts, p->vertex_count, clipVerts);
if (num_vertices != 0)
{
// Push the results back into the main vertices
for (int i=0; i < num_vertices; i++)
{
p->pv[i].x = clipVerts[i].x;
p->pv[i].y = clipVerts[i].y;
p->pv[i].p[0] = clipVerts[i].z;
p->pv[i].p[1] = clipVerts[i].w;
p->pv[i].p[2] = clipVerts[i].p[0];
p->pv[i].p[3] = clipVerts[i].p[1];
p->pv[i].p[4] = clipVerts[i].p[2];
}
p->vertex_count = num_vertices;
// This is our poor-man's projection matrix
for(int i=0; i<p->vertex_count; i++)
{
render_project(p->pv[i]);
const float w = p->pv[i].p[1];
p->pv[i].p[2] *= w;
p->pv[i].p[3] *= w;
p->pv[i].p[4] *= w;
}
// Compute an odd sorta'-Z thing that can situate the polygon wherever you want in Z-depth
p->front = !(h & 0x00000001);
p->rd.machine = &machine();
p->rd.texture_lookup = render_texture_lookup_nocache_point;
p->rd.pens = m_palette->pens() + (color << 8);
render.poly_count++;
}
p->zkey = 0.5f*(minz+maxz);
p->front = !(h & 0x00000001);
p->rd.machine = &machine();
p->rd.texture_lookup = render_texture_lookup_nocache_point;
p->rd.pens = m_palette->pens() + (color << 8);
render.poly_count++;
}
if(type & 0x000010000)
@ -2057,17 +2118,6 @@ void namcos23_state::render_one_model(const namcos23_render_entry *re)
}
}
static int render_poly_compare(const void *i1, const void *i2)
{
const namcos23_poly_entry *p1 = *(const namcos23_poly_entry **)i1;
const namcos23_poly_entry *p2 = *(const namcos23_poly_entry **)i2;
if(p1->front != p2->front)
return p1->front ? 1 : -1;
return p1->zkey < p2->zkey ? 1 : p1->zkey > p2->zkey ? -1 : 0;
}
void namcos23_renderer::render_flush(bitmap_rgb32& bitmap)
{
render_t &render = m_state.m_render;
@ -2075,28 +2125,32 @@ void namcos23_renderer::render_flush(bitmap_rgb32& bitmap)
if(!render.poly_count)
return;
for(int i=0; i<render.poly_count; i++)
render.poly_order[i] = &render.polys[i];
qsort(render.poly_order, render.poly_count, sizeof(namcos23_poly_entry *), render_poly_compare);
const static rectangle scissor(0, 639, 0, 479);
for(int i=0; i<render.poly_count; i++) {
const namcos23_poly_entry *p = render.poly_order[i];
const namcos23_poly_entry *p = &render.polys[i];
namcos23_render_data& extra = render.polymgr->object_data_alloc();
extra = p->rd;
// We should probably split the polygons into triangles ourselves to insure everything is being rendered properly
if (p->vertex_count == 3)
render_triangle(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 4, p->pv[0], p->pv[1], p->pv[2]);
render_triangle(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 5, p->pv[0], p->pv[1], p->pv[2]);
else if (p->vertex_count == 4)
render_polygon<4>(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 4, p->pv);
render_polygon<4>(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 5, p->pv);
else if (p->vertex_count == 5)
render_polygon<5>(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 4, p->pv);
render_polygon<5>(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 5, p->pv);
else if (p->vertex_count == 6)
render_polygon<6>(scissor, render_delegate(FUNC(namcos23_renderer::render_scanline), this), 5, p->pv);
}
render.poly_count = 0;
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, scissor);
// Reset the buffers
for (int i = 0; i < (m_state.m_screen->visible_area().width())*(m_state.m_screen->visible_area().height()); i++)
{
m_zBuffer[i] = 1000.0f; // TODO: set to far clipping plane value
}
}
void namcos23_state::render_run(bitmap_rgb32 &bitmap)

View File

@ -24,7 +24,7 @@ enum hng64trans_t
struct blit_parameters
{
bitmap_rgb32 * bitmap;
bitmap_rgb32 * bitmap;
rectangle cliprect;
UINT32 tilemap_priority_code;
UINT8 mask;
@ -55,7 +55,7 @@ struct polyVert
struct polygon
{
int n; // Number of sides
struct polyVert vert[10]; // Vertices (maximum number per polygon is 10 -> 3+6)
polyVert vert[10]; // Vertices (maximum number per polygon is 10 -> 3+6)
float faceNormal[4]; // Normal of the face overall - for calculating visibility and flat-shading...
int visible; // Polygon visibility in scene
@ -92,6 +92,8 @@ struct polygon
const int HNG64_MAX_POLYGONS = 10000;
typedef frustum_clip_vertex<float, 5> hng64_clip_vertex;
struct hng64_poly_data
{
UINT8 texType;
@ -109,15 +111,15 @@ class hng64_state;
class hng64_poly_renderer : public poly_manager<float, hng64_poly_data, 7, HNG64_MAX_POLYGONS>
{
public:
hng64_poly_renderer(hng64_state& state);
void drawShaded(struct polygon *p);
void render_scanline(INT32 scanline, const extent_t& extent, const hng64_poly_data& renderData, int threadid);
hng64_state& state() { return m_state; }
bitmap_rgb32& colorBuffer3d() { return m_colorBuffer3d; }
float* depthBuffer3d() { return m_depthBuffer3d; }
hng64_poly_renderer(hng64_state& state);
void drawShaded(polygon *p);
void render_scanline(INT32 scanline, const extent_t& extent, const hng64_poly_data& renderData, int threadid);
hng64_state& state() { return m_state; }
bitmap_rgb32& colorBuffer3d() { return m_colorBuffer3d; }
float* depthBuffer3d() { return m_depthBuffer3d; }
private:
hng64_state& m_state;
@ -127,7 +129,6 @@ private:
};
class hng64_state : public driver_device
{
public:
@ -173,9 +174,11 @@ public:
required_shared_ptr<UINT32> m_videoregs;
required_shared_ptr<UINT32> m_tcram;
<<<<<<< HEAD
/* 3D stuff */
=======
>>>>>>> polyplay
UINT16* m_dl;
required_shared_ptr<UINT32> m_3dregs;
required_shared_ptr<UINT32> m_3d_1;
required_shared_ptr<UINT32> m_3d_2;
@ -193,8 +196,8 @@ public:
UINT16 *m_soundram2;
/* Communications stuff */
UINT8 *m_com_op_base;
UINT8 *m_com_virtual_mem;
UINT8 *m_com_op_base;
UINT8 *m_com_virtual_mem;
UINT8 m_com_shared[8];
INT32 m_dma_start;
@ -319,32 +322,14 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER(hng64_irq);
void do_dma(address_space &space);
DECLARE_CUSTOM_INPUT_MEMBER(left_handle_r);
DECLARE_CUSTOM_INPUT_MEMBER(right_handle_r);
DECLARE_CUSTOM_INPUT_MEMBER(acc_down_r);
DECLARE_CUSTOM_INPUT_MEMBER(brake_down_r);
hng64_poly_renderer* m_poly_renderer;
void clear3d();
TIMER_CALLBACK_MEMBER(hng64_3dfifo_processed);
void hng64_command3d(const UINT16* packet);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void transition_control(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void hng64_tilemap_draw_roz_core(screen_device &screen, tilemap_t *tmap, const blit_parameters *blit,
UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy, int wraparound);
void hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int tm);
void setCameraTransformation(const UINT16* packet);
void setLighting(const UINT16* packet);
void set3dFlags(const UINT16* packet);
void setCameraProjectionMatrix(const UINT16* packet);
void recoverPolygonBlock(const UINT16* packet, int* numPolys);
void hng64_mark_all_tiles_dirty(int tilemap);
void hng64_mark_all_tiles_dirty(int tilemap);
void hng64_mark_tile_dirty(int tilemap, int tile_index);
void hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int tm);
void hng64_tilemap_draw_roz(screen_device &screen, bitmap_rgb32 &dest, const rectangle &cliprect, tilemap_t *tmap,
void hng64_tilemap_draw_roz_core(screen_device &screen, tilemap_t *tmap, const blit_parameters *blit,
UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy, int wraparound);
void hng64_tilemap_draw_roz(screen_device &screen, bitmap_rgb32 &dest, const rectangle &cliprect, tilemap_t *tmap,
UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy,
int wraparound, UINT32 flags, UINT8 priority, hng64trans_t drawformat);
@ -352,19 +337,46 @@ public:
UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy,
int wraparound, UINT32 flags, UINT8 priority, UINT8 priority_mask, hng64trans_t drawformat);
DECLARE_CUSTOM_INPUT_MEMBER(left_handle_r);
DECLARE_CUSTOM_INPUT_MEMBER(right_handle_r);
DECLARE_CUSTOM_INPUT_MEMBER(acc_down_r);
DECLARE_CUSTOM_INPUT_MEMBER(brake_down_r);
<<<<<<< HEAD
hng64_poly_renderer* m_poly_renderer;
void clear3d();
TIMER_CALLBACK_MEMBER(hng64_3dfifo_processed);
=======
hng64_poly_renderer* m_poly_renderer;
TIMER_CALLBACK_MEMBER(hng64_3dfifo_processed);
>>>>>>> polyplay
UINT8 *m_texturerom;
UINT16* m_vertsrom;
int m_vertsrom_size;
std::vector<polygon> m_polys; // HNG64_MAX_POLYGONS
void clear3d();
void hng64_command3d(const UINT16* packet);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void transition_control(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void setCameraTransformation(const UINT16* packet);
void setLighting(const UINT16* packet);
void set3dFlags(const UINT16* packet);
void setCameraProjectionMatrix(const UINT16* packet);
void recoverPolygonBlock(const UINT16* packet, int& numPolys);
void printPacket(const UINT16* packet, int hex);
float uToF(UINT16 input);
void matmul4(float *product, const float *a, const float *b);
void vecmatmul4(float *product, const float *a, const float *b);
float vecDotProduct(const float *a, const float *b);
void setIdentity(float *matrix);
float uToF(UINT16 input);
void normalize(float* x);
int Inside(struct polyVert *v, int plane);
void Intersect(struct polyVert *input0, struct polyVert *input1, struct polyVert *output, int plane);
void performFrustumClip(struct polygon *p);
UINT8 *m_texturerom;
UINT16* m_vertsrom;
int m_vertsrom_size;
void reset_sound();
void reset_net();
@ -397,7 +409,6 @@ public:
DECLARE_WRITE16_MEMBER(main_sound_comms_w);
DECLARE_READ16_MEMBER(sound_comms_r);
DECLARE_WRITE16_MEMBER(sound_comms_w);
UINT16 main_latch[2],sound_latch[2];
std::vector<polygon> polys;//(1024*5);
UINT16 main_latch[2];
UINT16 sound_latch[2];
};

View File

@ -34,17 +34,7 @@ struct m3_vertex
float nz;
};
struct m3_clip_vertex
{
float x;
float y;
float z;
float w;
float u;
float v;
float i;
float s;
};
typedef frustum_clip_vertex<float, 4> m3_clip_vertex;
struct m3_triangle
{

View File

@ -1317,7 +1317,7 @@ void hng64_state::video_start()
// 3d information
m_dl = auto_alloc_array(machine(), UINT16, 0x200/2);
polys.resize(1024*5);
m_polys.resize(HNG64_MAX_POLYGONS);
m_texturerom = memregion("textures")->base();
m_vertsrom = (UINT16*)memregion("verts")->base();

View File

@ -56,7 +56,7 @@ WRITE16_MEMBER(hng64_state::dl_w)
/* TODO: different param for both Samurai games, less FIFO to process? */
// TODO: different param for both Samurai games, less FIFO to process?
WRITE32_MEMBER(hng64_state::dl_upload_w)
{
// this is written after the game uploads 16 packets, each 32 bytes long (2x 16 words?)
@ -80,7 +80,7 @@ TIMER_CALLBACK_MEMBER(hng64_state::hng64_3dfifo_processed)
}
/* Note: Samurai Shodown games never calls bit 1, so it can't be framebuffer clear. It also calls bit 3 at start-up, meaning unknown */
// Note: Samurai Shodown games never calls bit 1, so it can't be framebuffer clear. It also calls bit 3 at start-up, meaning unknown
WRITE32_MEMBER(hng64_state::dl_control_w) // This handles framebuffers
{
// printf("dl_control_w %08x %08x\n", data, mem_mask);
@ -251,12 +251,12 @@ void hng64_state::setCameraProjectionMatrix(const UINT16* packet)
// [1] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset.
// [2] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset.
// [3] - ???? ... ? Contains a value
// [4] - xxxx ... Camera projection near scale
// [5] - xxxx ... Camera projection near height(?)
// [6] - xxxx ... Camera projection near width(?)
// [7] - xxxx ... Camera projection far scale
// [8] - xxxx ... Camera projection far height(?)
// [9] - xxxx ... Camera projection far width(?)
// [4] - xxxx ... Camera projection near (?)
// [5] - xxxx ... Camera projection near (?)
// [6] - xxxx ... Camera projection near (?)
// [7] - xxxx ... Camera projection far (?)
// [8] - xxxx ... Camera projection far (?)
// [9] - xxxx ... Camera projection far (?)
// [10] - xxxx ... Camera projection right
// [11] - xxxx ... Camera projection left
// [12] - xxxx ... Camera projection top
@ -272,9 +272,10 @@ void hng64_state::setCameraProjectionMatrix(const UINT16* packet)
right = uToF(packet[10]);
top = uToF(packet[12]);
bottom = uToF(packet[13]);
near_ = uToF(packet[6]) + (uToF(packet[6]) * uToF(packet[4]));
far_ = uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7]));
// (note are likely not 100% correct - I'm not using one of the parameters)
// Note: The near and far clipping planes are totally guesses.
near_ = uToF(packet[6]); // + (uToF(packet[6]) * uToF(packet[4]));
far_ = 0.9f; // uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7]));
projectionMatrix[0] = (2.0f*near_)/(right-left);
projectionMatrix[1] = 0.0f;
@ -299,7 +300,7 @@ void hng64_state::setCameraProjectionMatrix(const UINT16* packet)
// Operation 0100
// Polygon rasterization.
void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
{
/*//////////////
// PACKET FORMAT
@ -367,12 +368,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
UINT32 size[4];
UINT32 address[4];
UINT32 megaOffset;
float eyeCoords[4]; // ObjectCoords transformed by the modelViewMatrix
// float clipCoords[4]; // EyeCoords transformed by the projectionMatrix
float ndCoords[4]; // Normalized device coordinates/clipCoordinates (x/w, y/w, z/w)
float windowCoords[4]; // Mapped ndCoordinates to screen space
float cullRay[4];
struct polygon lastPoly = { 0 };
polygon lastPoly = { 0 };
const rectangle &visarea = m_screen->visible_area();
@ -442,11 +438,10 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
size[2] = threeDPointer[9];
size[3] = threeDPointer[10];
/* ???? [11]; Used. */
/* ???? [12]; Used. */
/* ???? [13]; Used. */
/* ???? [14]; Used. */
// ???? [11]; Used.
// ???? [12]; Used.
// ???? [13]; Used.
// ???? [14]; Used.
if (threeDPointer[15] != 0x0000) printf("ZOMG! 3dPointer[15] is non-zero!\n");
if (threeDPointer[16] != 0x0000) printf("ZOMG! 3dPointer[16] is non-zero!\n");
@ -456,7 +451,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
if (threeDPointer[19] != 0x0000) printf("ZOMG! 3dPointer[19] is non-zero!\n");
if (threeDPointer[20] != 0x0000) printf("ZOMG! 3dPointer[20] is non-zero!\n");
/* Concatenate the megaOffset with the addresses */
// Concatenate the megaOffset with the addresses
address[0] |= (megaOffset << 16);
address[1] |= (megaOffset << 16);
address[2] |= (megaOffset << 16);
@ -468,7 +463,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
//if (threeDPointer[14] & 0x0001) tdColor |= 0x0000ff00;
//if (threeDPointer[14] & 0x0000) tdColor |= 0x000000ff;
/* For all 4 polygon chunks */
// For all 4 polygon chunks
for (int k = 0; k < 4; k++)
{
UINT16* chunkOffset = &threeDRoms[address[k] * 3];
@ -502,37 +497,40 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
continue;
}
// Syntactical simplification
polygon& currentPoly = m_polys[numPolys];
// Debug - Colors polygons with certain flags bright blue! ajg
polys[*numPolys].debugColor = 0;
//polys[*numPolys].debugColor = tdColor;
currentPoly.debugColor = 0;
//currentPoly.debugColor = tdColor;
// Debug - ajg
//printf("%d (%08x) : %04x %04x %04x\n", k, address[k]*3*2, chunkOffset[0], chunkOffset[1], chunkOffset[2]);
//break;
// TEXTURE
/* There may be more than just high & low res texture types, so I'm keeping texType as a UINT8. */
if (chunkOffset[1] & 0x1000) polys[*numPolys].texType = 0x1;
else polys[*numPolys].texType = 0x0;
// There may be more than just high & low res texture types, so I'm keeping texType as a UINT8. */
if (chunkOffset[1] & 0x1000) currentPoly.texType = 0x1;
else currentPoly.texType = 0x0;
polys[*numPolys].texPageSmall = (chunkOffset[2] & 0xc000)>>14; // Just a guess.
polys[*numPolys].texPageHorizOffset = (chunkOffset[2] & 0x3800) >> 11;
polys[*numPolys].texPageVertOffset = (chunkOffset[2] & 0x0070) >> 4;
currentPoly.texPageSmall = (chunkOffset[2] & 0xc000)>>14; // Just a guess.
currentPoly.texPageHorizOffset = (chunkOffset[2] & 0x3800) >> 11;
currentPoly.texPageVertOffset = (chunkOffset[2] & 0x0070) >> 4;
polys[*numPolys].texIndex = chunkOffset[1] & 0x000f;
currentPoly.texIndex = chunkOffset[1] & 0x000f;
// PALETTE
polys[*numPolys].palOffset = 0;
polys[*numPolys].palPageSize = 0x100;
currentPoly.palOffset = 0;
currentPoly.palPageSize = 0x100;
/* FIXME: This isn't correct.
Buriki & Xrally need this line. Roads Edge needs it removed.
So instead we're looking for a bit that is on for XRally & Buriki, but noone else. */
// FIXME: This isn't correct.
// Buriki & Xrally need this line. Roads Edge needs it removed.
// So instead we're looking for a bit that is on for XRally & Buriki, but noone else.
if (m_3dregs[0x00/4] & 0x2000)
{
if (strcmp(machine().basename(), "roadedge"))
polys[*numPolys].palOffset += 0x800;
currentPoly.palOffset += 0x800;
}
//UINT16 explicitPaletteValue0 = ((chunkOffset[?] & 0x????) >> ?) * 0x800;
@ -540,7 +538,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
UINT16 explicitPaletteValue2 = ((chunkOffset[1] & 0x00f0) >> 4) * 0x008;
// The presence of 0x00f0 *probably* sets 0x10-sized palette addressing.
if (explicitPaletteValue2) polys[*numPolys].palPageSize = 0x10;
if (explicitPaletteValue2) currentPoly.palPageSize = 0x10;
// Apply the dynamic palette offset if its flag is set, otherwise stick with the fixed one
if ((packet[1] & 0x0100))
@ -549,7 +547,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
explicitPaletteValue2 = 0; // This is probably hiding somewhere in operation 0011
}
polys[*numPolys].palOffset += (explicitPaletteValue1 + explicitPaletteValue2);
currentPoly.palOffset += (explicitPaletteValue1 + explicitPaletteValue2);
#if 0
@ -557,7 +555,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
{
// if (chunkOffset[2] == 0xd870)
{
polys[*numPolys].debugColor = 0xffff0000;
currentPoly.debugColor = 0xffff0000;
printf("%d (%08x) : %04x %04x %04x\n", k, address[k] * 3 * 2, chunkOffset[0], chunkOffset[1], chunkOffset[2]);
}
}
@ -583,29 +581,29 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
case 0x0f: // 0000 1111
for (int m = 0; m < 3; m++)
{
polys[*numPolys].vert[m].worldCoords[0] = uToF(chunkOffset[3 + (9*m)]);
polys[*numPolys].vert[m].worldCoords[1] = uToF(chunkOffset[4 + (9*m)]);
polys[*numPolys].vert[m].worldCoords[2] = uToF(chunkOffset[5 + (9*m)]);
polys[*numPolys].vert[m].worldCoords[3] = 1.0f;
polys[*numPolys].n = 3;
currentPoly.vert[m].worldCoords[0] = uToF(chunkOffset[3 + (9*m)]);
currentPoly.vert[m].worldCoords[1] = uToF(chunkOffset[4 + (9*m)]);
currentPoly.vert[m].worldCoords[2] = uToF(chunkOffset[5 + (9*m)]);
currentPoly.vert[m].worldCoords[3] = 1.0f;
currentPoly.n = 3;
// chunkOffset[6 + (9*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
polys[*numPolys].vert[m].texCoords[0] = uToF(chunkOffset[7 + (9*m)]);
polys[*numPolys].vert[m].texCoords[1] = uToF(chunkOffset[8 + (9*m)]);
polys[*numPolys].vert[m].texCoords[2] = 0.0f;
polys[*numPolys].vert[m].texCoords[3] = 1.0f;
currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (9*m)]);
currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (9*m)]);
currentPoly.vert[m].texCoords[2] = 0.0f;
currentPoly.vert[m].texCoords[3] = 1.0f;
polys[*numPolys].vert[m].normal[0] = uToF(chunkOffset[9 + (9*m)]);
polys[*numPolys].vert[m].normal[1] = uToF(chunkOffset[10 + (9*m)]);
polys[*numPolys].vert[m].normal[2] = uToF(chunkOffset[11 + (9*m)]);
polys[*numPolys].vert[m].normal[3] = 0.0f;
currentPoly.vert[m].normal[0] = uToF(chunkOffset[9 + (9*m)]);
currentPoly.vert[m].normal[1] = uToF(chunkOffset[10 + (9*m)]);
currentPoly.vert[m].normal[2] = uToF(chunkOffset[11 + (9*m)]);
currentPoly.vert[m].normal[3] = 0.0f;
}
// Redundantly called, but it works...
polys[*numPolys].faceNormal[0] = uToF(chunkOffset[30]);
polys[*numPolys].faceNormal[1] = uToF(chunkOffset[31]);
polys[*numPolys].faceNormal[2] = uToF(chunkOffset[32]);
polys[*numPolys].faceNormal[3] = 0.0f;
currentPoly.faceNormal[0] = uToF(chunkOffset[30]);
currentPoly.faceNormal[1] = uToF(chunkOffset[31]);
currentPoly.faceNormal[2] = uToF(chunkOffset[32]);
currentPoly.faceNormal[3] = 0.0f;
chunkLength = 33;
break;
@ -618,29 +616,29 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
case 0x2e: // 0010 1110
for (int m = 0; m < 3; m++)
{
polys[*numPolys].vert[m].worldCoords[0] = uToF(chunkOffset[3 + (6*m)]);
polys[*numPolys].vert[m].worldCoords[1] = uToF(chunkOffset[4 + (6*m)]);
polys[*numPolys].vert[m].worldCoords[2] = uToF(chunkOffset[5 + (6*m)]);
polys[*numPolys].vert[m].worldCoords[3] = 1.0f;
polys[*numPolys].n = 3;
currentPoly.vert[m].worldCoords[0] = uToF(chunkOffset[3 + (6*m)]);
currentPoly.vert[m].worldCoords[1] = uToF(chunkOffset[4 + (6*m)]);
currentPoly.vert[m].worldCoords[2] = uToF(chunkOffset[5 + (6*m)]);
currentPoly.vert[m].worldCoords[3] = 1.0f;
currentPoly.n = 3;
// chunkOffset[6 + (6*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
polys[*numPolys].vert[m].texCoords[0] = uToF(chunkOffset[7 + (6*m)]);
polys[*numPolys].vert[m].texCoords[1] = uToF(chunkOffset[8 + (6*m)]);
polys[*numPolys].vert[m].texCoords[2] = 0.0f;
polys[*numPolys].vert[m].texCoords[3] = 1.0f;
currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (6*m)]);
currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (6*m)]);
currentPoly.vert[m].texCoords[2] = 0.0f;
currentPoly.vert[m].texCoords[3] = 1.0f;
polys[*numPolys].vert[m].normal[0] = uToF(chunkOffset[21]);
polys[*numPolys].vert[m].normal[1] = uToF(chunkOffset[22]);
polys[*numPolys].vert[m].normal[2] = uToF(chunkOffset[23]);
polys[*numPolys].vert[m].normal[3] = 0.0f;
currentPoly.vert[m].normal[0] = uToF(chunkOffset[21]);
currentPoly.vert[m].normal[1] = uToF(chunkOffset[22]);
currentPoly.vert[m].normal[2] = uToF(chunkOffset[23]);
currentPoly.vert[m].normal[3] = 0.0f;
}
// Redundantly called, but it works...
polys[*numPolys].faceNormal[0] = polys[*numPolys].vert[2].normal[0];
polys[*numPolys].faceNormal[1] = polys[*numPolys].vert[2].normal[1];
polys[*numPolys].faceNormal[2] = polys[*numPolys].vert[2].normal[2];
polys[*numPolys].faceNormal[3] = 0.0f;
currentPoly.faceNormal[0] = currentPoly.vert[2].normal[0];
currentPoly.faceNormal[1] = currentPoly.vert[2].normal[1];
currentPoly.faceNormal[2] = currentPoly.vert[2].normal[2];
currentPoly.faceNormal[3] = 0.0f;
chunkLength = 24;
break;
@ -652,31 +650,31 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
case 0xd7: // 1101 0111
case 0xc7: // 1100 0111
// Copy over the proper vertices from the previous triangle...
memcpy(&polys[*numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert));
memcpy(&polys[*numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert));
memcpy(&currentPoly.vert[1], &lastPoly.vert[0], sizeof(polyVert));
memcpy(&currentPoly.vert[2], &lastPoly.vert[2], sizeof(polyVert));
// Fill in the appropriate data...
polys[*numPolys].vert[0].worldCoords[0] = uToF(chunkOffset[3]);
polys[*numPolys].vert[0].worldCoords[1] = uToF(chunkOffset[4]);
polys[*numPolys].vert[0].worldCoords[2] = uToF(chunkOffset[5]);
polys[*numPolys].vert[0].worldCoords[3] = 1.0f;
polys[*numPolys].n = 3;
currentPoly.vert[0].worldCoords[0] = uToF(chunkOffset[3]);
currentPoly.vert[0].worldCoords[1] = uToF(chunkOffset[4]);
currentPoly.vert[0].worldCoords[2] = uToF(chunkOffset[5]);
currentPoly.vert[0].worldCoords[3] = 1.0f;
currentPoly.n = 3;
// chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
polys[*numPolys].vert[0].texCoords[0] = uToF(chunkOffset[7]);
polys[*numPolys].vert[0].texCoords[1] = uToF(chunkOffset[8]);
polys[*numPolys].vert[0].texCoords[2] = 0.0f;
polys[*numPolys].vert[0].texCoords[3] = 1.0f;
currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]);
currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]);
currentPoly.vert[0].texCoords[2] = 0.0f;
currentPoly.vert[0].texCoords[3] = 1.0f;
polys[*numPolys].vert[0].normal[0] = uToF(chunkOffset[9]);
polys[*numPolys].vert[0].normal[1] = uToF(chunkOffset[10]);
polys[*numPolys].vert[0].normal[2] = uToF(chunkOffset[11]);
polys[*numPolys].vert[0].normal[3] = 0.0f;
currentPoly.vert[0].normal[0] = uToF(chunkOffset[9]);
currentPoly.vert[0].normal[1] = uToF(chunkOffset[10]);
currentPoly.vert[0].normal[2] = uToF(chunkOffset[11]);
currentPoly.vert[0].normal[3] = 0.0f;
polys[*numPolys].faceNormal[0] = uToF(chunkOffset[12]);
polys[*numPolys].faceNormal[1] = uToF(chunkOffset[13]);
polys[*numPolys].faceNormal[2] = uToF(chunkOffset[14]);
polys[*numPolys].faceNormal[3] = 0.0f;
currentPoly.faceNormal[0] = uToF(chunkOffset[12]);
currentPoly.faceNormal[1] = uToF(chunkOffset[13]);
currentPoly.faceNormal[2] = uToF(chunkOffset[14]);
currentPoly.faceNormal[3] = 0.0f;
chunkLength = 15;
break;
@ -689,33 +687,33 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
case 0xc6: // 1100 0110
case 0xd6: // 1101 0110
// Copy over the proper vertices from the previous triangle...
memcpy(&polys[*numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert));
memcpy(&polys[*numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert));
memcpy(&currentPoly.vert[1], &lastPoly.vert[0], sizeof(polyVert));
memcpy(&currentPoly.vert[2], &lastPoly.vert[2], sizeof(polyVert));
polys[*numPolys].vert[0].worldCoords[0] = uToF(chunkOffset[3]);
polys[*numPolys].vert[0].worldCoords[1] = uToF(chunkOffset[4]);
polys[*numPolys].vert[0].worldCoords[2] = uToF(chunkOffset[5]);
polys[*numPolys].vert[0].worldCoords[3] = 1.0f;
polys[*numPolys].n = 3;
currentPoly.vert[0].worldCoords[0] = uToF(chunkOffset[3]);
currentPoly.vert[0].worldCoords[1] = uToF(chunkOffset[4]);
currentPoly.vert[0].worldCoords[2] = uToF(chunkOffset[5]);
currentPoly.vert[0].worldCoords[3] = 1.0f;
currentPoly.n = 3;
// chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
polys[*numPolys].vert[0].texCoords[0] = uToF(chunkOffset[7]);
polys[*numPolys].vert[0].texCoords[1] = uToF(chunkOffset[8]);
polys[*numPolys].vert[0].texCoords[2] = 0.0f;
polys[*numPolys].vert[0].texCoords[3] = 1.0f;
currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]);
currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]);
currentPoly.vert[0].texCoords[2] = 0.0f;
currentPoly.vert[0].texCoords[3] = 1.0f;
// This normal could be right, but I'm not entirely sure - there is no normal in the 18 bytes!
polys[*numPolys].vert[0].normal[0] = lastPoly.faceNormal[0];
polys[*numPolys].vert[0].normal[1] = lastPoly.faceNormal[1];
polys[*numPolys].vert[0].normal[2] = lastPoly.faceNormal[2];
polys[*numPolys].vert[0].normal[3] = lastPoly.faceNormal[3];
currentPoly.vert[0].normal[0] = lastPoly.faceNormal[0];
currentPoly.vert[0].normal[1] = lastPoly.faceNormal[1];
currentPoly.vert[0].normal[2] = lastPoly.faceNormal[2];
currentPoly.vert[0].normal[3] = lastPoly.faceNormal[3];
polys[*numPolys].faceNormal[0] = lastPoly.faceNormal[0];
polys[*numPolys].faceNormal[1] = lastPoly.faceNormal[1];
polys[*numPolys].faceNormal[2] = lastPoly.faceNormal[2];
polys[*numPolys].faceNormal[3] = lastPoly.faceNormal[3];
currentPoly.faceNormal[0] = lastPoly.faceNormal[0];
currentPoly.faceNormal[1] = lastPoly.faceNormal[1];
currentPoly.faceNormal[2] = lastPoly.faceNormal[2];
currentPoly.faceNormal[3] = lastPoly.faceNormal[3];
// TODO: I'm not reading 3 necessary words here (maybe face normal) !!!
// TODO: I'm not reading 3 necessary words here (maybe face normal)
#if 0
// DEBUG
@ -738,17 +736,18 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
break;
}
polys[*numPolys].visible = 1;
currentPoly.visible = 1;
// Backup the last polygon (for triangle fans [strips?])
memcpy(&lastPoly, &polys[*numPolys], sizeof(struct polygon));
memcpy(&lastPoly, &currentPoly, sizeof(polygon));
////////////////////////////////////
// Project and clip //
////////////////////////////////////
// Perform the world transformations...
// !! Can eliminate this step with a matrix stack (maybe necessary?) !!
// TODO: We can eliminate this step with a matrix stack (maybe necessary?)
// Note: fatfurwa's helicopter tracking in scene 3 of its intro shows one of these matrices isn't quite correct
setIdentity(m_modelViewMatrix);
if (m_mcu_type != SAMSHO_MCU)
{
@ -767,7 +766,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
for (int v = 0; v < 3; v++)
{
float transformedNormal[4];
vecmatmul4(transformedNormal, objectMatrix, polys[*numPolys].vert[v].normal);
vecmatmul4(transformedNormal, objectMatrix, currentPoly.vert[v].normal);
normalize(transformedNormal);
normalize(m_lightVector);
@ -777,9 +776,9 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
intensity *= 128.0; // Maps intensity to the range [0.0, 2.0]
if (intensity >= 255.0f) intensity = 255.0f;
polys[*numPolys].vert[v].light[0] = intensity;
polys[*numPolys].vert[v].light[1] = intensity;
polys[*numPolys].vert[v].light[2] = intensity;
currentPoly.vert[v].light[0] = intensity;
currentPoly.vert[v].light[1] = intensity;
currentPoly.vert[v].light[2] = intensity;
}
}
else
@ -787,77 +786,109 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
// Just clear out the light values
for (int v = 0; v < 3; v++)
{
polys[*numPolys].vert[v].light[0] = 0;
polys[*numPolys].vert[v].light[1] = 0;
polys[*numPolys].vert[v].light[2] = 0;
currentPoly.vert[v].light[0] = 0;
currentPoly.vert[v].light[1] = 0;
currentPoly.vert[v].light[2] = 0;
}
}
// BACKFACE CULL //
// EMPIRICAL EVIDENCE SEEMS TO SHOW THE HNG64 HARDWARE DOES NOT BACKFACE CULL //
// (empirical evidence seems to show the hng64 hardware does not backface cull) //
#if 0
float cullRay[4];
float cullNorm[4];
// Cast a ray out of the camera towards the polygon's point in eyespace.
vecmatmul4(cullRay, modelViewMatrix, polys[*numPolys].vert[0].worldCoords);
vecmatmul4(cullRay, modelViewMatrix, currentPoly.vert[0].worldCoords);
normalize(cullRay);
// Dot product that with the normal to see if you're negative...
vecmatmul4(cullNorm, modelViewMatrix, polys[*numPolys].faceNormal);
float result = vecDotProduct(cullRay, cullNorm);
if (result < 0.0f)
polys[*numPolys].visible = 1;
vecmatmul4(cullNorm, modelViewMatrix, currentPoly.faceNormal);
const float backfaceCullResult = vecDotProduct(cullRay, cullNorm);
if (backfaceCullResult < 0.0f)
currentPoly.visible = 1;
else
polys[*numPolys].visible = 0;
currentPoly.visible = 0;
#endif
// BEHIND-THE-CAMERA CULL //
vecmatmul4(cullRay, m_modelViewMatrix, polys[*numPolys].vert[0].worldCoords);
float cullRay[4];
vecmatmul4(cullRay, m_modelViewMatrix, currentPoly.vert[0].worldCoords);
if (cullRay[2] > 0.0f) // Camera is pointing down -Z
{
polys[*numPolys].visible = 0;
currentPoly.visible = 0;
}
// TRANSFORM THE TRIANGLE INTO HOMOGENEOUS SCREEN SPACE //
if (polys[*numPolys].visible)
if (currentPoly.visible)
{
for (int m = 0; m < polys[*numPolys].n; m++)
hng64_clip_vertex clipVerts[10];
// Transform and project each vertex into pre-divided homogeneous coordinates
for (int m = 0; m < currentPoly.n; m++)
{
// Transform and project the vertex into pre-divided homogeneous coordinates...
vecmatmul4(eyeCoords, m_modelViewMatrix, polys[*numPolys].vert[m].worldCoords);
vecmatmul4(polys[*numPolys].vert[m].clipCoords, m_projectionMatrix, eyeCoords);
float eyeCoords[4]; // World coordinates transformed by the modelViewMatrix
vecmatmul4(eyeCoords, m_modelViewMatrix, currentPoly.vert[m].worldCoords);
vecmatmul4(currentPoly.vert[m].clipCoords, m_projectionMatrix, eyeCoords);
clipVerts[m].x = currentPoly.vert[m].clipCoords[0];
clipVerts[m].y = currentPoly.vert[m].clipCoords[1];
clipVerts[m].z = currentPoly.vert[m].clipCoords[2];
clipVerts[m].w = currentPoly.vert[m].clipCoords[3];
clipVerts[m].p[0] = currentPoly.vert[m].texCoords[0];
clipVerts[m].p[1] = currentPoly.vert[m].texCoords[1];
clipVerts[m].p[2] = currentPoly.vert[m].light[0];
clipVerts[m].p[3] = currentPoly.vert[m].light[1];
clipVerts[m].p[4] = currentPoly.vert[m].light[2];
}
if (polys[*numPolys].visible)
if (currentPoly.visible)
{
// Clip the triangles to the view frustum...
performFrustumClip(&polys[*numPolys]);
// Clip against all edges of the view frustum
int num_vertices = frustum_clip_all<float, 5>(clipVerts, currentPoly.n, clipVerts);
for (int m = 0; m < polys[*numPolys].n; m++)
// Copy the results of
currentPoly.n = num_vertices;
for (int m = 0; m < num_vertices; m++)
{
currentPoly.vert[m].clipCoords[0] = clipVerts[m].x;
currentPoly.vert[m].clipCoords[1] = clipVerts[m].y;
currentPoly.vert[m].clipCoords[2] = clipVerts[m].z;
currentPoly.vert[m].clipCoords[3] = clipVerts[m].w;
currentPoly.vert[m].texCoords[0] = clipVerts[m].p[0];
currentPoly.vert[m].texCoords[1] = clipVerts[m].p[1];
currentPoly.vert[m].light[0] = clipVerts[m].p[2];
currentPoly.vert[m].light[1] = clipVerts[m].p[3];
currentPoly.vert[m].light[2] = clipVerts[m].p[4];
}
for (int m = 0; m < currentPoly.n; m++)
{
// Convert into normalized device coordinates...
ndCoords[0] = polys[*numPolys].vert[m].clipCoords[0] / polys[*numPolys].vert[m].clipCoords[3];
ndCoords[1] = polys[*numPolys].vert[m].clipCoords[1] / polys[*numPolys].vert[m].clipCoords[3];
ndCoords[2] = polys[*numPolys].vert[m].clipCoords[2] / polys[*numPolys].vert[m].clipCoords[3];
ndCoords[3] = polys[*numPolys].vert[m].clipCoords[3];
float ndCoords[4]; // Normalized device coordinates/clipCoordinates (x/w, y/w, z/w)
ndCoords[0] = currentPoly.vert[m].clipCoords[0] / currentPoly.vert[m].clipCoords[3];
ndCoords[1] = currentPoly.vert[m].clipCoords[1] / currentPoly.vert[m].clipCoords[3];
ndCoords[2] = currentPoly.vert[m].clipCoords[2] / currentPoly.vert[m].clipCoords[3];
ndCoords[3] = currentPoly.vert[m].clipCoords[3];
// Final pixel values are garnered here :
float windowCoords[4]; // Mapped ndCoordinates to screen space
windowCoords[0] = (ndCoords[0]+1.0f) * ((float)(visarea.max_x) / 2.0f) + 0.0f;
windowCoords[1] = (ndCoords[1]+1.0f) * ((float)(visarea.max_y) / 2.0f) + 0.0f;
windowCoords[2] = (ndCoords[2]+1.0f) * 0.5f;
windowCoords[1] = (float)visarea.max_y - windowCoords[1]; // Flip Y
// Flip Y
windowCoords[1] = (float)visarea.max_y - windowCoords[1];
// Store the points in a list for later use...
polys[*numPolys].vert[m].clipCoords[0] = windowCoords[0];
polys[*numPolys].vert[m].clipCoords[1] = windowCoords[1];
polys[*numPolys].vert[m].clipCoords[2] = windowCoords[2];
polys[*numPolys].vert[m].clipCoords[3] = ndCoords[3];
currentPoly.vert[m].clipCoords[0] = windowCoords[0];
currentPoly.vert[m].clipCoords[1] = windowCoords[1];
currentPoly.vert[m].clipCoords[2] = windowCoords[2];
currentPoly.vert[m].clipCoords[3] = ndCoords[3];
}
}
}
@ -865,15 +896,16 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int* numPolys)
// Advance to the next polygon chunk...
chunkOffset += chunkLength;
(*numPolys)++;
numPolys++;
}
}
}
// note 0x0102 packets are only 8 words, it appears they can be in either the upper or lower half of the 16 word packet.
// We currently only draw 0x0102 packets where both halves contain 0x0102 (2 calls), but this causes graphics to vanish in xrally because in some cases the 0x0102 packet only exists in the upper or lower half
// with another value (often 0x0000 - NOP) in the other.
// If we also treat (0x0000 - NOP) as 8 word instead of 16 so that we can access a 0x0102 in the 2nd half of the 16 word packet then we end up with other invalid packets in the 2nd half which should be ignored.
// We currently only draw 0x0102 packets where both halves contain 0x0102 (2 calls), but this causes graphics to vanish in
// xrally because in some cases the 0x0102 packet only exists in the upper or lower half with another value (often 0x0000 - NOP) in the other.
// If we also treat (0x0000 - NOP) as 8 word instead of 16 so that we can access a 0x0102 in the 2nd half of the 16 word packet
// then we end up with other invalid packets in the 2nd half which should be ignored.
// This would suggest our processing if flawed in other ways, or there is something else to indicate packet length.
void hng64_state::hng64_command3d(const UINT16* packet)
@ -912,7 +944,7 @@ void hng64_state::hng64_command3d(const UINT16* packet)
if (packet[2] == 0x0003 && packet[3] == 0x8f37 && m_mcu_type == SHOOT_MCU)
break;
recoverPolygonBlock(packet, &numPolys);
recoverPolygonBlock(packet, numPolys);
break;
case 0x0102: // Geometry with only translation
@ -932,7 +964,7 @@ void hng64_state::hng64_command3d(const UINT16* packet)
miniPacket[7] = 0x7fff;
miniPacket[11] = 0x7fff;
miniPacket[15] = 0x7fff;
recoverPolygonBlock(miniPacket, &numPolys);
recoverPolygonBlock(miniPacket, numPolys);
memset(miniPacket, 0, sizeof(UINT16)*16);
for (int i = 0; i < 7; i++) miniPacket[i] = packet[i+8];
@ -940,7 +972,7 @@ void hng64_state::hng64_command3d(const UINT16* packet)
miniPacket[7] = 0x7fff;
miniPacket[11] = 0x7fff;
miniPacket[15] = 0x7fff;
recoverPolygonBlock(miniPacket, &numPolys);
recoverPolygonBlock(miniPacket, numPolys);
break;
case 0x1000: // Unknown: Some sort of global flags?
@ -956,12 +988,12 @@ void hng64_state::hng64_command3d(const UINT16* packet)
break;
}
/* If there are polygons, rasterize them into the display buffer */
// If there are polygons, rasterize them into the display buffer
for (int i = 0; i < numPolys; i++)
{
if (polys[i].visible)
if (m_polys[i].visible)
{
m_poly_renderer->drawShaded(&polys[i]);
m_poly_renderer->drawShaded(&m_polys[i]);
}
}
m_poly_renderer->wait();
@ -1004,11 +1036,12 @@ void hng64_state::clear3d()
*
*/
/////////////////////
// 3D UTILITY CODE //
/////////////////////
/* 4x4 matrix multiplication */
// 4x4 matrix multiplication
void hng64_state::matmul4(float *product, const float *a, const float *b)
{
int i;
@ -1026,7 +1059,7 @@ void hng64_state::matmul4(float *product, const float *a, const float *b)
}
}
/* vector by 4x4 matrix multiply */
// vector by 4x4 matrix multiply
void hng64_state::vecmatmul4(float *product, const float *a, const float *b)
{
const float& bi0 = b[0];
@ -1082,140 +1115,9 @@ void hng64_state::normalize(float* x)
}
///////////////////////////
// POLYGON CLIPPING CODE //
///////////////////////////
int hng64_state::Inside(struct polyVert *v, int plane)
{
switch(plane)
{
case HNG64_LEFT:
return (v->clipCoords[0] >= -v->clipCoords[3]) ? 1 : 0;
case HNG64_RIGHT:
return (v->clipCoords[0] <= v->clipCoords[3]) ? 1 : 0;
case HNG64_TOP:
return (v->clipCoords[1] <= v->clipCoords[3]) ? 1 : 0;
case HNG64_BOTTOM:
return (v->clipCoords[1] >= -v->clipCoords[3]) ? 1 : 0;
case HNG64_NEAR:
return (v->clipCoords[2] <= v->clipCoords[3]) ? 1 : 0;
case HNG64_FAR:
return (v->clipCoords[2] >= -v->clipCoords[3]) ? 1 : 0;
}
return 0;
}
void hng64_state::Intersect(struct polyVert *input0, struct polyVert *input1, struct polyVert *output, int plane)
{
float t = 0.0f;
float *Iv0 = input0->clipCoords;
float *Iv1 = input1->clipCoords;
float *Ov = output->clipCoords;
float *It0 = input0->texCoords;
float *It1 = input1->texCoords;
float *Ot = output->texCoords;
float *Il0 = input0->light;
float *Il1 = input1->light;
float *Ol = output->light;
switch(plane)
{
case HNG64_LEFT:
t = (Iv0[0]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[0]+Iv0[0]);
break;
case HNG64_RIGHT:
t = (Iv0[0]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[0]+Iv0[0]);
break;
case HNG64_TOP:
t = (Iv0[1]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[1]+Iv0[1]);
break;
case HNG64_BOTTOM:
t = (Iv0[1]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[1]+Iv0[1]);
break;
case HNG64_NEAR:
t = (Iv0[2]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[2]+Iv0[2]);
break;
case HNG64_FAR:
t = (Iv0[2]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[2]+Iv0[2]);
break;
}
Ov[0] = Iv0[0] + (Iv1[0] - Iv0[0]) * t;
Ov[1] = Iv0[1] + (Iv1[1] - Iv0[1]) * t;
Ov[2] = Iv0[2] + (Iv1[2] - Iv0[2]) * t;
Ov[3] = Iv0[3] + (Iv1[3] - Iv0[3]) * t;
Ot[0] = It0[0] + (It1[0] - It0[0]) * t;
Ot[1] = It0[1] + (It1[1] - It0[1]) * t;
Ot[2] = It0[2] + (It1[2] - It0[2]) * t;
Ot[3] = It0[3] + (It1[3] - It0[3]) * t;
Ol[0] = Il0[0] + (Il1[0] - Il0[0]) * t;
Ol[1] = Il0[1] + (Il1[1] - Il0[1]) * t;
Ol[2] = Il0[2] + (Il1[2] - Il0[2]) * t;
}
//////////////////////////////////////////////////////////////////////////
// Clip against the volumes defined by the homogeneous clip coordinates //
//////////////////////////////////////////////////////////////////////////
void hng64_state::performFrustumClip(struct polygon *p)
{
polyVert *v0;
polyVert *v1;
polyVert *tv;
polygon temp;
temp.n = 0;
// Skip near and far clipping planes ?
for (int j = 0; j <= HNG64_BOTTOM; j++)
{
for (int i = 0; i < p->n; i++)
{
int k = (i+1) % p->n; // Index of next vertex
v0 = &p->vert[i];
v1 = &p->vert[k];
tv = &temp.vert[temp.n];
if (Inside(v0, j) && Inside(v1, j)) // Edge is completely inside the volume...
{
memcpy(tv, v1, sizeof(struct polyVert));
temp.n++;
}
else if (Inside(v0, j) && !Inside(v1, j)) // Edge goes from in to out...
{
Intersect(v0, v1, tv, j);
temp.n++;
}
else if (!Inside(v0, j) && Inside(v1, j)) // Edge goes from out to in...
{
Intersect(v0, v1, tv, j);
memcpy(&temp.vert[temp.n+1], v1, sizeof(struct polyVert));
temp.n+=2;
}
}
p->n = temp.n;
for (int i = 0; i < temp.n; i++)
{
memcpy(&p->vert[i], &temp.vert[i], sizeof(struct polyVert));
}
temp.n = 0;
}
}
////////////////////////////////
// POLYGON RASTERIZATION CODE //
////////////////////////////////
void hng64_poly_renderer::render_scanline(INT32 scanline, const extent_t& extent, const hng64_poly_data& renderData, int threadid)
{
@ -1351,7 +1253,7 @@ void hng64_poly_renderer::render_scanline(INT32 scanline, const extent_t& extent
}
}
void hng64_poly_renderer::drawShaded(struct polygon *p)
void hng64_poly_renderer::drawShaded(polygon *p)
{
// Polygon information for the rasterizer
hng64_poly_data rOptions;
@ -1365,7 +1267,7 @@ void hng64_poly_renderer::drawShaded(struct polygon *p)
rOptions.texPageVertOffset = p->texPageVertOffset;
// The perspective-correct texture divide...
// NOTE: There is a very good chance the HNG64 hardware does not do perspective-correct texture-mapping - explore
// Note: There is a very good chance the HNG64 hardware does not do perspective-correct texture-mapping - explore
for (int j = 0; j < p->n; j++)
{
p->vert[j].clipCoords[3] = 1.0f / p->vert[j].clipCoords[3];

View File

@ -1,7 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont, Ville Linde
#include "emu.h"
#include "video/poly.h"
#include "video/rgbutil.h"
#include "includes/model3.h"
@ -1433,120 +1432,6 @@ void model3_state::set_projection(float left, float right, float top, float bott
/*****************************************************************************/
/* transformation and rasterizing */
static int clip_w(const m3_clip_vertex* v, int num_vertices, m3_clip_vertex* out)
{
if (num_vertices <= 0)
return 0;
const float W_PLANE = 0.000001f;
m3_clip_vertex clipv[10];
int clip_verts = 0;
int previ = num_vertices - 1;
for (int i=0; i < num_vertices; i++)
{
int v1_side = (v[i].w < W_PLANE) ? -1 : 1;
int v2_side = (v[previ].w < W_PLANE) ? -1 : 1;
if ((v1_side * v2_side) < 0) // edge goes through W plane
{
// insert vertex at intersection point
float wdiv = v[previ].w - v[i].w;
if (wdiv == 0.0f) // 0 edge means degenerate polygon
return 0;
float t = fabs((W_PLANE - v[previ].w) / wdiv);
clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t);
clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t);
clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t);
clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t);
clipv[clip_verts].u = v[previ].u + ((v[i].u - v[previ].u) * t);
clipv[clip_verts].v = v[previ].v + ((v[i].v - v[previ].v) * t);
clipv[clip_verts].i = v[previ].i + ((v[i].i - v[previ].i) * t);
clipv[clip_verts].s = v[previ].s + ((v[i].s - v[previ].s) * t);
++clip_verts;
}
if (v1_side > 0) // current point is inside
{
clipv[clip_verts] = v[i];
++clip_verts;
}
previ = i;
}
memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts);
return clip_verts;
}
static int clip(const m3_clip_vertex* v, int num_vertices, m3_clip_vertex* out, int axis, int sign)
{
if (num_vertices <= 0)
return 0;
m3_clip_vertex clipv[10];
int clip_verts = 0;
int previ = num_vertices - 1;
for (int i=0; i < num_vertices; i++)
{
int v1_side, v2_side;
float* v1a = (float*)&v[i];
float* v2a = (float*)&v[previ];
float v1_axis, v2_axis;
if (sign) // +axis
{
v1_axis = v1a[axis];
v2_axis = v2a[axis];
}
else // -axis
{
v1_axis = -v1a[axis];
v2_axis = -v2a[axis];
}
v1_side = (v1_axis <= v[i].w) ? 1 : -1;
v2_side = (v2_axis <= v[previ].w) ? 1 : -1;
if ((v1_side * v2_side) < 0) // edge goes through W plane
{
// insert vertex at intersection point
float wdiv = ((v[previ].w - v2_axis) - (v[i].w - v1_axis));
if (wdiv == 0.0f) // 0 edge means degenerate polygon
return 0;
float t = fabs((v[previ].w - v2_axis) / wdiv);
clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t);
clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t);
clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t);
clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t);
clipv[clip_verts].u = v[previ].u + ((v[i].u - v[previ].u) * t);
clipv[clip_verts].v = v[previ].v + ((v[i].v - v[previ].v) * t);
clipv[clip_verts].i = v[previ].i + ((v[i].i - v[previ].i) * t);
clipv[clip_verts].s = v[previ].s + ((v[i].s - v[previ].s) * t);
++clip_verts;
}
if (v1_side > 0) // current point is inside
{
clipv[clip_verts] = v[i];
++clip_verts;
}
previ = i;
}
memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts);
return clip_verts;
}
void model3_state::reset_triangle_buffers()
{
m_tri_buffer_ptr = 0;
@ -1728,8 +1613,8 @@ void model3_state::draw_model(UINT32 addr)
clip_vert[i].z = p[i][2];
clip_vert[i].w = p[i][3];
clip_vert[i].u = vertex[i].u * texture_coord_scale * 256.0f; // 8 bits of subtexel accuracy for bilinear filtering
clip_vert[i].v = vertex[i].v * texture_coord_scale * 256.0f;
clip_vert[i].p[0] = vertex[i].u * texture_coord_scale * 256.0f; // 8 bits of subtexel accuracy for bilinear filtering
clip_vert[i].p[1] = vertex[i].v * texture_coord_scale * 256.0f;
// transform vertex normal
VECTOR3 n;
@ -1767,17 +1652,11 @@ void model3_state::draw_model(UINT32 addr)
intensity = 255.0f;
}
clip_vert[i].i = intensity;
clip_vert[i].p[2] = intensity;
}
/* clip against view frustum */
num_vertices = clip_w(clip_vert, num_vertices, clip_vert);
num_vertices = clip(clip_vert, num_vertices, clip_vert, 0, 0); // W <= -X
num_vertices = clip(clip_vert, num_vertices, clip_vert, 0, 1); // W <= +X
num_vertices = clip(clip_vert, num_vertices, clip_vert, 1, 0); // W <= -Y
num_vertices = clip(clip_vert, num_vertices, clip_vert, 1, 1); // W <= +X
num_vertices = clip(clip_vert, num_vertices, clip_vert, 2, 0); // W <= -Z
num_vertices = clip(clip_vert, num_vertices, clip_vert, 2, 1); // W <= +Z
/* clip against all edges of the view frustum */
num_vertices = frustum_clip_all<float, 4>(clip_vert, num_vertices, clip_vert);
/* divide by W, transform to screen coords */
for(i=0; i < num_vertices; i++)
@ -1787,8 +1666,8 @@ void model3_state::draw_model(UINT32 addr)
clip_vert[i].x *= oow;
clip_vert[i].y *= oow;
clip_vert[i].z *= oow;
clip_vert[i].u *= oow;
clip_vert[i].v *= oow;
clip_vert[i].p[0] *= oow;
clip_vert[i].p[1] *= oow;
clip_vert[i].x = (((clip_vert[i].x * 0.5f) + 0.5f) * m_viewport_width) + m_viewport_x;
clip_vert[i].y = (((clip_vert[i].y * 0.5f) + 0.5f) * m_viewport_height) + m_viewport_y;
@ -2159,9 +2038,9 @@ void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tri
v[i].y = tri->v[i].y;
v[i].p[0] = tri->v[i].w;
v[i].p[1] = 1.0f / tri->v[i].w;
v[i].p[2] = tri->v[i].u;
v[i].p[3] = tri->v[i].v;
v[i].p[4] = tri->v[i].i;
v[i].p[2] = tri->v[i].p[0];
v[i].p[3] = tri->v[i].p[1];
v[i].p[4] = tri->v[i].p[2];
}
model3_polydata &extra = object_data_alloc();
@ -2189,7 +2068,7 @@ void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tri
v[i].x = tri->v[i].x;
v[i].y = tri->v[i].y;
v[i].p[0] = tri->v[i].w;
v[i].p[1] = tri->v[i].i;
v[i].p[1] = tri->v[i].p[2];
}
model3_polydata &extra = object_data_alloc();
@ -2224,9 +2103,9 @@ void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris
v[i].y = tri->v[i].y;
v[i].p[0] = tri->v[i].w;
v[i].p[1] = 1.0f / tri->v[i].w;
v[i].p[2] = tri->v[i].u;
v[i].p[3] = tri->v[i].v;
v[i].p[4] = tri->v[i].i;
v[i].p[2] = tri->v[i].p[0];
v[i].p[3] = tri->v[i].p[1];
v[i].p[4] = tri->v[i].p[2];
}
model3_polydata &extra = object_data_alloc();
@ -2243,7 +2122,7 @@ void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris
v[i].x = tri->v[i].x;
v[i].y = tri->v[i].y;
v[i].p[0] = tri->v[i].w;
v[i].p[1] = tri->v[i].i;
v[i].p[1] = tri->v[i].p[2];
}
model3_polydata &extra = object_data_alloc();