Files
BlitzNext/Runtime/blitz3d/planemodel.cpp
T

141 lines
3.3 KiB
C++
Raw Normal View History

2019-01-18 15:55:06 +01:00
#include "planemodel.hpp"
#include "camera.hpp"
2019-01-18 17:04:17 +01:00
#include "frustum.hpp"
2019-01-18 21:26:42 +01:00
#include <gxgraphics.hpp>
2014-01-31 08:23:00 +13:00
static Vector vts[17][17];
2019-01-18 17:04:17 +01:00
extern gxGraphics* gx_graphics;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
struct PlaneModel::Rep {
int ref_cnt;
gxMesh* mesh;
int sub_divs;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
Rep(int n) : ref_cnt(1), sub_divs(n)
{
mesh = gx_graphics->createMesh(5 * sub_divs * sub_divs, 3 * sub_divs * sub_divs, 0);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
~Rep()
{
gx_graphics->freeMesh(mesh);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void render(PlaneModel* model, const RenderContext& rc)
{
2014-01-31 08:23:00 +13:00
static Frustum f;
2019-01-18 17:04:17 +01:00
new (&f) Frustum(rc.getWorldFrustum(), -model->getRenderTform());
const Vector& eye = f.getVertex(Frustum::VERT_EYE);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
if (eye.y <= 0)
return;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
const Vector& tl = f.getVertex(Frustum::VERT_TLFAR);
const Vector& tr = f.getVertex(Frustum::VERT_TRFAR);
const Vector& br = f.getVertex(Frustum::VERT_BRFAR);
const Vector& bl = f.getVertex(Frustum::VERT_BLFAR);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
Transform tex_t(model->getRenderTform().m);
2014-01-31 08:23:00 +13:00
int x;
2019-01-18 17:04:17 +01:00
for (x = 0; x <= sub_divs; ++x) {
float t = float(x) / float(sub_divs);
Vector tx = (tr - tl) * t + tl;
Vector bx = (br - bl) * t + bl;
for (int y = 0; y <= sub_divs; ++y) {
float t = float(y) / float(sub_divs);
vts[x][y] = (bx - tx) * t + tx;
2014-01-31 08:23:00 +13:00
}
}
2019-01-18 17:04:17 +01:00
Plane plane(Vector(0, 1, 0), 0);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
mesh->lock(true);
int v_cnt = 0, t_cnt = 0;
for (x = 0; x < sub_divs; ++x) {
for (int y = 0; y < sub_divs; ++y) {
Vector in_verts[4], out_verts[5];
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
in_verts[0] = vts[x][y];
in_verts[1] = vts[x + 1][y];
in_verts[2] = vts[x + 1][y + 1];
in_verts[3] = vts[x][y + 1];
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
int k, out_cnt = 0;
for (k = 0; k < 4; ++k) {
const Vector& vert = in_verts[k];
const Vector& prev_vert = in_verts[(k - 1) & 3];
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
if (vert.y > 0) {
if (prev_vert.y <= 0) {
float t = prev_vert.y / (prev_vert.y - vert.y);
out_verts[out_cnt++] = (vert - prev_vert) * t + prev_vert;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
} else {
if (prev_vert.y > 0) {
float t = prev_vert.y / (prev_vert.y - vert.y);
out_verts[out_cnt++] = (vert - prev_vert) * t + prev_vert;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
out_verts[out_cnt++] = plane.intersect(Line(eye, vert - eye));
2014-01-31 08:23:00 +13:00
}
}
2019-01-18 17:04:17 +01:00
if (out_cnt < 3 || out_cnt > 5)
continue;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
for (k = 0; k < out_cnt; ++k) {
const Vector& v = out_verts[k];
float tex_coords[2][2] = {{v.x, v.z}, {v.x, v.z}};
mesh->setVertex(v_cnt + k, &v.x, &plane.n.x, tex_coords);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
for (k = 2; k < out_cnt; ++k) {
mesh->setTriangle(t_cnt++, v_cnt, v_cnt + k - 1, v_cnt + k);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
v_cnt += out_cnt;
2014-01-31 08:23:00 +13:00
}
}
mesh->unlock();
2019-01-18 17:04:17 +01:00
if (v_cnt < 3)
return;
model->enqueue(mesh, 0, v_cnt, 0, t_cnt);
2014-01-31 08:23:00 +13:00
}
};
2019-01-18 17:04:17 +01:00
PlaneModel::PlaneModel(int sub_divs) : rep(new Rep(sub_divs)) {}
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
PlaneModel::PlaneModel(const PlaneModel& t) : Model(t), rep(t.rep)
{
2014-01-31 08:23:00 +13:00
++rep->ref_cnt;
}
2019-01-18 17:04:17 +01:00
PlaneModel::~PlaneModel()
{
if (!--rep->ref_cnt)
delete rep;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
Plane PlaneModel::getRenderPlane() const
{
return Plane(getRenderTform().v, getRenderTform().m.j.normalized());
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
bool PlaneModel::render(const RenderContext& rc)
{
rep->render(this, rc);
2014-01-31 08:23:00 +13:00
return false;
}
2019-01-18 17:04:17 +01:00
bool PlaneModel::collide(const Line& l, float radius, Collision* curr_coll, const Transform& tf)
{
Line line(-tf * l);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
Plane p(Vector(0, 1, 0), 0);
p.d -= radius;
float t = p.t_intersect(line);
if (t >= curr_coll->time)
return false;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
Vector n = (tf.m.cofactor() * p.n).normalized();
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
return curr_coll->update(l, t, n);
2014-01-31 08:23:00 +13:00
}