670 lines
20 KiB
Plaintext
670 lines
20 KiB
Plaintext
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
|
// See the file tools.license for terms.
|
|
|
|
#ifndef tools_sg_render_zb
|
|
#define tools_sg_render_zb
|
|
|
|
#include "manager_zb"
|
|
|
|
#include "render_action"
|
|
#include "primitive_visitor"
|
|
#include "../glprims"
|
|
|
|
#include "../zb/buffer"
|
|
|
|
#include "../lina/plane"
|
|
#include "../mathf"
|
|
#include "../hls"
|
|
|
|
#ifdef _MSC_VER
|
|
// disable the warning about the usage of "this" in the constructor.
|
|
#pragma warning(disable:4355)
|
|
#endif
|
|
|
|
namespace tools {
|
|
namespace sg {
|
|
|
|
class render_zb : public render_action {
|
|
public:
|
|
virtual void draw_vertex_array(gl::mode_t a_mode,unsigned int a_floatn,const float* a_xyzs){
|
|
m_pv.add_primitive(a_mode,a_floatn,a_xyzs);
|
|
}
|
|
|
|
virtual void draw_vertex_array_xy(gl::mode_t a_mode,unsigned int a_floatn,const float* a_xys){
|
|
m_pv.add_primitive_xy(a_mode,a_floatn,a_xys);
|
|
}
|
|
|
|
virtual void draw_vertex_color_array(gl::mode_t a_mode,unsigned int a_floatn,
|
|
const float* a_xyzs,const float* a_rgbas){
|
|
m_pv.add_primitive(a_mode,a_floatn,a_xyzs,a_rgbas);
|
|
}
|
|
|
|
virtual void draw_vertex_normal_array(gl::mode_t a_mode,unsigned int a_floatn,
|
|
const float* a_xyzs,const float* /*a_nms*/){
|
|
m_pv.add_primitive(a_mode,a_floatn,a_xyzs);
|
|
}
|
|
|
|
virtual void draw_vertex_color_normal_array(gl::mode_t a_mode,unsigned int a_floatn,
|
|
const float* a_xyzs,const float* a_rgbas,const float* /*a_nms*/){
|
|
// We expect a_nms of size : 3*(a_floatn/3)
|
|
// (then one normal per 3D point).
|
|
m_pv.add_primitive(a_mode,a_floatn,a_xyzs,a_rgbas);
|
|
}
|
|
|
|
virtual void clear_color(float a_r,float a_g,float a_b,float a_a){
|
|
zb::buffer::ZPixel px = get_pix(colorf(a_r,a_g,a_b,a_a));
|
|
m_zb.clear_color_buffer(px);
|
|
}
|
|
virtual void color4f(float a_r,float a_g,float a_b,float a_a){
|
|
m_rgba.set_value(a_r,a_g,a_b,a_a);
|
|
}
|
|
virtual void line_width(float a_v){m_line_width = a_v;}
|
|
virtual void point_size(float a_v) {m_point_size = a_v;}
|
|
virtual void set_polygon_offset(bool a_v) {m_POLYGON_OFFSET_FILL = a_v;}
|
|
virtual void normal(float a_x,float a_y,float a_z) {
|
|
m_normal.set_value(a_x,a_y,a_z);
|
|
}
|
|
|
|
virtual void set_winding(winding_type a_v) {
|
|
m_ccw = (a_v==winding_ccw?true:false);
|
|
}
|
|
|
|
virtual void set_depth_test(bool a_on) {m_DEPTH_TEST = a_on;}
|
|
|
|
virtual void set_cull_face(bool a_on) {m_CULL_FACE = a_on;}
|
|
virtual void set_point_smooth(bool a_on) {m_POINT_SMOOTH = a_on;}
|
|
virtual void set_line_smooth(bool a_on) {m_LINE_SMOOTH = a_on;}
|
|
|
|
virtual void load_proj_matrix(const mat4f& a_mtx) {
|
|
m_proj = a_mtx;
|
|
if(!m_proj.invert(m_proj_1)){}
|
|
}
|
|
|
|
virtual void load_model_matrix(const mat4f& a_mtx) {m_model = a_mtx;}
|
|
|
|
virtual unsigned int max_lights() {return 1000;}
|
|
|
|
virtual void enable_light(unsigned int,
|
|
float a_dx,float a_dy,float a_dz,
|
|
float a_r,float a_g,float a_b,float a_a){
|
|
m_light_color.set_value(a_r,a_g,a_b,a_a);
|
|
m_light_direction.set_value(a_dx,a_dy,a_dz);
|
|
m_light_on = true;
|
|
}
|
|
|
|
virtual void set_lighting(bool a_on) {m_light_on = a_on;}
|
|
|
|
virtual void restore_state(unsigned int /*a_ret_num_light*/) {
|
|
m_proj = m_state.m_proj;
|
|
m_model = m_state.m_model;
|
|
|
|
if(!m_proj.invert(m_proj_1)){}
|
|
|
|
m_rgba = m_state.m_color;
|
|
m_ccw = (m_state.m_winding==winding_ccw?true:false);
|
|
m_POLYGON_OFFSET_FILL = m_state.m_GL_POLYGON_OFFSET_FILL;
|
|
m_CULL_FACE = m_state.m_GL_CULL_FACE;
|
|
m_POINT_SMOOTH = m_state.m_GL_POINT_SMOOTH;
|
|
m_LINE_SMOOTH = m_state.m_GL_LINE_SMOOTH;
|
|
m_line_width = m_state.m_line_width;
|
|
m_point_size = m_state.m_point_size;
|
|
m_light_on = m_state.m_GL_LIGHTING;
|
|
m_DEPTH_TEST = m_state.m_GL_DEPTH_TEST;
|
|
|
|
|
|
/*
|
|
if(m_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
|
|
else ::glDisable(GL_TEXTURE_2D);
|
|
|
|
// The "return of separator" state had ret_num_light.
|
|
// The restored state has m_light.
|
|
// We have to glDisable lights with index in [m_light,ret_num_light-1]
|
|
for(unsigned int index=m_state.m_light;index<a_ret_num_light;index++) {
|
|
::glDisable(GL_LIGHT0+index);
|
|
}
|
|
*/
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
/// texture /////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////
|
|
virtual void draw_vertex_array_texture(tools::gl::mode_t,unsigned int a_xyzn,const float* a_xyzs,
|
|
unsigned int a_id,const float*) {
|
|
//::printf("debug : render_zb : 000 : %d\n",a_id);
|
|
|
|
tools::img_byte img;
|
|
if(!m_mgr.find(a_id,img)) return;
|
|
|
|
//::printf("debug : render_zb : img : %d %d\n",img.width(),img.height());
|
|
|
|
if(a_xyzn!=12) {
|
|
m_out << "tools::sg::render_zb::draw_vertex_array_texture :"
|
|
<< " primitive has not four points."
|
|
<< std::endl;
|
|
return;
|
|
}
|
|
|
|
float x1 = a_xyzs[0];
|
|
float y1 = a_xyzs[ 1];
|
|
//float z1 = a_xyzs[ 2];
|
|
|
|
float x2 = a_xyzs[3];
|
|
//float y2 = a_xyzs[ 4];
|
|
//float z2 = a_xyzs[ 5];
|
|
|
|
//float x3 = a_xyzs[6];
|
|
//float y3 = a_xyzs[ 7];
|
|
//float z3 = a_xyzs[ 8];
|
|
|
|
//float x4 = a_xyzs[9];
|
|
float y4 = a_xyzs[10];
|
|
//float z4 = a_xyzs[11];
|
|
|
|
float bw = x2-x1;
|
|
float bh = y4-y1;
|
|
float bw_2 = bw*0.5f;
|
|
float bh_2 = bh*0.5f;
|
|
|
|
//::printf("debug : render_zb : box : %g %g\n",bw,bh);
|
|
|
|
unsigned int w = img.width();
|
|
unsigned int h = img.height();
|
|
unsigned int bpp = img.bpp();
|
|
if(bpp!=3) {
|
|
m_out << "tools::sg::render_zb::draw_vertex_array_texture :"
|
|
<< " not a 3 bytes per pixel image."
|
|
<< std::endl;
|
|
return;
|
|
}
|
|
|
|
unsigned char* pos = img.buffer();
|
|
for(unsigned int row=0;row<h;row++) {
|
|
for(unsigned int col=0;col<w;col++) {
|
|
float r = (*pos)/255.0f;pos++;
|
|
float g = (*pos)/255.0f;pos++;
|
|
float b = (*pos)/255.0f;pos++;
|
|
float x = bw*float(col)/float(w-1)-bw_2;
|
|
float y = bh*float(row)/float(h-1)-bh_2;
|
|
float z = 0;
|
|
m_rgba.set_value(r,g,b,1);
|
|
m_pv.add_one_point(x,y,z);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
virtual void draw_vertex_normal_array_texture(tools::gl::mode_t a_mode,
|
|
unsigned int a_xyzn,const float* a_xyzs,const float* /*a_nms*/,
|
|
unsigned int a_id,const float* a_tcs) {
|
|
draw_vertex_array_texture(a_mode,a_xyzn,a_xyzs,a_id,a_tcs);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
/// VBO /////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////
|
|
virtual void begin_gsto(unsigned int) {}
|
|
virtual void draw_gsto_v(tools::gl::mode_t,unsigned int,bufpos){}
|
|
virtual void draw_gsto_vc(tools::gl::mode_t,unsigned int,bufpos,bufpos) {}
|
|
virtual void draw_gsto_vn(tools::gl::mode_t,unsigned int,bufpos,bufpos) {}
|
|
virtual void draw_gsto_vcn(tools::gl::mode_t,unsigned int,bufpos,bufpos,bufpos) {}
|
|
virtual void end_gsto() {}
|
|
/////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////
|
|
virtual sg::gl_manager& gl_manager() {return m_mgr;}
|
|
public:
|
|
render_zb(manager_zb& a_mgr,std::ostream& a_out,unsigned int a_ww,unsigned int a_wh)
|
|
:render_action(a_out,a_ww,a_wh)
|
|
,m_mgr(a_mgr)
|
|
,m_pv(*this)
|
|
,m_light_color(tools::colorf::white())
|
|
,m_light_direction(tools::vec3f(0,0,-1))
|
|
|
|
,m_ccw(true)
|
|
,m_POLYGON_OFFSET_FILL(false)
|
|
,m_CULL_FACE(true)
|
|
,m_POINT_SMOOTH(false)
|
|
,m_LINE_SMOOTH(false)
|
|
,m_line_width(1)
|
|
,m_point_size(1)
|
|
,m_light_on(false)
|
|
,m_DEPTH_TEST(true)
|
|
{
|
|
m_vp_mtx.set_identity();
|
|
m_vp_mtx.mul_translate(float(m_ww)/2,float(m_wh)/2,0);
|
|
m_vp_mtx.mul_scale(float(m_ww)/2,float(m_wh)/2,1);
|
|
|
|
m_zb.change_size(a_ww,a_wh);
|
|
// m_zb.clear_color_buffer(0);
|
|
// m_zb.clear_depth_buffer();
|
|
}
|
|
virtual ~render_zb(){}
|
|
protected:
|
|
render_zb(const render_zb& a_from)
|
|
:render_action(a_from)
|
|
,m_mgr(a_from.m_mgr)
|
|
,m_vp_mtx(a_from.m_vp_mtx)
|
|
//,m_buffer(a_from.m_buffer)
|
|
,m_pv(a_from.m_pv)
|
|
,m_proj_1(a_from.m_proj_1)
|
|
,m_light_color(a_from.m_light_color)
|
|
,m_light_direction(a_from.m_light_direction)
|
|
,m_normal(a_from.m_normal)
|
|
|
|
,m_proj(a_from.m_proj)
|
|
,m_model(a_from.m_model)
|
|
,m_rgba(a_from.m_rgba)
|
|
,m_ccw(a_from.m_ccw)
|
|
,m_POLYGON_OFFSET_FILL(a_from.m_POLYGON_OFFSET_FILL)
|
|
,m_CULL_FACE(a_from.m_CULL_FACE)
|
|
,m_POINT_SMOOTH(a_from.m_POINT_SMOOTH)
|
|
,m_LINE_SMOOTH(a_from.m_LINE_SMOOTH)
|
|
,m_line_width(a_from.m_line_width)
|
|
,m_point_size(a_from.m_point_size)
|
|
,m_light_on(a_from.m_light_on)
|
|
,m_DEPTH_TEST(a_from.m_DEPTH_TEST)
|
|
{}
|
|
render_zb& operator=(const render_zb& a_from){
|
|
render_action::operator=(a_from);
|
|
m_vp_mtx = a_from.m_vp_mtx;
|
|
//m_buffer = a_from.m_buffer;
|
|
m_pv = a_from.m_pv;
|
|
m_proj_1 = a_from.m_proj_1;
|
|
m_light_color = a_from.m_light_color;
|
|
m_light_direction = a_from.m_light_direction;
|
|
m_normal = a_from.m_normal;
|
|
|
|
m_proj = a_from.m_proj;
|
|
m_model = a_from.m_model;
|
|
m_rgba = a_from.m_rgba;
|
|
m_ccw = a_from.m_ccw;
|
|
m_POLYGON_OFFSET_FILL = a_from.m_POLYGON_OFFSET_FILL;
|
|
m_CULL_FACE = a_from.m_CULL_FACE;
|
|
m_POINT_SMOOTH = a_from.m_POINT_SMOOTH;
|
|
m_LINE_SMOOTH = a_from.m_LINE_SMOOTH;
|
|
m_line_width = a_from.m_line_width;
|
|
m_point_size = a_from.m_point_size;
|
|
m_light_on = a_from.m_light_on;
|
|
m_DEPTH_TEST = a_from.m_DEPTH_TEST;
|
|
return *this;
|
|
}
|
|
public:
|
|
void reset() {
|
|
m_cmap.clear();
|
|
m_rcmap.clear();
|
|
}
|
|
|
|
const zb::buffer& zbuffer() const {return m_zb;}
|
|
zb::buffer& zbuffer() {return m_zb;}
|
|
protected:
|
|
typedef std::map<colorf,zb::buffer::ZPixel,cmp_colorf> cmap_t;
|
|
public:
|
|
//const cmap_t& colormap() const {return m_cmap;}
|
|
//cmap_t& colormap() {return m_cmap;}
|
|
zb::buffer::ZPixel add_color(float a_r,float a_g,float a_b,float a_a){
|
|
return add_color(colorf(a_r,a_g,a_b,a_a));
|
|
}
|
|
zb::buffer::ZPixel add_color(float a_r,float a_g,float a_b){
|
|
return add_color(a_r,a_g,a_b,1);
|
|
}
|
|
zb::buffer::ZPixel add_color(const colorf& a_col){
|
|
//::printf("debug : render_zb::add_color : %g %g %g %g : %d\n",
|
|
// a_col.r(),a_col.g(),a_col.b(),a_col.a(),m_cmap.size());
|
|
zb::buffer::ZPixel pix = m_cmap.size();
|
|
m_cmap[a_col] = pix;
|
|
return pix;
|
|
}
|
|
|
|
zb::buffer::ZPixel get_pix(const colorf& a_rgba) {
|
|
cmap_t::const_iterator it = m_cmap.find(a_rgba);
|
|
if(it!=m_cmap.end()) return (*it).second;
|
|
return add_color(a_rgba);
|
|
}
|
|
|
|
typedef std::map<zb::buffer::ZPixel,colorf> rcmap_t;
|
|
const rcmap_t& rcolormap() const {return m_rcmap;}
|
|
rcmap_t& rcolormap() {return m_rcmap;}
|
|
protected:
|
|
void gen_rcmap() {
|
|
m_rcmap.clear();
|
|
cmap_t::const_iterator it;
|
|
for(it=m_cmap.begin();it!=m_cmap.end();++it){
|
|
m_rcmap[(*it).second] = (*it).first;
|
|
}
|
|
}
|
|
public:
|
|
//typedef tools::wps::VCol VCol;
|
|
typedef float VCol;
|
|
|
|
static bool get_rgb(void* a_tag,unsigned int a_col,unsigned int a_row,VCol& a_r,VCol& a_g,VCol& a_b){
|
|
//used with tools::wps.
|
|
render_zb* rzb = (render_zb*)a_tag;
|
|
|
|
zb::buffer::ZPixel pix;
|
|
if(!rzb->zbuffer().get_clipped_pixel(a_col,rzb->wh()-1-a_row,pix)){
|
|
rzb->out() << "get_rgb : can't get zbuffer pixel" << std::endl;
|
|
a_r = 1;
|
|
a_g = 0;
|
|
a_b = 0;
|
|
return false;
|
|
}
|
|
|
|
if(rzb->rcolormap().empty()) rzb->gen_rcmap();
|
|
|
|
{rcmap_t::const_iterator it = rzb->rcolormap().find(pix);
|
|
if(it==rzb->rcolormap().end()) {
|
|
rzb->out() << "can't find pixel " << pix
|
|
<< " in cmap (sz " << rzb->rcolormap().size() << ")."
|
|
<< std::endl;
|
|
a_r = 1;
|
|
a_g = 0;
|
|
a_b = 0;
|
|
return false;
|
|
}
|
|
a_r = (*it).second.r();
|
|
a_g = (*it).second.g();
|
|
a_b = (*it).second.b();}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected:
|
|
bool project_point(float& a_x,float& a_y,float& a_z,float& a_w) {
|
|
a_w = 1;
|
|
m_model.mul_4f(a_x,a_y,a_z,a_w);
|
|
m_proj.mul_4f(a_x,a_y,a_z,a_w);
|
|
if(a_w==0) return false;
|
|
a_x /= a_w;
|
|
a_y /= a_w;
|
|
a_z /= a_w;
|
|
return true;
|
|
}
|
|
|
|
class primvis : public primitive_visitor {
|
|
protected:
|
|
virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) {
|
|
return m_rzb.project_point(a_x,a_y,a_z,a_w);
|
|
}
|
|
virtual bool add_point(float a_x,float a_y,float a_z,float) {
|
|
return _add_point(a_x,a_y,a_z,m_rzb.m_rgba);
|
|
}
|
|
|
|
virtual bool add_point(float a_x,float a_y,float a_z,float,
|
|
float a_r,float a_g,float a_b,float a_a) {
|
|
colorf c(a_r,a_g,a_b,a_a);
|
|
return _add_point(a_x,a_y,a_z,c);
|
|
}
|
|
|
|
virtual bool add_line(float a_bx,float a_by,float a_bz,float,
|
|
float a_ex,float a_ey,float a_ez,float) {
|
|
m_rzb.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
|
|
m_rzb.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
|
|
a_bz *= -1;
|
|
a_ez *= -1;
|
|
|
|
zb::point beg;
|
|
zinit(beg,a_bx,a_by,a_bz);
|
|
|
|
zb::point end;
|
|
zinit(end,a_ex,a_ey,a_ez);
|
|
|
|
m_rzb.m_zb.set_depth_test(m_rzb.m_DEPTH_TEST);
|
|
m_rzb.m_zb.draw_line(beg,end,m_rzb.get_pix(m_rzb.m_rgba),npix(m_rzb.m_line_width));
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool add_line(float a_bx,float a_by,float a_bz,float,
|
|
float a_br,float a_bg,float a_bb,float a_ba,
|
|
float a_ex,float a_ey,float a_ez,float,
|
|
float,float,float,float) {
|
|
m_rzb.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
|
|
m_rzb.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
|
|
a_bz *= -1;
|
|
a_ez *= -1;
|
|
|
|
zb::point beg;
|
|
zinit(beg,a_bx,a_by,a_bz);
|
|
|
|
zb::point end;
|
|
zinit(end,a_ex,a_ey,a_ez);
|
|
|
|
m_rzb.m_zb.set_depth_test(m_rzb.m_DEPTH_TEST);
|
|
|
|
// interpolate color with beg,end ?
|
|
m_rzb.m_zb.draw_line(beg,end,m_rzb.get_pix(colorf(a_br,a_bg,a_bb,a_ba)),npix(m_rzb.m_line_width));
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
|
|
float a_p2x,float a_p2y,float a_p2z,float a_p2w,
|
|
float a_p3x,float a_p3y,float a_p3z,float a_p3w){
|
|
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
|
|
a_p2x,a_p2y,a_p2z,a_p2w,
|
|
a_p3x,a_p3y,a_p3z,a_p3w,
|
|
m_rzb.m_rgba);
|
|
}
|
|
|
|
virtual bool add_triangle(
|
|
float a_p1x,float a_p1y,float a_p1z,float a_p1w,
|
|
float a_r1,float a_g1,float a_b1,float a_a1,
|
|
float a_p2x,float a_p2y,float a_p2z,float a_p2w,
|
|
float a_r2,float a_g2,float a_b2,float a_a2,
|
|
float a_p3x,float a_p3y,float a_p3z,float a_p3w,
|
|
float a_r3,float a_g3,float a_b3,float a_a3){
|
|
|
|
float r = (a_r1+a_r2+a_r3)/3.0f;
|
|
float g = (a_g1+a_g2+a_g3)/3.0f;
|
|
float b = (a_b1+a_b2+a_b3)/3.0f;
|
|
float a = (a_a1+a_a2+a_a3)/3.0f;
|
|
colorf col(r,g,b,a);
|
|
|
|
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
|
|
a_p2x,a_p2y,a_p2z,a_p2w,
|
|
a_p3x,a_p3y,a_p3z,a_p3w,
|
|
col);
|
|
}
|
|
|
|
public:
|
|
primvis(render_zb& a_zb):m_rzb(a_zb){}
|
|
virtual ~primvis(){}
|
|
public:
|
|
primvis(const primvis& a_from)
|
|
:primitive_visitor(a_from)
|
|
,m_rzb(a_from.m_rzb)
|
|
{}
|
|
primvis& operator=(const primvis& a_from){
|
|
primitive_visitor::operator=(a_from);
|
|
return *this;
|
|
}
|
|
protected:
|
|
static void zinit(zb::point& a_p,float a_x,float a_y,float a_z) {
|
|
a_p.x = fround(a_x); //float -> int
|
|
a_p.y = fround(a_y); //float -> int
|
|
a_p.z = (zb::ZZ)a_z; //float -> double
|
|
}
|
|
|
|
unsigned int npix(float a_size) { //a_size must be >1
|
|
// 0 -> 0
|
|
// 1 -> 0
|
|
// 2 -> 1 3x3
|
|
// 3 -> 1 3x3
|
|
// 4 -> 2 5x5
|
|
// 5 -> 2 5x5
|
|
// 6 -> 3 7x7
|
|
unsigned int num = (unsigned int)a_size;
|
|
unsigned int num_2 = num/2;
|
|
if(2*num_2==num) {num++;num_2 = num/2;}
|
|
return num_2;
|
|
}
|
|
|
|
bool _add_point(float a_x,float a_y,float a_z,const colorf& a_color){
|
|
m_rzb.m_zb.set_depth_test(m_rzb.m_DEPTH_TEST);
|
|
|
|
m_rzb.m_vp_mtx.mul_3f(a_x,a_y,a_z);
|
|
a_z *= -1;
|
|
|
|
zb::point p;
|
|
zinit(p,a_x,a_y,a_z);
|
|
|
|
zb::buffer::ZPixel px = m_rzb.get_pix(a_color);
|
|
|
|
m_rzb.m_zb.draw_point(p,px,npix(m_rzb.m_point_size));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool _add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
|
|
float a_p2x,float a_p2y,float a_p2z,float a_p2w,
|
|
float a_p3x,float a_p3y,float a_p3z,float a_p3w,
|
|
const colorf& a_color){
|
|
|
|
float p1x = a_p1x;float p1y = a_p1y;float p1z = a_p1z;//float p1w = a_p1w;
|
|
float p2x = a_p2x;float p2y = a_p2y;float p2z = a_p2z;//float p2w = a_p2w;
|
|
float p3x = a_p3x;float p3y = a_p3y;float p3z = a_p3z;//float p3w = a_p3w;
|
|
|
|
m_rzb.m_vp_mtx.mul_3f(p1x,p1y,p1z);
|
|
m_rzb.m_vp_mtx.mul_3f(p2x,p2y,p2z);
|
|
m_rzb.m_vp_mtx.mul_3f(p3x,p3y,p3z);
|
|
p1z *= -1;
|
|
p2z *= -1;
|
|
p3z *= -1;
|
|
|
|
if(m_rzb.m_POLYGON_OFFSET_FILL){
|
|
// zs are in [-1,1]
|
|
float epsil = 1e-5f;
|
|
//float epsil = 1e-4f;
|
|
p1z -= epsil;
|
|
p2z -= epsil;
|
|
p3z -= epsil;
|
|
}
|
|
|
|
typedef tools::zb::ZZ ZZ;
|
|
|
|
plane<ZZ> pn(
|
|
vec3<ZZ>(p1x,p1y,p1z),
|
|
vec3<ZZ>(p2x,p2y,p2z),
|
|
vec3<ZZ>(p3x,p3y,p3z)
|
|
);
|
|
if(!pn.is_valid()) return true;
|
|
|
|
// norm[0]*x+norm[1]*y+norm[2]*z = dist
|
|
// A*x+B*y+C*z+D = 0
|
|
|
|
ZZ C = pn.normal()[2];
|
|
|
|
if(m_rzb.m_CULL_FACE){ // check back facing or by the edge :
|
|
if(m_rzb.m_ccw) {
|
|
if(C<=0) return true;
|
|
} else {
|
|
if(C>=0) return true;
|
|
}
|
|
}
|
|
|
|
ZZ A = pn.normal()[0];
|
|
ZZ B = pn.normal()[1];
|
|
ZZ D = -pn.distance_from_origin();
|
|
|
|
//ZZ zmn = mn<ZZ>(mn<ZZ>(p1z,p2z),p3z);
|
|
//ZZ zmx = mx<ZZ>(mx<ZZ>(p1z,p2z),p3z);
|
|
|
|
zb::point list[3];
|
|
zinit(list[0],p1x,p1y,p1z);
|
|
zinit(list[1],p2x,p2y,p2z);
|
|
zinit(list[2],p3x,p3y,p3z);
|
|
|
|
m_rzb.m_zb.set_depth_test(m_rzb.m_DEPTH_TEST);
|
|
|
|
if(m_rzb.m_light_on) {
|
|
|
|
float _p1x = a_p1x;float _p1y = a_p1y;float _p1z = a_p1z;float _p1w = a_p1w;
|
|
float _p2x = a_p2x;float _p2y = a_p2y;float _p2z = a_p2z;float _p2w = a_p2w;
|
|
float _p3x = a_p3x;float _p3y = a_p3y;float _p3z = a_p3z;float _p3w = a_p3w;
|
|
|
|
_p1x *= _p1w;_p1y *= _p1w;_p1z *= _p1w;
|
|
_p2x *= _p2w;_p2y *= _p2w;_p2z *= _p2w;
|
|
_p3x *= _p3w;_p3y *= _p3w;_p3z *= _p3w;
|
|
|
|
m_rzb.m_proj_1.mul_4f(_p1x,_p1y,_p1z,_p1w);
|
|
m_rzb.m_proj_1.mul_4f(_p2x,_p2y,_p2z,_p2w);
|
|
m_rzb.m_proj_1.mul_4f(_p3x,_p3y,_p3z,_p3w);
|
|
|
|
plane<ZZ> _pn(
|
|
vec3<ZZ>(_p1x,_p1y,_p1z),
|
|
vec3<ZZ>(_p2x,_p2y,_p2z),
|
|
vec3<ZZ>(_p3x,_p3y,_p3z)
|
|
);
|
|
if(_pn.is_valid()) {
|
|
vec3f npn(float(_pn.normal().x()),
|
|
float(_pn.normal().y()),
|
|
float(_pn.normal().z()));
|
|
vec3f d = m_rzb.m_light_direction;
|
|
float dx = m_rzb.m_light_direction.x();
|
|
float dy = m_rzb.m_light_direction.y();
|
|
float dz = m_rzb.m_light_direction.z();
|
|
m_rzb.m_model.mul_3f(dx,dy,dz);
|
|
d.set_value(dx,dy,dz);
|
|
if(d.normalize()) {
|
|
float dot = npn.dot(d);
|
|
if((-1<=dot)&&(dot<=0)) {
|
|
dot *= -1;
|
|
|
|
// colorf c
|
|
// (a_color.r()*dot,a_color.g()*dot,a_color.b()*dot,a_color.a());
|
|
|
|
float h,l,s;
|
|
rgb_to_hls(a_color.r(),a_color.g(),a_color.b(),h,l,s);
|
|
l *= dot;
|
|
float r,g,b;
|
|
hls_to_rgb(h,l,s,r,g,b);
|
|
|
|
colorf c(r,g,b,a_color.a());
|
|
|
|
m_rzb.m_zb.draw_polygon(3,list,A,B,C,D,m_rzb.get_pix(c));
|
|
//m_rzb.m_zb.draw_polygon(3,list,A,B,C,D,m_rzb.get_pix(a_color));
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
m_rzb.m_zb.draw_polygon(3,list,A,B,C,D,m_rzb.get_pix(a_color));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
protected:
|
|
render_zb& m_rzb;
|
|
};
|
|
|
|
protected:
|
|
manager_zb& m_mgr;
|
|
mat4f m_vp_mtx;
|
|
zb::buffer m_zb;
|
|
primvis m_pv;
|
|
mat4f m_proj_1; //OPTIMIZE : used if m_light_on true.
|
|
cmap_t m_cmap;
|
|
rcmap_t m_rcmap;
|
|
colorf m_light_color;
|
|
vec3f m_light_direction;
|
|
vec3f m_normal;
|
|
|
|
// to be restored in restore_state() :
|
|
mat4f m_proj;
|
|
mat4f m_model;
|
|
colorf m_rgba;
|
|
bool m_ccw;
|
|
bool m_POLYGON_OFFSET_FILL;
|
|
bool m_CULL_FACE;
|
|
bool m_POINT_SMOOTH;
|
|
bool m_LINE_SMOOTH;
|
|
float m_line_width;
|
|
float m_point_size;
|
|
bool m_light_on;
|
|
bool m_DEPTH_TEST;
|
|
};
|
|
|
|
}}
|
|
|
|
#endif
|