Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
+660
View File
@@ -0,0 +1,660 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_action
#define toolx_sg_GL_action
#include "GL_manager"
#include <tools/sg/render_action>
//#include <tools/mathf>
//#include <tools/lina/matout>
namespace toolx {
namespace sg {
class GL_action : public tools::sg::render_action {
TOOLS_ACTION(GL_action,toolx::sg::GL_action,tools::sg::render_action)
public:
virtual void draw_vertex_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs){
size_t num = a_floatn/3;
if(!num) return;
_draw_v(a_mode,num,a_xyzs);
}
virtual void draw_vertex_array_xy(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xys){
size_t num = a_floatn/2;
if(!num) return;
#ifdef _WIN32
float* vp = new float[num*3];
if(!vp) return;
float* pos = vp;
float* pda = (float*)a_xys;
for(size_t index=0;index<num;index++){
*pos = *pda;pos++;pda++;
*pos = *pda;pos++;pda++;
*pos = 0;pos++; //Windows GL needs a z = 0.
}
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,vp);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
delete [] vp;
#else
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(2,GL_FLOAT,0,a_xys);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
#endif
}
virtual void draw_vertex_color_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_rgbas){
// Used in atb_vertices.
// We expect a_rgbas of size : 4*(a_floatn/3)
// (then one RGBA color per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vc(a_mode,num,a_xyzs,a_rgbas);
}
virtual void draw_vertex_normal_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_nms){
// We expect a_nms of size : 3*(a_floatn/3)
// (then one normal per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vn(a_mode,num,a_xyzs,a_nms);
}
virtual void draw_vertex_color_normal_array(tools::gl::mode_t a_mode,
size_t a_floatn,const float* a_xyzs,const float* a_rgbas,const float* a_nms){
// Used in atb_vertices.
// We expect a_nms of size : 3*(a_floatn/3)
// (then one normal per 3D point).
// We expect a_rgbas of size : 4*(a_floatn/3)
// (then one RGBA color per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vcn(a_mode,num,a_xyzs,a_rgbas,a_nms);
}
/////////////////////////////////////////////////////////////////
/// texture /////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void draw_vertex_array_texture(tools::gl::mode_t a_mode,
size_t a_floatn,
const float* a_xyzs,
gstoid a_tex,
const float* a_tex_coords) {
size_t num = a_floatn/3;
if(!num) return;
//expect 2*num a_tex_coords.
::glEnable(GL_TEXTURE_2D);
m_mgr.bind_gsto(a_tex);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
::glBindTexture(GL_TEXTURE_2D,0);
::glDisable(GL_TEXTURE_2D);
}
virtual void draw_vertex_normal_array_texture(tools::gl::mode_t a_mode,
size_t a_floatn,
const float* a_xyzs,
const float* a_nms,
gstoid a_tex,
const float* a_tex_coords) {
size_t num = a_floatn/3;
if(!num) return;
//expect 2*num a_tex_coords.
::glEnable(GL_TEXTURE_2D);
m_mgr.bind_gsto(a_tex);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
::glNormalPointer(GL_FLOAT,0,a_nms);
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
::glBindTexture(GL_TEXTURE_2D,0);
::glDisable(GL_TEXTURE_2D);
}
/////////////////////////////////////////////////////////////////
/// VBO /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void begin_gsto(gstoid a_id) {
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
m_mgr.bind_gsto(a_id);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
m_gsto = a_id;
m_created = false;
m_gl_id = m_mgr.gsto_gl_list_id(a_id,m_created);
if(m_gl_id && m_created) {
::glNewList(m_gl_id,GL_COMPILE);
}
#endif
}break;
case tools::sg::gsto_memory:{
m_gsto = a_id;
}break;
}
}
virtual void end_gsto() {
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
::glBindBuffer(GL_ARRAY_BUFFER,0);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
if(m_gl_id && m_created) {
::glEndList();
}
if(m_gl_id) ::glCallList(m_gl_id);
m_created = false;
m_gl_id = 0;
m_gsto = 0;
#endif
}break;
case tools::sg::gsto_memory:{
m_gsto = 0;
}break;
}
}
typedef tools::sg::bufpos bufpos;
virtual void draw_gsto_v(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_v(a_mode,a_elems,(char*)NULL+a_pos_xyzs);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
for(size_t index=0;index<a_elems;index++,pos+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
_draw_v(a_mode,a_elems,pos_xyzs);
}break;
}
}
virtual void draw_gsto_vc(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vc(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
float* pco = (float*)pos_rgbas;
for(size_t index=0;index<a_elems;index++,pos+=3,pco+=4) {
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
_draw_vc(a_mode,a_elems,pos_xyzs,pos_rgbas);
}break;
}
}
virtual void draw_gsto_vn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_nms){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_nms);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
//void* pos_nms = (char*)buffer+a_pos_nms;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
for(size_t index=0;index<a_elems;index++,pos+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_nms = (char*)buffer+a_pos_nms;
_draw_vn(a_mode,a_elems,pos_xyzs,pos_nms);
}break;
}
}
virtual void draw_gsto_vcn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas,bufpos a_pos_nms){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vcn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas,(char*)NULL+a_pos_nms);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
void* pos_nms = (char*)buffer+a_pos_nms;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
float* pco = (float*)pos_rgbas;
float* pnm = (float*)pos_nms;
for(size_t index=0;index<a_elems;
index++,pos+=3,pco+=4,pnm+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
::glNormal3f(*(pnm+0),*(pnm+1),*(pnm+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
void* pos_nms = (char*)buffer+a_pos_nms;
_draw_vcn(a_mode,a_elems,pos_xyzs,pos_rgbas,pos_nms);
}break;
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void clear_color(float a_r,float a_g,float a_b,float a_a){
::glClearColor(a_r,a_g,a_b,a_a);
::glClear(GL_COLOR_BUFFER_BIT);
}
virtual void color4f(float a_r,float a_g,float a_b,float a_a){
::glColor4f(a_r,a_g,a_b,a_a);
}
virtual void line_width(float a_v){::glLineWidth(a_v);}
virtual void point_size(float a_v){::glPointSize(a_v);}
virtual void set_polygon_offset(bool a_v) {
if(a_v) ::glEnable(GL_POLYGON_OFFSET_FILL);
else ::glDisable(GL_POLYGON_OFFSET_FILL);
::glPolygonOffset(1.,1.);
}
virtual void normal(float a_x,float a_y,float a_z) {
::glNormal3f(a_x,a_y,a_z);
}
virtual void set_winding(tools::sg::winding_type a_v) {
if(a_v==tools::sg::winding_ccw)
::glFrontFace(GL_CCW);
else
::glFrontFace(GL_CW);
}
virtual void set_shade_model(tools::sg::shade_type a_v) {
if(a_v==tools::sg::shade_smooth)
::glShadeModel(GL_SMOOTH);
else
::glShadeModel(GL_FLAT);
}
virtual void set_cull_face(bool a_on) {
if(a_on) ::glEnable(GL_CULL_FACE);
else ::glDisable(GL_CULL_FACE);
}
virtual void set_point_smooth(bool a_on) {
if(a_on) ::glEnable(GL_POINT_SMOOTH);
else ::glDisable(GL_POINT_SMOOTH);
}
virtual void set_line_smooth(bool a_on) {
if(a_on) ::glEnable(GL_LINE_SMOOTH);
else ::glDisable(GL_LINE_SMOOTH);
}
virtual void set_depth_test(bool a_on) {
if(a_on) ::glEnable(GL_DEPTH_TEST);
else ::glDisable(GL_DEPTH_TEST);
}
virtual void load_proj_matrix(const tools::mat4f& a_mtx) {
::glMatrixMode(GL_PROJECTION);
::glLoadMatrixf(a_mtx.data());
}
virtual void load_model_matrix(const tools::mat4f& a_mtx) {
::glMatrixMode(GL_MODELVIEW);
::glLoadMatrixf(a_mtx.data());
/*
tools::mat4f tmp(a_mtx);
tmp.no_translate();
tools::mat4f normal_matrix;
if(!tmp.invert(normal_matrix)) {
m_out << "toolx::WebGL::render::load_model_matrix :"
<< " can't invert model matrix."
<< std::endl;
}
normal_matrix.transpose();
tools::mat4f to_check(a_mtx);
to_check.no_translate();
float fepsilon = 1e-10;
if(!normal_matrix.equal_prec(to_check,fepsilon,tools::ffabs)) {
mat_dump(m_out,"problem with normal_matrix ",normal_matrix);
mat_dump(m_out,"expected",to_check);
}
*/
}
virtual unsigned int max_lights() {return GL_MAX_LIGHTS;}
virtual void enable_light(unsigned int a_light,
float a_dx,float a_dy,float a_dz,
float a_r,float a_g,float a_b,float a_a){
::glEnable(GL_LIGHTING);
GLenum light = GL_LIGHT0+a_light;
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
float params[4];
params[0] = -a_dx;
params[1] = -a_dy;
params[2] = -a_dz;
params[3] = 0; //0 tells that it is a directional light.
::glLightfv(light,GL_POSITION,params);
//params[0] = a_dir[0];
//params[1] = a_dir[1];
//params[2] = a_dir[2];
//::glLightfv(light,GL_SPOT_DIRECTION,params);
params[0] = a_r;
params[1] = a_g;
params[2] = a_b;
params[3] = a_a;
::glLightfv(light,GL_DIFFUSE,params);
::glLightfv(light,GL_SPECULAR,params); //coin/SoDirectionalLight does that.
params[0] = 0;
params[1] = 0;
params[2] = 0;
params[3] = 1;
::glLightfv(light,GL_AMBIENT,params); //coin/SoDirectionalLight does that.
// coin/SoDirectionalLight does the below :
::glLightf(light, GL_SPOT_EXPONENT, 0.0);
::glLightf(light, GL_SPOT_CUTOFF, 180.0);
::glLightf(light, GL_CONSTANT_ATTENUATION, 1);
::glLightf(light, GL_LINEAR_ATTENUATION, 0);
::glLightf(light, GL_QUADRATIC_ATTENUATION, 0);
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
::glEnable(light);
}
virtual void set_lighting(bool a_on) {
if(a_on) ::glEnable(GL_LIGHTING);
else ::glDisable(GL_LIGHTING);
}
virtual void set_blend(bool a_on) {
if(a_on) ::glEnable(GL_BLEND);
else ::glDisable(GL_BLEND);
}
virtual void restore_state(unsigned int a_ret_num_light) {
const tools::sg::state& _state = state();
::glMatrixMode(GL_PROJECTION);
::glLoadMatrixf(_state.m_proj.data());
::glMatrixMode(GL_MODELVIEW);
::glLoadMatrixf(_state.m_model.data());
if(_state.m_GL_LIGHTING) ::glEnable(GL_LIGHTING);
else ::glDisable(GL_LIGHTING);
if(_state.m_GL_DEPTH_TEST) ::glEnable(GL_DEPTH_TEST);
else ::glDisable(GL_DEPTH_TEST);
if(_state.m_GL_CULL_FACE) ::glEnable(GL_CULL_FACE);
else ::glDisable(GL_CULL_FACE);
if(_state.m_GL_POINT_SMOOTH) ::glEnable(GL_POINT_SMOOTH);
else ::glDisable(GL_POINT_SMOOTH);
if(_state.m_GL_LINE_SMOOTH) ::glEnable(GL_LINE_SMOOTH);
else ::glDisable(GL_LINE_SMOOTH);
if(_state.m_GL_POLYGON_OFFSET_FILL) ::glEnable(GL_POLYGON_OFFSET_FILL);
else ::glDisable(GL_POLYGON_OFFSET_FILL);
if(_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
else ::glDisable(GL_TEXTURE_2D);
if(_state.m_GL_BLEND) ::glEnable(GL_BLEND);
else ::glDisable(GL_BLEND);
if(_state.m_winding==tools::sg::winding_ccw) {
::glFrontFace(GL_CCW);
} else {
::glFrontFace(GL_CW);
}
if(_state.m_shade_model==tools::sg::shade_smooth)
::glShadeModel(GL_SMOOTH);
else
::glShadeModel(GL_FLAT);
::glColor4f(_state.m_color.r(),
_state.m_color.g(),
_state.m_color.b(),
_state.m_color.a());
::glNormal3f(_state.m_normal.x(),
_state.m_normal.y(),
_state.m_normal.z());
// 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=_state.m_light;index<a_ret_num_light;index++) {
::glDisable(GL_LIGHT0+index);
}
::glLineWidth(_state.m_line_width);
::glPointSize(_state.m_point_size);
#if TARGET_OS_IPHONE
// GL-ES
#elif defined(ANDROID)
// GL-ES
#else
::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
#endif
}
virtual tools::sg::render_manager& render_manager() {return m_mgr;}
public:
GL_action(GL_manager& a_mgr,std::ostream& a_out,unsigned int a_ww,unsigned int a_wh)
:parent(a_out,a_ww,a_wh)
,m_mgr(a_mgr)
,m_gsto(0)
#ifdef TOOLX_HAS_GL_LIST
,m_created(false)
,m_gl_id(0)
#endif
{}
virtual ~GL_action(){}
public:
GL_action(const GL_action& a_from)
:parent(a_from)
,m_mgr(a_from.m_mgr)
,m_gsto(0)
#ifdef TOOLX_HAS_GL_LIST
,m_created(false)
,m_gl_id(0)
#endif
{}
GL_action& operator=(const GL_action& a_from){
render_action::operator=(a_from);
m_gsto = 0;
#ifdef TOOLX_HAS_GL_LIST
m_created = false;
m_gl_id = 0;
#endif
return *this;
}
protected:
void _draw_v(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs){
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vc(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_COLOR_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_nms){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vcn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas,const void* a_pos_nms){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_COLOR_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
protected:
GL_manager& m_mgr;
gstoid m_gsto;
#ifdef TOOLX_HAS_GL_LIST
bool m_created;
gstoid m_gl_id;
#endif
};
}}
#endif
+696
View File
@@ -0,0 +1,696 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_manager
#define toolx_sg_GL_manager
#include "gl"
#include "../glbuf"
#include <tools/sg/render_manager>
#include <tools/mapmanip>
#include <tools/carray>
#include <cmath> //::sqrt
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
namespace toolx {
namespace sg {
class GL_manager : public virtual tools::sg::render_manager {
typedef tools::sg::render_manager parent;
public:
TOOLS_SCLASS(toolx::sg::GL_manager)
virtual void* cast(const std::string& a_class) const {
if(void* p = tools::cmp_cast<GL_manager>(this,a_class)) {return p;}
else return 0;
}
public:
virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh,
float a_r,float a_g,float a_b,float a_a,bool a_clear = true) {
gl_clear_errors();
#if TARGET_OS_IPHONE
#elif defined(ANDROID)
#elif _WIN32
#elif __APPLE__ // Cocoa
// to avoid a 0x506 error message :
#ifdef TOOLX_HAS_GL_VBO
#if GL_ARB_framebuffer_object
if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
//m_out << "toolx::sg::GL_manager::begin_render :"
// << " frame buffer not complete."
// << std::endl;
return false;
}
#endif //GL_ARB_framebuffer_object
#endif //TOOLX_HAS_GL_VBO
#else
#endif
// WARNING : the values set here must match the default values in sg::state.
// Antialiasing :
#if TARGET_OS_IPHONE
#elif defined(ANDROID)
::glEnable(GL_MULTISAMPLE);
#elif _WIN32
#elif __APPLE__
::glEnable(GL_MULTISAMPLE); //Cocoa
#else
#endif
/* NOTE : not GL-ES :
// ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
// The upper is cruely lacking with povama solid+light.
// ::glEnable(GL_LINE_STIPPLE);
::glDisable(GL_POLYGON_SMOOTH);
::glAccum(GL_LOAD,1.0f);
::glAccum(GL_RETURN,1.0f);
::glReadBuffer(GL_FRONT);
NOTE : GL_POLYGON_SMOOTH is here on Cocoa/AGL, Windows/WGL but it
does nothing.
*/
#if TARGET_OS_IPHONE
// GL-ES
#elif defined(ANDROID)
// GL-ES
#else
::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
#endif
/*
::printf("debug : is enabled %d\n",::glIsEnabled(GL_COLOR_MATERIAL));
{GLfloat v[4];
::glGetMaterialfv(GL_FRONT,GL_AMBIENT,v);
::printf("debug : ambient : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
{GLfloat v[4];
::glGetMaterialfv(GL_FRONT,GL_DIFFUSE,v);
::printf("debug : diffuse : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
{GLfloat v[4];
::glGetMaterialfv(GL_FRONT,GL_SPECULAR,v);
::printf("debug : specular : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
{GLfloat v[4];
::glGetMaterialfv(GL_FRONT,GL_EMISSION,v);
::printf("debug : emission : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
{GLfloat shine;
::glGetMaterialfv(GL_FRONT,GL_SHININESS,&shine);
::printf("debug : shine : %g\n",shine);}
debug : is enabled 0
debug : ambient : 0.2 0.2 0.2 1
debug : diffuse : 0.8 0.8 0.8 1
debug : specular : 0 0 0 1
debug : emission : 0 0 0 1
debug : shine : 0
*/
::glEnable(GL_NORMALIZE);
::glShadeModel(GL_FLAT);
//::glShadeModel(GL_SMOOTH);
// GL-ES : ::glMaterialfv does not work. We then use :
// ::glEnable(GL_COLOR_MATERIAL) and ::glColor.
//::glColorMaterial(GL_FRONT, GL_DIFFUSE); //?
::glEnable(GL_COLOR_MATERIAL);
/*
debug : is enabled 1
debug : ambient : 1 1 1 1
debug : diffuse : 1 1 1 1
debug : specular : 0 0 0 1
debug : emission : 0 0 0 1
debug : shine : 0
*/
// to handle transparency (same as SoGLRenderAction::SCREEN_DOOR ?) :
//::glEnable(GL_BLEND);
// NOTE : with Cocoa+AppleGL on macOS-10.14 (Mojave), it appears that points are blended ! (Even if alpha color is 1).
// Seen with some simulated catalog of galaxies done for LSST/DC2.
// To master this, we disable GL_BLEND by default. Then people wanting some transparency have to
// use the tools::sg::blend node in their scene graph.
::glDisable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
::glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//WARNING : the below glEnable/glDisable corresponds
// to defaults in tools::sg::state.
::glEnable(GL_DEPTH_TEST);
::glDisable(GL_LIGHTING);
::glFrontFace(GL_CCW);
::glEnable(GL_CULL_FACE);
::glDisable(GL_POLYGON_OFFSET_FILL);
::glDisable(GL_TEXTURE_2D);
::glDisable(GL_POINT_SMOOTH);
::glPointSize(1);
::glDisable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms !
::glLineWidth(1);
::glViewport(a_x,a_y,a_ww,a_wh);
// NOTE : iOS : glScissor logic does not work properly with Apple multisampling.
// But it appears that it is not needed for VR split views.
// Here a combination glViewport+[correct camera lrbt] does the clipping job (???).
// (But the clear color should be the same for both views).
//::glEnable(GL_SCISSOR_TEST);
//::glScissor(a_x,a_y,a_ww,a_wh);
//NOTE : a=0 coworks with the below logic to handle transparent background.
if(a_clear) {
::glClearColor(a_r,a_g,a_b,0);
::glClear(GL_COLOR_BUFFER_BIT);
::glClear(GL_DEPTH_BUFFER_BIT);
}
//WARNING : Android, iPhone : only one glPushMatrix ok !
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
//WARNING : we take the convention that the current mode is MODELVIEW
::glMatrixMode(GL_MODELVIEW);
::glLoadIdentity();
//m_clear_color.set_a(0.2);
// to handle a transparent background :
//NOTE : not tested on Android and iOS.
// dst color :
// cr * alpha + cr * (1-alpha) = cr
// cg * alpha + cg * (1-alpha) = cg
// cb * alpha + cb * (1-alpha) = cb
// alpha*alpha + 0 * (1-alpha) = ca => alpha = sqrt(ca)
{::glColor4f(a_r,a_g,a_b,::sqrt(a_a));
float xyzs[12];
xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0;
xyzs[3] = 1;xyzs[ 4] = -1;xyzs[ 5] = 0;
xyzs[6] = 1;xyzs[ 7] = 1;xyzs[ 8] = 0;
xyzs[9] = -1;xyzs[10] = 1;xyzs[11] = 0;
::glDisable(GL_DEPTH_TEST);
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,xyzs);
::glDrawArrays(GL_TRIANGLE_FAN,0,4);
::glDisableClientState(GL_VERTEX_ARRAY);
::glEnable(GL_DEPTH_TEST);}
return true;
}
virtual void end_render() {
::glFinish();
gl_dump_if_errors(m_out,"toolx::sg::GL_manager::end_render :");
}
////////////////////////////////////////////////
/// texture : //////////////////////////////////
////////////////////////////////////////////////
virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) {
unsigned int gl_id;
::glGenTextures(1,&gl_id);
if(!gl_id) return 0;
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_tex().c_str());
#endif
unsigned int gsto_size = a_img.size();
::glBindTexture(GL_TEXTURE_2D,gl_id);
bool status = true;
{int sz;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE,&sz);
// MacBookPro : it returns 8192.
// Android : it returns 2048.
// iPad1 : it returns 2048.
// iPod : it returns ?
//::printf("debug : GL_MAX_TEXTURE_SIZE : %d\n",sz);
tools::img_byte res;
if(!sz) {
m_out << "toolx::sg::gl::tex_img : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl;
status = gl_tex_img(m_out,a_img);
} else {
if(a_img.check_gl_limit(sz,res)) {
if(res.is_empty()) { //a_img does not exceed.
status = gl_tex_img(m_out,a_img);
} else {
m_out << "toolx::sg::gl::tex_img : warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ")." << std::endl;
status = gl_tex_img(m_out,res);
gsto_size = res.size();
}
} else {
m_out << "toolx::sg::gl::tex_img :"
<< " warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce."
<< std::endl;
status = false;
}}}
if(a_NEAREST) {
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels.
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem.
} else {
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
::glBindTexture(GL_TEXTURE_2D,0);
if(!status) {
gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (1) :");
::glDeleteTextures(1,&gl_id);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_tex().c_str());
#endif
gl_id = 0;
gl_clear_errors();
return 0;
}
if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (2) :")) {
::glDeleteTextures(1,&gl_id);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_tex().c_str());
#endif
gl_id = 0;
gl_clear_errors();
return 0;
}
unsigned int _id = m_gen_id;m_gen_id++;
m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0);
return _id;
}
////////////////////////////////////////////////
/// VBO ////////////////////////////////////////
////////////////////////////////////////////////
virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) {
if(!a_floatn) return 0;
switch(m_gsto_mode) {
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
unsigned int gl_id = 0;
::glGenBuffers(1,&gl_id);
if(!gl_id) {
if(!m_warned) {
m_warned = true;
m_out << "toolx::sg::GL_manager::create_gsto_from_data : glGenBuffers failed ()." << std::endl;
}
return 0;
}
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_gsto().c_str());
#endif
::glBindBuffer(GL_ARRAY_BUFFER,gl_id);
::glBufferData(GL_ARRAY_BUFFER,
a_floatn*sizeof(float),a_data,
GL_STATIC_DRAW);
::glBindBuffer(GL_ARRAY_BUFFER,0);
if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_gsto_from_data :")) {
::glDeleteBuffers(1,&gl_id);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_gsto().c_str());
#endif
gl_id = 0;
gl_clear_errors();
return 0;
}
unsigned int _id = m_gen_id;m_gen_id++;
m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0);
return _id;
#else //!TOOLX_HAS_GL_VBO
m_out << "toolx::sg::GL_manager::create_gsto_from_data :"
<< " gsto mode is gl_vbo but class not compiled with TOOLX_HAS_GL_VBO."
<< std::endl;
return 0;
#endif //TOOLX_HAS_GL_VBO
}break;
case tools::sg::gsto_gl_list:{
unsigned int gl_id = 0;
unsigned int _id = m_gen_id;m_gen_id++;
m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data);
return _id;
}break;
case tools::sg::gsto_memory:{
unsigned int gl_id = 0;
unsigned int _id = m_gen_id;m_gen_id++;
m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data);
return _id;
}break;
}
return 0;
}
virtual bool is_gsto_id_valid(unsigned int a_id) const {
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
if(it==m_gstos.end()) return false;
return (*it).second->is_valid();
}
virtual void delete_gsto(unsigned int a_id){
tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id);
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
float* gsto_data(unsigned int a_id) const {
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
if(it==m_gstos.end()) return 0;
return (*it).second->m_data;
}
unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) const {
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
if(it==m_gstos.end()) {a_created = false;return 0;}
if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;}
if((*it).second->m_gl_id) {
a_created = false;
return (*it).second->m_gl_id;
} else {
#ifdef TOOLX_HAS_GL_LIST
unsigned int _id = ::glGenLists(1);
if(!_id) {a_created = false;return 0;}
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_gsto().c_str());
#endif
a_created = true;
(*it).second->m_gl_id = _id;
return _id;
#else
a_created = false;
return 0;
#endif
}
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;}
virtual void set_gsto_mode(tools::sg::gsto_mode a_v) {
if(a_v==m_gsto_mode) return;
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
switch(a_v) {
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
m_gsto_mode = a_v;
#else
m_gsto_mode = tools::sg::gsto_memory;
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
m_gsto_mode = a_v;
#else
m_gsto_mode = tools::sg::gsto_memory;
#endif
}break;
case tools::sg::gsto_memory:{
m_gsto_mode = tools::sg::gsto_memory;
}break;
}
}
virtual void available_gsto_modes(std::vector<std::string>& a_vs) {
a_vs.clear();
#ifdef TOOLX_HAS_GL_VBO
a_vs.push_back(tools::sg::s_gsto_gl_vbo());
#endif
#ifdef TOOLX_HAS_GL_LIST
a_vs.push_back(tools::sg::s_gsto_gl_list());
#endif
a_vs.push_back(tools::sg::s_gsto_memory());
}
virtual void available_not_memory_gsto_mode(std::string& a_v) const {
a_v.clear();
#ifdef TOOLX_HAS_GL_VBO
a_v = tools::sg::s_gsto_gl_vbo();
#endif
#ifdef TOOLX_HAS_GL_LIST
if(a_v.empty()) a_v = tools::sg::s_gsto_gl_list();
#endif
}
virtual size_t used_texture_memory() const {
size_t sz = 0;
std::map<unsigned int,gsto_t*>::const_iterator it;
for(it=m_gstos.begin();it!=m_gstos.end();++it) {
if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size;
}
return sz;
}
virtual size_t gstos_size() const {
size_t sz = 0;
std::map<unsigned int,gsto_t*>::const_iterator it;
for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size;
return sz;
}
public:
GL_manager(std::ostream& a_out)
:m_out(a_out)
,m_gen_id(1)
#ifdef TOOLX_HAS_GL_VBO
,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs.
#elif TOOLX_HAS_GL_LIST
,m_gsto_mode(tools::sg::gsto_gl_list)
#else
,m_gsto_mode(tools::sg::gsto_memory)
#endif
,m_warned(false)
{}
virtual ~GL_manager(){
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
}
public:
GL_manager(const GL_manager& a_from)
:parent(a_from)
,m_out(a_from.m_out)
,m_gen_id(a_from.m_gen_id)
,m_gsto_mode(a_from.m_gsto_mode)
,m_warned(false)
{}
GL_manager& operator=(const GL_manager& a_from){
if(&a_from==this) return *this;
m_gen_id = a_from.m_gen_id;
m_gsto_mode = a_from.m_gsto_mode;
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
m_warned = false;
return *this;
}
public:
void bind_gsto(unsigned int a_id) {
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
if(it==m_gstos.end()) return;
(*it).second->bind();
}
void delete_gstos() {
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
}
public:
static unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) {
//WARNING : it does OpenGL. Under Android it should be executed
// in the OpenGL thread.
//NOTE : Android, iOS : RGB produces a black image.
unsigned char* rgbas = new unsigned char[4 * a_w * a_h];
if(!rgbas) return 0;
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
::glReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas);
/*{size_t number = 4 * a_w * a_h;
size_t count_not_255 = 0;
for(size_t item=3;item<number;item+=4) {
unsigned char a = rgbas[item];
if(a!=255) {
::printf("%lu : %d\n",item,a);
count_not_255++;
rgbas[item] = 255;
}
}
::printf("not_255 : %lu\n",count_not_255);}*/
return rgbas;
}
#if defined(TARGET_OS_IPHONE) || defined(ANDROID)
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
unsigned char* rgbas = get_rgbas(a_w,a_h);
if(!rgbas) return 0;
unsigned char* rgbs = tools::_4s_to_3s<unsigned char,unsigned int>(rgbas,a_w,a_h);
delete [] rgbas;
return rgbs;
}
#else
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
//WARNING : it does OpenGL. Under Android it should be executed
// in the OpenGL thread.
//NOTE : Android, iOS : RGB produces a black image.
unsigned char* rgbs = new unsigned char[3 * a_w * a_h];
if(!rgbs) return 0;
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
::glReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs);
return rgbs;
}
#endif
protected:
std::ostream& m_out;
class gsto_t {
TOOLS_SCLASS(GL_manager::gsto_t)
public:
enum kind {
kind_texture,
kind_buffer,
kind_list,
kind_memory
};
public:
gsto_t(kind a_kind,int a_gl_id,size_t a_size,const float* a_data)
:m_gl_id(a_gl_id)
,m_kind(a_kind)
,m_size(a_size)
,m_data(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
if(a_data) {
size_t num = m_size/sizeof(float);
m_data = new float[num];
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_new().c_str());
#endif
::memcpy(m_data,a_data,m_size);
}
}
virtual ~gsto_t() {
if(m_kind==kind_texture) {
::glDeleteTextures(1,&m_gl_id);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_tex().c_str());
#endif
} else if(m_kind==kind_buffer) {
#ifdef TOOLX_HAS_GL_VBO
::glDeleteBuffers(1,&m_gl_id);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_gsto().c_str());
#endif
#endif
} else if(m_kind==kind_list) {
if(m_gl_id) {
#ifdef TOOLX_HAS_GL_LIST
::glDeleteLists(m_gl_id,1);
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_gsto().c_str());
#endif
#endif
}
}
if(m_data) {
delete [] m_data;
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_new().c_str());
#endif
}
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
private:
gsto_t(const gsto_t& a_from)
:m_gl_id(a_from.m_gl_id)
,m_kind(a_from.m_kind)
,m_size(a_from.m_size)
,m_data(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
if(a_from.m_data) {
size_t num = m_size/sizeof(float);
m_data = new float[num];
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_new().c_str());
#endif
::memcpy(m_data,a_from.m_data,m_size);
}
}
gsto_t& operator=(const gsto_t& a_from){
if(&a_from==this) return *this;
m_gl_id = a_from.m_gl_id;
m_kind = a_from.m_kind;
m_size = a_from.m_size;
if(m_data) {
delete [] m_data;
#ifdef TOOLS_MEM
tools::mem::decrement(tools::s_new().c_str());
#endif
m_data = 0;
}
if(a_from.m_data) {
size_t num = m_size/sizeof(float);
m_data = new float[num];
#ifdef TOOLS_MEM
tools::mem::increment(tools::s_new().c_str());
#endif
::memcpy(m_data,a_from.m_data,m_size);
}
return *this;
}
public:
bool is_valid() const {
if(m_kind==kind_texture) {
return (::glIsTexture(m_gl_id)==GL_TRUE?true:false);
} else if(m_kind==kind_buffer) {
#ifdef TOOLX_HAS_GL_VBO
return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false);
#endif
} else if(m_kind==kind_list) {
#ifdef TOOLX_HAS_GL_LIST
return (::glIsList(m_gl_id)==GL_TRUE?true:false);
#endif
} else if(m_kind==kind_memory) {
return true;
}
return false;
}
void bind() const {
if(m_kind==kind_texture) {
::glBindTexture(GL_TEXTURE_2D,m_gl_id);
} else if(m_kind==kind_buffer) {
#ifdef TOOLX_HAS_GL_VBO
::glBindBuffer(GL_ARRAY_BUFFER,m_gl_id);
#endif
}
}
public:
unsigned int m_gl_id;
kind m_kind;
size_t m_size;
float* m_data;
};
std::map<unsigned int,gsto_t*> m_gstos;
bool m_gsto_on_card;
unsigned int m_gen_id;
tools::sg::gsto_mode m_gsto_mode;
bool m_warned;
};
}}
#endif
+78
View File
@@ -0,0 +1,78 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_viewer
#define toolx_sg_GL_viewer
#include <tools/sg/viewer>
#include "GL_manager"
#include "GL_action"
namespace toolx {
namespace sg {
class GL_viewer : public tools::sg::viewer {
TOOLS_HEADER(GL_viewer,toolx::sg::GL_viewer,tools::sg::viewer)
public:
void render() {
if(!m_ww) return;
if(!m_wh) return;
m_gl_mgr.begin_render(0,0,m_ww,m_wh,
m_clear_color.r(),
m_clear_color.g(),
m_clear_color.b(),
m_clear_color.a());
GL_action action(m_gl_mgr,m_out,m_ww,m_wh);
action.state().m_use_gsto = m_use_gsto;
action.set_do_transparency(false);
action.set_have_to_do_transparency(false);
m_sg.render(action);
if(!action.end()) { //check that matrices stack are ok.
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
} else {
if(action.have_to_do_transparency()) {
action.set_do_transparency(true);
m_sg.render(action);
if(!action.end()) { //check that matrices stack are ok.
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
}
}
}
//after_render();
m_gl_mgr.end_render();
}
public:
GL_viewer(std::ostream& a_out,unsigned int a_width,unsigned int a_height)
:parent(a_out,a_width,a_height)
,m_gl_mgr(a_out)
{}
virtual ~GL_viewer(){
//WARNING : nodes may refer m_gl_mgr (to handle gstos/texs), then
// we have to delete them first.
m_sg.clear();
}
public:
GL_viewer(const GL_viewer& a_from)
:parent(a_from)
,m_gl_mgr(a_from.m_gl_mgr)
{}
GL_viewer& operator=(const GL_viewer& a_from){
parent::operator=(a_from);
m_gl_mgr = a_from.m_gl_mgr;
return *this;
}
protected:
GL_manager m_gl_mgr;
};
}}
#endif
+110
View File
@@ -0,0 +1,110 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_gl
#define toolx_sg_gl
#include "../OpenGL"
#include <tools/platform> //for APPLE TargetConditionals.h
#include <tools/img>
#include <ostream>
namespace toolx {
namespace sg {
//namespace gl : no, problem with g4tools.
inline void gl_clear_errors() {
GLenum glerror = ::glGetError();
while(glerror!=GL_NO_ERROR) {
glerror = ::glGetError();
}
}
inline bool gl_dump_if_errors(std::ostream& a_out,const std::string& a_head) {
bool retval = false;
GLenum glerror = ::glGetError();
if(glerror!=GL_NO_ERROR) {
a_out << a_head
<< " we have gl errors :"
<< std::endl;
retval = true;
}
while(glerror!=GL_NO_ERROR) {
//#define GL_NO_ERROR 0
//#define GL_INVALID_ENUM 0x0500
//#define GL_INVALID_VALUE 0x0501
//#define GL_INVALID_OPERATION 0x0502
//#define GL_STACK_OVERFLOW 0x0503
//#define GL_STACK_UNDERFLOW 0x0504
//#define GL_OUT_OF_MEMORY 0x0505
//#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
a_out << "0x" << std::hex << glerror << std::endl;
glerror = ::glGetError();
}
return retval;
}
inline void gl_dump_infos(std::ostream& a_out) {
std::string gl_version;
{const char* _sv = (const char*)::glGetString(GL_VERSION);
if(_sv) gl_version = _sv;}
std::string gl_vendor;
{const char* _sv = (const char*)::glGetString(GL_VENDOR);
if(_sv) gl_vendor = _sv;}
std::string gl_renderer;
{const char* _sv = (const char*)::glGetString(GL_RENDERER);
if(_sv) gl_renderer = _sv;}
std::string gl_extensions;
{const char* _sv = (const char*)::glGetString(GL_EXTENSIONS);
if(_sv) gl_extensions = _sv;}
GLint gl_texture_size;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_texture_size);
//GLint gl_buffer_size;
//::glGetIntegerv(GL_BUFFER_SIZE, &gl_buffer_size);
a_out << "toolx::sg::gl::dump_infos :" << std::endl;
a_out << " GL_VERSION " << gl_version << std::endl;
a_out << " GL_VENDOR " << gl_vendor << std::endl;
a_out << " GL_RENDERER " << gl_renderer << std::endl;
a_out << " GL_EXTENSIONS " << gl_extensions << std::endl;
a_out << " GL_MAX_TEXTURE_SIZE " << gl_texture_size << std::endl;
//a_out << " GL_BUFFER_SIZE " << gl_buffer_size << std::endl;
}
inline bool gl_tex_img(std::ostream& a_out,const tools::img_byte& a_img) {
if(a_img.bpp()==1) {
//to pass eiffel-tower.png
#if defined(ANDROID) || TARGET_OS_IPHONE
tools::img_byte res;
if(!a_img.bw2x(3,res)) {
a_out << "toolx::sg::gl::tex_img : toolx::img.bw2x() failed." << std::endl;
return false;
}
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,res.width(),res.height(),0,GL_RGB,GL_UNSIGNED_BYTE,res.buffer());
#else
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_LUMINANCE,GL_UNSIGNED_BYTE,a_img.buffer());
#endif
} else if(a_img.bpp()==3) {
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_RGB,GL_UNSIGNED_BYTE,a_img.buffer());
} else if(a_img.bpp()==4) {
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,a_img.width(),a_img.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,a_img.buffer());
} else {
a_out << "toolx::sg::gl::tex_img : img.bpp() " << a_img.bpp() << " not treated." << std::endl;
return false;
}
return true;
}
}}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_text_freetype_marker
#define toolx_sg_text_freetype_marker
#include "text_freetype"
namespace toolx {
namespace sg {
class text_freetype_marker : public text_freetype {
TOOLS_NODE(text_freetype_marker,toolx::sg::text_freetype_marker,text_freetype)
public:
virtual bool draw_in_frame_buffer() const {return true;}
virtual void render(tools::sg::render_action& a_action) {
{bool _color_touched = color_touched(a_action.state());
bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_color_touched||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
const tools::sg::state& state = a_action.state();
a_action.set_lighting(false); //Same logic as Inventor SoLightModel.model = BASE_COLOR.
a_action.set_depth_test(false);
if(m_wndg==wndg_ccw) a_action.set_winding(tools::sg::winding_ccw);
else if(m_wndg==wndg_cw) a_action.set_winding(tools::sg::winding_cw);
float x,y,z;
a_action.projected_origin(x,y,z);
float zz = 0;
a_action.load_matrices_to_identity();
{tools::mat4f _mtx;
_mtx.set_translate(x,y,zz);
if(!m_bitmaps.size()) {
if(state.m_ww) _mtx.mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
}
a_action.load_model_matrix(_mtx);}
///////////////////////////////////////////////////////////
/// lines /////////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t pos = item.first;
size_t num = item.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
a_action.draw_vertex_array_xy(tools::gl::line_strip(),num*2,data);
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t pos = item.second.first;
size_t num = item.second.second;
if(!num) continue;
//a_out << "toolx::sg::text_freetype_marker::render :"
// << " num points " << num
// << std::endl;
const float* data = tools::vec_data<float>(m_xys)+pos;
a_action.draw_vertex_array_xy((*it).first,num*2,data);
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
if(m_bitmaps.size()) {
#if defined(ANDROID) /*|| TARGET_OS_IPHONE*/
// we do not have transparent texture here (see also gl/tex_img() that does img/4-bytes => img/3-bytes) :
{tools::sg::state& _state = a_action.state();
tools::colorf old_color = _state.m_color;
_state.m_color = tools::colorf_white();
a_action.color4f(_state.m_color);
m_bitmaps.render(a_action);
_state.m_color = old_color;
a_action.color4f(_state.m_color);}
#else
m_bitmaps.render(a_action);
#endif
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
a_action.load_matrices_from_state();
a_action.set_depth_test(state.m_GL_DEPTH_TEST);
a_action.set_lighting(state.m_GL_LIGHTING);
a_action.set_winding(state.m_winding);
}
virtual void pick(tools::sg::pick_action& a_action) {
const tools::sg::state& state = a_action.state();
{bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
float x,y,z;
a_action.projected_origin(x,y,z);
float zz = 0;
a_action.set_matrices_to_identity();
a_action.model_matrix().set_translate(x,y,zz);
if(!m_bitmaps.size()) {
if(state.m_ww) a_action.model_matrix().mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
}
///////////////////////////////////////////////////////////
/// lines /////////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t pos = item.first;
size_t num = item.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
float* vp = _trans2(num,data,x,y);
if(!vp) continue;
if(a_action.add__line_strip_xy(*this,2*num,vp,true)) {
delete [] vp;
a_action.set_matrices_from_state();
return;
}
delete [] vp;
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t pos = item.second.first;
size_t num = item.second.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
float* vp = _trans2(num,data,x,y);
if(!vp) continue;
if(a_action.add__primitive_xy(*this,item.first,2*num,vp,true)){
delete [] vp;
a_action.set_matrices_from_state();
return;
}
delete [] vp;
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
if(m_bitmaps.size()) {
m_bitmaps.pick(a_action);
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
a_action.set_matrices_from_state();
}
virtual void bbox(tools::sg::bbox_action& a_action) {
{bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
a_action.add_one_point(0,0,0);
/*
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t num = item.second;
const float* data = tools::vec_data<float>(m_xys)+item.first;
float px,py,pz;
float* pos = (float*)data;
for(size_t index=0;index<num;index++) {
px = *pos;pos++;
py = *pos;pos++;
pz = 0;
a_action.add_one_point(px,py,pz);
}
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t num = item.second.second;
const float* data = tools::vec_data<float>(m_xys)+item.second.first;
float px,py,pz;
float* pos = (float*)data;
for(size_t index=0;index<num;index++) {
px = *pos;pos++;
py = *pos;pos++;
pz = 0;
a_action.add_one_point(px,py,pz);
}
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
m_bitmaps.bbox(a_action);
*/
}
public:
text_freetype_marker():parent(){
height = 10; //pixels
}
virtual ~text_freetype_marker(){}
public:
text_freetype_marker(const text_freetype_marker& a_from):parent(a_from) {}
text_freetype_marker& operator=(const text_freetype_marker& a_from){parent::operator=(a_from);return *this;}
protected:
void update_sg(std::ostream& a_out,bool a_load_font,const tools::sg::state& a_state) {
if(!a_state.m_wh) {parent::update_sg(a_out,a_load_font);return;}
float sy = 2.0f*float(height.value())/float(a_state.m_wh); //in [-1,1]
float old_height = height.value();
height.value_no_cmp(sy);
//update_what what = lines;
//if(modeling==tools::sg::font_filled) what = faces_and_lines;
parent::update_sg(a_out,a_load_font);
height.value_no_cmp(old_height);
}
float* _trans2(size_t a_num,const float* a_data,float a_x,float a_y) {
float* vp = new float[a_num*2];
if(!vp) return 0;
float* pos = vp;
float* pda = (float*)a_data;
for(size_t index=0;index<a_num;index++){
*pos = *pda + a_x;pos++;pda++;
*pos = *pda + a_y;pos++;pda++;
}
return vp;
}
};
}}
#endif