Import Geant4 11.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2022-12-09 14:43:28 +01:00
parent c07cea1fe0
commit 9f34590941
3810 changed files with 200490 additions and 182326 deletions
+29 -2
View File
@@ -29,6 +29,32 @@ public:
return *this;
}
public:
colorf& operator*=(const colorf& a_v) {
m_data[0] *= a_v.m_data[0];
m_data[1] *= a_v.m_data[1];
m_data[2] *= a_v.m_data[2];
m_data[3] *= a_v.m_data[3];
return *this;
}
colorf& operator*=(float a_v) {
m_data[0] *= a_v;
m_data[1] *= a_v;
m_data[2] *= a_v;
m_data[3] *= a_v;
return *this;
}
public:
void clamp(float a_min = 0,float a_max = 1) {
if(m_data[0]<a_min) m_data[0] = a_min;
if(m_data[1]<a_min) m_data[1] = a_min;
if(m_data[2]<a_min) m_data[2] = a_min;
if(m_data[3]<a_min) m_data[3] = a_min;
if(a_max<m_data[0]) m_data[0] = a_max;
if(a_max<m_data[1]) m_data[1] = a_max;
if(a_max<m_data[2]) m_data[2] = a_max;
if(a_max<m_data[3]) m_data[3] = a_max;
}
float r() const {return v0();}
float g() const {return v1();}
float b() const {return v2();}
@@ -155,10 +181,11 @@ struct cmp_colorf {
}
};
//default color is lightgrey:
#if defined(TOOLS_MEM) && !defined(TOOLS_MEM_ATEXIT)
inline const colorf& colorf_default() {static const colorf s_v(0.8f,0.8f,0.8f,1,false);return s_v;}
inline const colorf& colorf_default() {static const colorf s_v(0.824231F,0.824231F,0.824231F,1,false);return s_v;}
#else
inline const colorf& colorf_default() {static const colorf s_v(0.8f,0.8f,0.8f,1);return s_v;}
inline const colorf& colorf_default() {static const colorf s_v(0.824231F,0.824231F,0.824231F,1);return s_v;}
#endif
}
+134
View File
@@ -0,0 +1,134 @@
#ifndef tools_fpng
#define tools_fpng
// G.Barrand: pure header version of fpng found at https://github.com/richgel999/fpng
// The original namespace fpng had been changed to tools::fpng to avoid
// clashes with potential other usage of fpng within the same software.
// fpng.h - unlicense (see end of fpng.cpp)
#include <stdlib.h>
#include <stdint.h>
#include <vector>
namespace tools {
namespace fpng
{
// Fast CRC-32 SSE4.1+pclmul or a scalar fallback (slice by 4)
const uint32_t FPNG_CRC32_INIT = 0;
uint32_t fpng_crc32(const void* pData, size_t size, uint32_t prev_crc32 = FPNG_CRC32_INIT);
// Fast Adler32 SSE4.1 Adler-32 with a scalar fallback.
const uint32_t FPNG_ADLER32_INIT = 1;
uint32_t fpng_adler32(const void* pData, size_t size, uint32_t adler = FPNG_ADLER32_INIT);
// ---- Compression
enum
{
// Enables computing custom Huffman tables for each file, instead of using the custom global tables.
// Results in roughly 6% smaller files on average, but compression is around 40% slower.
FPNG_ENCODE_SLOWER = 1,
// Only use raw Deflate blocks (no compression at all). Intended for testing.
FPNG_FORCE_UNCOMPRESSED = 2,
};
// Fast PNG encoding. The resulting file can be decoded either using a standard PNG decoder or by the fpng_decode_memory() function below.
// pImage: pointer to RGB or RGBA image pixels, R first in memory, B/A last.
// w/h - image dimensions. Image's row pitch in bytes must is w*num_chans.
// num_chans must be 3 or 4.
bool fpng_encode_image_to_memory(const void* pImage, uint32_t w, uint32_t h, uint32_t num_chans, std::vector<uint8_t>& out_buf, uint32_t flags = 0);
// Fast PNG encoding to the specified file.
bool fpng_encode_image_to_file(const char* pFilename, const void* pImage, uint32_t w, uint32_t h, uint32_t num_chans, uint32_t flags = 0);
// ---- Decompression
enum
{
FPNG_DECODE_SUCCESS = 0, // file is a valid PNG file and written by FPNG and the decode succeeded
FPNG_DECODE_NOT_FPNG, // file is a valid PNG file, but it wasn't written by FPNG so you should try decoding it with a general purpose PNG decoder
FPNG_DECODE_INVALID_ARG, // invalid function parameter
FPNG_DECODE_FAILED_NOT_PNG, // file cannot be a PNG file
FPNG_DECODE_FAILED_HEADER_CRC32, // a chunk CRC32 check failed, file is likely corrupted or not PNG
FPNG_DECODE_FAILED_INVALID_DIMENSIONS, // invalid image dimensions in IHDR chunk (0 or too large)
FPNG_DECODE_FAILED_DIMENSIONS_TOO_LARGE, // decoding the file fully into memory would likely require too much memory (only on 32bpp builds)
FPNG_DECODE_FAILED_CHUNK_PARSING, // failed while parsing the chunk headers, or file is corrupted
FPNG_DECODE_FAILED_INVALID_IDAT, // IDAT data length is too small and cannot be valid, file is either corrupted or it's a bug
// fpng_decode_file() specific errors
FPNG_DECODE_FILE_OPEN_FAILED,
FPNG_DECODE_FILE_TOO_LARGE,
FPNG_DECODE_FILE_READ_FAILED,
FPNG_DECODE_FILE_SEEK_FAILED
};
// Fast PNG decoding of files ONLY created by fpng_encode_image_to_memory() or fpng_encode_image_to_file().
// If fpng_get_info() or fpng_decode_memory() returns FPNG_DECODE_NOT_FPNG, you should decode the PNG by falling back to a general purpose decoder.
//
// fpng_get_info() parses the PNG header and iterates through all chunks to determine if it's a file written by FPNG, but does not decompress the actual image data so it's relatively fast.
//
// pImage, image_size: Pointer to PNG image data and its size
// width, height: output image's dimensions
// channels_in_file: will be 3 or 4
//
// Returns FPNG_DECODE_SUCCESS on success, otherwise one of the failure codes above.
// If FPNG_DECODE_NOT_FPNG is returned, you must decompress the file with a general purpose PNG decoder.
// If another error occurs, the file is likely corrupted or invalid, but you can still try to decompress the file with another decoder (which will likely fail).
int fpng_get_info(const void* pImage, uint32_t image_size, uint32_t& width, uint32_t& height, uint32_t& channels_in_file);
// fpng_decode_memory() decompresses 24/32bpp PNG files ONLY encoded by this module.
// If the image was written by FPNG, it will decompress the image data, otherwise it will return FPNG_DECODE_NOT_FPNG in which case you should fall back to a general purpose PNG decoder (lodepng, stb_image, libpng, etc.)
//
// pImage, image_size: Pointer to PNG image data and its size
// out: Output 24/32bpp image buffer
// width, height: output image's dimensions
// channels_in_file: will be 3 or 4
// desired_channels: must be 3 or 4
//
// If the image is 24bpp and 32bpp is requested, the alpha values will be set to 0xFF.
// If the image is 32bpp and 24bpp is requested, the alpha values will be discarded.
//
// Returns FPNG_DECODE_SUCCESS on success, otherwise one of the failure codes above.
// If FPNG_DECODE_NOT_FPNG is returned, you must decompress the file with a general purpose PNG decoder.
// If another error occurs, the file is likely corrupted or invalid, but you can still try to decompress the file with another decoder (which will likely fail).
int fpng_decode_memory(const void* pImage, uint32_t image_size, std::vector<uint8_t>& out, uint32_t& width, uint32_t& height, uint32_t& channels_in_file, uint32_t desired_channels);
int fpng_decode_file(const char* pFilename, std::vector<uint8_t>& out, uint32_t& width, uint32_t& height, uint32_t& channels_in_file, uint32_t desired_channels);
} // namespace fpng
} // namespace tools
//G.Barrand specific:
#include "fpng.icc"
#include "sout"
#include <ostream>
namespace tools {
namespace fpng {
inline bool write(std::ostream& a_out,
const std::string& a_file,
unsigned char* a_buffer,
unsigned int a_width,
unsigned int a_height,
unsigned int a_bpp) {
if((a_bpp!=3)&&(a_bpp!=4)) {
a_out << "tools::fpng::write : bpp " << a_bpp << " not handled." << std::endl;
return false;
}
if(!fpng_encode_image_to_file(a_file.c_str(),a_buffer, a_width, a_height, a_bpp)) {
a_out << "tools::fpng::write : encode() failed for file " << sout(a_file) << "." << std::endl;
return false;
}
return true;
}
}}
#endif //tools_fpng
File diff suppressed because it is too large Load Diff
+73 -18
View File
@@ -821,12 +821,46 @@ inline void *tools_gl2psListPointer(tools_GL2PSlist *list, tools_GLint idx)
return &list->array[idx * list->size];
}
inline void tools_gl2psListSort(tools_GL2PSlist *list,
int (*fcmp)(const void *a, const void *b))
//G.Barrand: begin:
inline bool tools_gl2psPortableSort(void* a_items,size_t a_nitem,size_t a_item_size,int(*a_cmp)(const void*,const void*)) {
// We observed that qsort on macOS/clang, Linux/gcc, Windows/VisualC++
// does not produce the same output list for objects considered as "the same".
// "Same objects" are put correctly contiguously but not in the same order
// according the platform. In case of gl2ps, if using qsort we have, at end,
// primitives in the output file which are not in the same order according the platform.
// Then, we let the possibility to use a portable sort algorithm that will
// give the same sorted list, and then the same output file, on all platforms.
if(a_nitem<=1) return true;
if(!a_item_size) return true;
void* tmp = ::malloc(a_item_size);
if(!tmp) return false;
char* p = (char*)a_items;
size_t i,j;
char* a = p;char* b;
for(i=0;i<a_nitem;i++,a+=a_item_size) {
b = p+a_item_size*(i+1);
for(j=i+1;j<a_nitem;j++,b+=a_item_size) {
if(a_cmp(b,a)>=0) continue; //b>=a
::memcpy(tmp,a,a_item_size);
::memcpy(a,b,a_item_size);
::memcpy(b,tmp,a_item_size);
}
}
::free(tmp);
return true;
}
//G.Barrand: end.
inline void tools_gl2psListSort(tools_GL2PScontext* gl2ps,
tools_GL2PSlist *list,
int (*fcmp)(const void *a, const void *b))
{
if(!list)
return;
qsort(list->array, list->n, list->size, fcmp);
if(!list) return;
if(gl2ps->options & TOOLS_GL2PS_PORTABLE_SORT) {
tools_gl2psPortableSort(list->array, list->n, list->size, fcmp);
} else {
::qsort(list->array, list->n, list->size, fcmp);
}
}
/* Must be a list of tools_GL2PSprimitives. */
@@ -1715,6 +1749,7 @@ inline int tools_gl2psCompareDepth(const void *a, const void *b)
}
else{
/* Ensure that initial ordering is preserved when depths match. */
if(q->sortid==w->sortid) return 0; //G.Barrand.
return q->sortid < w->sortid ? -1 : 1;
}
}
@@ -1725,6 +1760,7 @@ inline int tools_gl2psTrianglesFirst(const void *a, const void *b)
q = *(const tools_GL2PSprimitive* const*)a;
w = *(const tools_GL2PSprimitive* const*)b;
if(q->type==w->type) return 0; //G.Barrand.
return (q->type < w->type ? 1 : -1);
}
@@ -1882,11 +1918,11 @@ inline void tools_gl2psBuildBspTree(tools_GL2PScontext* gl2ps, tools_GL2PSbsptre
}
if(tools_gl2psListNbr(tree->primitives)){
tools_gl2psListSort(tree->primitives, tools_gl2psTrianglesFirst);
tools_gl2psListSort(gl2ps, tree->primitives, tools_gl2psTrianglesFirst);
}
if(tools_gl2psListNbr(frontlist)){
tools_gl2psListSort(frontlist, tools_gl2psTrianglesFirst);
tools_gl2psListSort(gl2ps, frontlist, tools_gl2psTrianglesFirst);
tree->front = (tools_GL2PSbsptree*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree));
tools_gl2psBuildBspTree(gl2ps, tree->front, frontlist);
}
@@ -1895,7 +1931,7 @@ inline void tools_gl2psBuildBspTree(tools_GL2PScontext* gl2ps, tools_GL2PSbsptre
}
if(tools_gl2psListNbr(backlist)){
tools_gl2psListSort(backlist, tools_gl2psTrianglesFirst);
tools_gl2psListSort(gl2ps, backlist, tools_gl2psTrianglesFirst);
tree->back = (tools_GL2PSbsptree*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree));
tools_gl2psBuildBspTree(gl2ps, tree->back, backlist);
}
@@ -5335,6 +5371,9 @@ inline void tools_gl2psSVGGetCoordsAndColors(tools_GL2PScontext* gl2ps, int n, t
}
}
#include <sstream> //G.Barrand
#include <iomanip> //G.Barrand
inline void tools_gl2psSVGGetColorString(tools_GL2PSrgba rgba, char str[32])
{
int _r = (int)(255. * rgba[0]);
@@ -5343,7 +5382,15 @@ inline void tools_gl2psSVGGetColorString(tools_GL2PSrgba rgba, char str[32])
int rc = (_r < 0) ? 0 : (_r > 255) ? 255 : _r;
int gc = (_g < 0) ? 0 : (_g > 255) ? 255 : _g;
int bc = (_b < 0) ? 0 : (_b > 255) ? 255 : _b;
sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
//sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc); //G.Barrand
//G.Barrand:begin:
std::ostringstream oss;
oss << "#";
oss << std::setw(2) << std::setfill('0') << std::hex << rc;
oss << std::setw(2) << std::setfill('0') << std::hex << gc;
oss << std::setw(2) << std::setfill('0') << std::hex << bc;
strcpy(str,oss.str().c_str());
//G.Barrand:end.
}
inline void tools_gl2psPrintSVGHeader(tools_GL2PScontext* gl2ps)
@@ -5594,30 +5641,38 @@ inline void tools_gl2psPrintSVGPrimitive(tools_GL2PScontext* gl2ps, void *data)
col, prim->width);
switch (prim->linecap){
case TOOLS_GL2PS_LINE_CAP_BUTT:
sprintf (lcap, "%s", "butt");
//sprintf (lcap, "%s", "butt"); //G.Barrand
strcpy (lcap, "butt"); //G.Barrand
break;
case TOOLS_GL2PS_LINE_CAP_ROUND:
sprintf (lcap, "%s", "round");
//sprintf (lcap, "%s", "round"); //G.Barrand
strcpy (lcap, "round"); //G.Barrand
break;
case TOOLS_GL2PS_LINE_CAP_SQUARE:
sprintf (lcap, "%s", "square");
//sprintf (lcap, "%s", "square"); //G.Barrand
strcpy (lcap, "square"); //G.Barrand
break;
default: /*G.Barrand : to quiet Coverity :*/
sprintf (lcap, "%s", "butt");
//sprintf (lcap, "%s", "butt"); //G.Barrand
strcpy (lcap, "butt"); //G.Barrand
break;
}
switch (prim->linejoin){
case TOOLS_GL2PS_LINE_JOIN_MITER:
sprintf (ljoin, "%s", "miter");
//sprintf (ljoin, "%s", "miter"); //G.Barrand
strcpy (ljoin, "miter"); //G.Barrand
break;
case TOOLS_GL2PS_LINE_JOIN_ROUND:
sprintf (ljoin, "%s", "round");
//sprintf (ljoin, "%s", "round"); //G.Barrand
strcpy (ljoin, "round"); //G.Barrand
break;
case TOOLS_GL2PS_LINE_JOIN_BEVEL:
sprintf (ljoin, "%s", "bevel");
//sprintf (ljoin, "%s", "bevel"); //G.Barrand
strcpy (ljoin, "bevel"); //G.Barrand
break;
default: /*G.Barrand : to quiet Coverity :*/
sprintf (ljoin, "%s", "miter");
//sprintf (ljoin, "%s", "miter"); //G.Barrand
strcpy (ljoin, "miter"); //G.Barrand
break;
}
tools_gl2psPrintf(gl2ps,"stroke-linecap=\"%s\" stroke-linejoin=\"%s\" ",
@@ -6168,7 +6223,7 @@ inline tools_GLint tools_gl2psPrintPrimitives(tools_GL2PScontext* gl2ps)
break;
case TOOLS_GL2PS_SIMPLE_SORT :
tools_gl2psListAssignSortIds(gl2ps->primitives);
tools_gl2psListSort(gl2ps->primitives, tools_gl2psCompareDepth);
tools_gl2psListSort(gl2ps, gl2ps->primitives, tools_gl2psCompareDepth);
if(gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL){
tools_gl2psListActionInverseContext(gl2ps, gl2ps->primitives, tools_gl2psAddInImageTree);
tools_gl2psFreeBspImageTree(&gl2ps->imagetree);
+1
View File
@@ -72,6 +72,7 @@ typedef unsigned char tools_GLboolean;
#define TOOLS_GL2PS_TIGHT_BOUNDING_BOX (1<<12)
#define TOOLS_GL2PS_NO_OPENGL_CONTEXT (1<<13)
#define TOOLS_GL2PS_NO_TEX_FONTSIZE (1<<14)
#define TOOLS_GL2PS_PORTABLE_SORT (1<<15)
/* Arguments for tools_gl2psEnable/tools_gl2psDisable */
+2
View File
@@ -272,6 +272,7 @@ inline/*static*/ void static_RenderFan( GLUtesselator *tess, GLUhalfEdge *e, lon
assert( size == 0 );
CALL_END_OR_END_DATA();
(void)size;
}
@@ -300,6 +301,7 @@ inline/*static*/ void static_RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, l
assert( size == 0 );
CALL_END_OR_END_DATA();
(void)size;
}
@@ -0,0 +1,60 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_offscreen_session
#define tools_offscreen_session
namespace tools {
namespace offscreen {
class viewer {
public:
virtual ~viewer() {}
public:
virtual void render() = 0;
};
}}
#include "../forit"
#include "../vmanip"
#include <ostream>
namespace tools {
namespace offscreen {
class session {
public:
session(std::ostream& a_out):m_out(a_out) {}
virtual ~session() {}
protected:
session(const session& a_from):m_out(a_from.m_out) {}
session& operator=(const session& a_from) {if(&a_from==this) return *this;return *this;}
public:
std::ostream& out() const {return m_out;}
bool is_valid() const {return true;}
bool steer() {
tools_vforcit(viewer*,m_to_render,it) {(*it)->render();}
m_to_render.clear();
return true;
}
bool sync() {
tools_vforcit(viewer*,m_to_render,it) {(*it)->render();}
m_to_render.clear();
return true;
}
public:
void to_render(viewer* a_viewer) {
if(is_inp(m_to_render,a_viewer)) return;
m_to_render.push_back(a_viewer);
}
protected:
std::ostream& m_out;
std::vector<viewer*> m_to_render;
};
}}
#endif
@@ -0,0 +1,123 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_offscreen_sg_viewer
#define tools_offscreen_sg_viewer
#include "session"
#include "../sg/viewer"
#include "../sg/zb_manager"
#include "../sg/gl2ps_manager"
#include "../sg/write_paper"
namespace tools {namespace sg {class device_interactor;}}
namespace tools {
namespace offscreen {
class sg_viewer : public sg::viewer, public offscreen::viewer {
typedef sg::viewer parent;
protected:
virtual void render() {write_paper();}
public:
sg_viewer(session& a_session,
int /*a_x*/ = 0,int /*a_y*/ = 0,
unsigned int a_width = 500,unsigned int a_height = 500,
const std::string& /*a_win_title*/ = "")
:parent(a_session.out(),a_width,a_height)
,m_session(a_session)
,m_file_format("zb_ps")
,m_file_name("out_zb.ps")
,m_png_writer(0)
,m_jpeg_writer(0)
,m_do_transparency(true)
,m_top_to_bottom(true)
{}
virtual ~sg_viewer() {}
protected:
sg_viewer(const sg_viewer& a_from)
:parent(a_from)
,offscreen::viewer(a_from)
,m_session(a_from.m_session)
,m_zb_mgr(a_from.m_zb_mgr)
,m_gl2ps_mgr(a_from.m_gl2ps_mgr)
,m_file_format(a_from.m_file_format)
,m_file_name(a_from.m_file_name)
,m_png_writer(a_from.m_png_writer)
,m_jpeg_writer(a_from.m_jpeg_writer)
,m_do_transparency(a_from.m_do_transparency)
,m_top_to_bottom(a_from.m_top_to_bottom)
,m_opts_1(a_from.m_opts_1)
,m_opts_2(a_from.m_opts_2)
{}
sg_viewer& operator=(const sg_viewer& a_from){
parent::operator=(a_from);
m_file_format = a_from.m_file_format;
m_file_name = a_from.m_file_name;
m_png_writer = a_from.m_png_writer;
m_jpeg_writer = a_from.m_jpeg_writer;
m_do_transparency = a_from.m_do_transparency;
m_top_to_bottom = a_from.m_top_to_bottom;
m_opts_1 = a_from.m_opts_1;
m_opts_2 = a_from.m_opts_2;
return *this;
}
public:
bool has_window() const {return true;}
bool show() {
m_session.to_render(this);
return true;
}
void win_render() {
m_session.to_render(this);
}
void set_device_interactor(sg::device_interactor*) {}
public:
void set_file_format(const std::string& a_file_format) {m_file_format = a_file_format;}
void set_file_name(const std::string& a_file_name) {m_file_name = a_file_name;}
const std::string& file_format() const {return m_file_format;}
const std::string& file_name() const {return m_file_name;}
void set_png_writer(sg::png_writer a_png_writer) {m_png_writer = a_png_writer;}
void set_jpeg_writer(sg::jpeg_writer a_jpeg_writer) {m_jpeg_writer = a_jpeg_writer;}
void set_do_transparency(bool a_do_transparency) {m_do_transparency = a_do_transparency;}
void set_top_to_bottom(bool a_top_to_bottom) {m_top_to_bottom = a_top_to_bottom;}
void set_opts_1(const std::string& a_opts) {m_opts_1 = a_opts;}
void set_opts_2(const std::string& a_opts) {m_opts_2 = a_opts;}
bool write_paper() {
if(!m_ww) return false;
if(!m_wh) return false;
return sg::write_paper(m_out,m_gl2ps_mgr,m_zb_mgr,
m_png_writer,m_jpeg_writer,
m_clear_color.r(),
m_clear_color.g(),
m_clear_color.b(),
m_clear_color.a(),
m_sg,m_ww,m_wh,
m_file_name,m_file_format,
m_do_transparency,m_top_to_bottom,
m_opts_1,m_opts_2);
}
protected:
session& m_session;
sg::zb_manager m_zb_mgr;
sg::gl2ps_manager m_gl2ps_mgr;
std::string m_file_format;
std::string m_file_name;
sg::png_writer m_png_writer;
sg::jpeg_writer m_jpeg_writer;
bool m_do_transparency;
bool m_top_to_bottom;
std::string m_opts_1;
std::string m_opts_2;
};
}}
#endif
+3 -3
View File
@@ -86,7 +86,7 @@ inline unsigned int new_bin_number(const std::vector< axis_t >& aAxes) {
template <class T>
inline void add_outflow(const std::vector< axis_t >& aAxes,std::vector<T>& aVector) {
// aAxes[].m_offset contains the offset without outflow.
unsigned int dim = aAxes.size();
std::size_t dim = aAxes.size();
// new size and offsets :
std::vector<int> aoff(dim);
@@ -107,13 +107,13 @@ inline void add_outflow(const std::vector< axis_t >& aAxes,std::vector<T>& aVect
for(int index=0;index<oldn;index++) {
// Get new offset of index :
offset = index;
{for(int iaxis=dim-1;iaxis>=0;iaxis--) {
{for(int iaxis=(int)dim-1;iaxis>=0;iaxis--) {
is[iaxis] = offset/aAxes[iaxis].m_offset;
offset -= is[iaxis] * aAxes[iaxis].m_offset;
}}
// new offset :
offset = 0;
{for(unsigned iaxis=0;iaxis<dim;iaxis++) offset += is[iaxis] * aoff[iaxis];}
{for(std::size_t iaxis=0;iaxis<dim;iaxis++) offset += is[iaxis] * aoff[iaxis];}
aVector[offset] = tmp[index];
}
}
+3 -3
View File
@@ -18,7 +18,7 @@
#include <fcntl.h>
#include <errno.h>
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <io.h>
#include <sys/stat.h>
#else
@@ -60,7 +60,7 @@ public: //ifile
#if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
if (::lseek64(m_file, a_offset, whence) < 0) {
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) || defined(__MINGW32__)
if (::_lseeki64(m_file, a_offset, whence) < 0) {
#else
if (::lseek(m_file, a_offset, whence) < 0) {
@@ -137,7 +137,7 @@ public:
#endif
m_file = _open(a_path.c_str(),
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
O_RDONLY | O_BINARY,S_IREAD | S_IWRITE
#else
O_RDONLY,0644
+259 -116
View File
@@ -10,6 +10,7 @@
#include "render_action"
#include "primitive_visitor"
#include "../colorfs"
#include "../lina/plane"
#include <cstdio> //FILE
@@ -100,9 +101,12 @@ public:
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){
float a_r,float a_g,float a_b,float a_a,
float a_ar,float a_ag,float a_ab,float a_aa){
m_light_color.set_value(a_r,a_g,a_b,a_a);
m_light_ambient.set_value(a_ar,a_ag,a_ab,a_aa);
m_light_direction.set_value(a_dx,a_dy,a_dz);
m_light_direction.normalize();
m_light_on = true;
}
@@ -116,6 +120,8 @@ public:
set_normal_matrix();
m_color = _state.m_color;
m_normal = _state.m_normal;
m_ccw = (_state.m_winding==winding_ccw?true:false);
m_POLYGON_OFFSET_FILL = _state.m_GL_POLYGON_OFFSET_FILL;
m_CULL_FACE = _state.m_GL_CULL_FACE;
@@ -167,6 +173,7 @@ public:
,m_FILE(0)
,m_pv(get_me())
,m_light_color(colorf_white())
,m_light_ambient(colorf_black())
,m_light_direction(vec3f(0,0,-1))
,m_ccw(true)
@@ -207,6 +214,7 @@ protected:
,m_vp_mtx(a_from.m_vp_mtx)
,m_pv(a_from.m_pv)
,m_light_color(a_from.m_light_color)
,m_light_ambient(a_from.m_light_ambient)
,m_light_direction(a_from.m_light_direction)
,m_normal(a_from.m_normal)
@@ -239,6 +247,7 @@ protected:
m_vp_mtx = a_from.m_vp_mtx;
m_pv = a_from.m_pv;
m_light_color = a_from.m_light_color;
m_light_ambient = a_from.m_light_ambient;
m_light_direction = a_from.m_light_direction;
m_normal = a_from.m_normal;
@@ -259,6 +268,9 @@ protected:
}
public:
bool open(const std::string& a_name,int a_format = TOOLS_GL2PS_EPS) {
return open(a_name,a_format,-1,-1);
}
bool open(const std::string& a_name,int a_format,int a_sort,int a_options) {
close();
m_gl2ps_context = ::tools_gl2psCreateContext();
@@ -269,7 +281,7 @@ public:
return false;
}
m_FILE = ::fopen(a_name.c_str(),"w");
m_FILE = ::fopen(a_name.c_str(),"wb");
if(!m_FILE) {
m_out << "tools::sg::gl2ps_action::open :"
<< " can't open file " << a_name << "."
@@ -279,14 +291,23 @@ public:
return false;
}
int options = TOOLS_GL2PS_OCCLUSION_CULL
| TOOLS_GL2PS_BEST_ROOT
| TOOLS_GL2PS_SILENT
| TOOLS_GL2PS_DRAW_BACKGROUND;
//int sort = TOOLS_GL2PS_NO_SORT;
//int sort = TOOLS_GL2PS_SIMPLE_SORT;
int sort = TOOLS_GL2PS_BSP_SORT;
int sort = 0;
if(a_sort==(-1)) {
sort = TOOLS_GL2PS_BSP_SORT;
} else {
sort = a_sort;
}
int options = 0;
if(a_options==(-1)) {
options = TOOLS_GL2PS_SILENT
| TOOLS_GL2PS_OCCLUSION_CULL
| TOOLS_GL2PS_BEST_ROOT
| TOOLS_GL2PS_DRAW_BACKGROUND;
} else {
options = a_options;
}
tools_GLint vp[4];
vp[0] = 0;
vp[1] = 0;
@@ -343,7 +364,7 @@ protected:
mat4f tmp(m_model);
tmp.no_translate();
if(!tmp.invert(m_normal_matrix)) {
m_out << "mem_action::set_normal_matrix : can't invert model matrix." << std::endl;
m_out << "tools::sg::gl2ps_action::set_normal_matrix : can't invert model matrix." << std::endl;
}
m_normal_matrix.transpose();
}
@@ -390,14 +411,14 @@ protected:
float a = m_this.m_color[3];
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLfloat ofactor = 0;
tools_GLfloat ounits = 0;
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat sz = m_this.m_point_size;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GLint linecap = 0;
tools_GLint linejoin = 0;
char boundary = 0;
tools_GL2PSvertex vertices[1];
@@ -413,14 +434,14 @@ protected:
if(!m_this.m_gl2ps_context) return false;
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLfloat ofactor = 0;
tools_GLfloat ounits = 0;
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat sz = m_this.m_point_size;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GLint linecap = 0;
tools_GLint linejoin = 0;
char boundary = 0;
tools_GL2PSvertex vertices[1];
@@ -428,7 +449,6 @@ protected:
m_this.set_vtx(vertices,0, a_x,a_y,a_z, a_r,a_g,a_b,a_a);
//::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_POINT(),1,vertices,0,pattern,factor,sz,0);
::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_POINT(),1,vertices,offset,ofactor,ounits,pattern,factor,sz,linecap,linejoin,boundary);
return true;
}
@@ -443,14 +463,14 @@ protected:
float a = m_this.m_color[3];
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLfloat ofactor = 0;
tools_GLfloat ounits = 0;
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat lwidth = m_this.m_line_width;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GLint linecap = 0;
tools_GLint linejoin = 0;
char boundary = 0;
tools_GL2PSvertex vertices[2];
@@ -460,7 +480,6 @@ protected:
m_this.set_vtx(vertices,0, a_bx,a_by,a_bz, r,g,b,a);
m_this.set_vtx(vertices,1, a_ex,a_ey,a_ez, r,g,b,a);
//::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_LINE(),2,vertices,0,pattern,factor,lwidth,0);
::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_LINE(),2,vertices,offset,ofactor,ounits,pattern,factor,lwidth,linecap,linejoin,boundary);
return true;
@@ -473,14 +492,14 @@ protected:
if(!m_this.m_gl2ps_context) return false;
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLfloat ofactor = 0;
tools_GLfloat ounits = 0;
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat lwidth = m_this.m_line_width;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GLint linecap = 0;
tools_GLint linejoin = 0;
char boundary = 0;
tools_GL2PSvertex vertices[2];
@@ -496,76 +515,41 @@ protected:
return true;
}
virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float,
float a_p2x,float a_p2y,float a_p2z,float,
float a_p3x,float a_p3y,float a_p3z,float){
if(!m_this.m_gl2ps_context) return false;
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){
float r = m_this.m_color[0];
float g = m_this.m_color[1];
float b = m_this.m_color[2];
float a = m_this.m_color[3];
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat lwidth = m_this.m_line_width;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GL2PSvertex vertices[3];
m_this.m_vp_mtx.mul_3f(a_p1x,a_p1y,a_p1z);
m_this.m_vp_mtx.mul_3f(a_p2x,a_p2y,a_p2z);
m_this.m_vp_mtx.mul_3f(a_p3x,a_p3y,a_p3z);
m_this.set_vtx(vertices,0, a_p1x,a_p1y,a_p1z, r,g,b,a);
m_this.set_vtx(vertices,1, a_p2x,a_p2y,a_p2z, r,g,b,a);
m_this.set_vtx(vertices,2, a_p3x,a_p3y,a_p3z, r,g,b,a);
//tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_TRIANGLE(),3,vertices,0,pattern,factor,lwidth,0);
::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_TRIANGLE(),3,vertices,offset,ofactor,ounits,pattern,factor,lwidth,linecap,linejoin,boundary);
return true;
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
r,g,b,a,
a_p2x,a_p2y,a_p2z,a_p2w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
r,g,b,a,
a_p3x,a_p3y,a_p3z,a_p3w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
r,g,b,a);
}
virtual bool add_triangle(
float a_p1x,float a_p1y,float a_p1z,float,
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,
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,
float a_p3x,float a_p3y,float a_p3z,float a_p3w,
float a_r3,float a_g3,float a_b3,float a_a3){
if(!m_this.m_gl2ps_context) return false;
tools_GLint offset = 0;
tools_GLfloat ofactor = 0; //
tools_GLfloat ounits = 0; //
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat lwidth = m_this.m_line_width;
tools_GLint linecap = 0; //
tools_GLint linejoin = 0; //
char boundary = 0; //
tools_GL2PSvertex vertices[3];
m_this.m_vp_mtx.mul_3f(a_p1x,a_p1y,a_p1z);
m_this.m_vp_mtx.mul_3f(a_p2x,a_p2y,a_p2z);
m_this.m_vp_mtx.mul_3f(a_p3x,a_p3y,a_p3z);
m_this.set_vtx(vertices,0, a_p1x,a_p1y,a_p1z, a_r1,a_g1,a_b1,a_a1);
m_this.set_vtx(vertices,1, a_p2x,a_p2y,a_p2z, a_r2,a_g2,a_b2,a_a2);
m_this.set_vtx(vertices,2, a_p3x,a_p3y,a_p3z, a_r3,a_g3,a_b3,a_a3);
//tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_TRIANGLE(),3,vertices,0,pattern,factor,lwidth,0);
::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_TRIANGLE(),3,vertices,offset,ofactor,ounits,pattern,factor,lwidth,linecap,linejoin,boundary);
return true;
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
a_r1,a_g1,a_b1,a_a1,
a_p2x,a_p2y,a_p2z,a_p2w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
a_r2,a_g2,a_b2,a_a2,
a_p3x,a_p3y,a_p3z,a_p3w,
m_this.m_normal.x(),m_this.m_normal.y(),m_this.m_normal.z(),
a_r3,a_g3,a_b3,a_a3);
}
virtual bool project_normal(float& /*a_x*/,float& /*a_y*/,float& /*a_z*/) {
@@ -607,39 +591,46 @@ protected:
}
virtual bool add_triangle_normal(
float a_p1x,float a_p1y,float a_p1z,float a_p1w,
float /*a_n1x*/,float /*a_n1y*/,float /*a_n1z*/,
float a_n1x,float a_n1y,float a_n1z,
float a_p2x,float a_p2y,float a_p2z,float a_p2w,
float /*a_n2x*/,float /*a_n2y*/,float /*a_n2z*/,
float a_n2x,float a_n2y,float a_n2z,
float a_p3x,float a_p3y,float a_p3z,float a_p3w,
float /*a_n3x*/,float /*a_n3y*/,float /*a_n3z*/) {
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_this.m_triangles.add_normal(a_n1x,a_n1y,a_n1z);
//m_this.m_triangles.add_normal(a_n2x,a_n2y,a_n2z);
//m_this.m_triangles.add_normal(a_n3x,a_n3y,a_n3z);
return true;
float a_n3x,float a_n3y,float a_n3z) {
float r = m_this.m_color[0];
float g = m_this.m_color[1];
float b = m_this.m_color[2];
float a = m_this.m_color[3];
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
a_n1x,a_n1y,a_n1z,
r,g,b,a,
a_p2x,a_p2y,a_p2z,a_p2w,
a_n2x,a_n2y,a_n2z,
r,g,b,a,
a_p3x,a_p3y,a_p3z,a_p3w,
a_n3x,a_n3y,a_n3z,
r,g,b,a);
}
virtual bool add_triangle_normal(
float a_p1x,float a_p1y,float a_p1z,float a_p1w,
float /*a_n1x*/,float /*a_n1y*/,float /*a_n1z*/,
float a_n1x,float a_n1y,float a_n1z,
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_n2x*/,float /*a_n2y*/,float /*a_n2z*/,
float a_n2x,float a_n2y,float a_n2z,
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_n3x*/,float /*a_n3y*/,float /*a_n3z*/,
float a_n3x,float a_n3y,float a_n3z,
float a_r3,float a_g3,float a_b3,float a_a3){
add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
a_r1,a_g1,a_b1,a_a1,
a_p2x,a_p2y,a_p2z,a_p2w,
a_r2,a_g2,a_b2,a_a2,
a_p3x,a_p3y,a_p3z,a_p3w,
a_r3,a_g3,a_b3,a_a3);
//m_this.m_triangles.add_normal(a_n1x,a_n1y,a_n1z);
//m_this.m_triangles.add_normal(a_n2x,a_n2y,a_n2z);
//m_this.m_triangles.add_normal(a_n3x,a_n3y,a_n3z);
return true;
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
a_n1x,a_n1y,a_n1z,
a_r1,a_g1,a_b1,a_a1,
a_p2x,a_p2y,a_p2z,a_p2w,
a_n2x,a_n2y,a_n2z,
a_r2,a_g2,a_b2,a_a2,
a_p3x,a_p3y,a_p3z,a_p3w,
a_n3x,a_n3y,a_n3z,
a_r3,a_g3,a_b3,a_a3);
}
public:
primvis(gl2ps_action& a_this):m_this(a_this){}
@@ -653,6 +644,109 @@ protected:
primitive_visitor::operator=(a_from);
return *this;
}
protected:
bool _add_triangle(float a_p1x,float a_p1y,float a_p1z,float /*a_p1w*/,
float a_n1x,float a_n1y,float a_n1z,
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_n2x,float a_n2y,float a_n2z,
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_n3x,float a_n3y,float a_n3z,
float a_r3,float a_g3,float a_b3,float a_a3) {
if(!m_this.m_gl2ps_context) return false;
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_this.m_vp_mtx.mul_3f(p1x,p1y,p1z);
m_this.m_vp_mtx.mul_3f(p2x,p2y,p2z);
m_this.m_vp_mtx.mul_3f(p3x,p3y,p3z);
{plane<vec3f> pn(
vec3f(p1x,p1y,p1z),
vec3f(p2x,p2y,p2z),
vec3f(p3x,p3y,p3z)
);
if(!pn.is_valid()) return true;
float C = pn.normal()[2];
if(m_this.m_CULL_FACE){
if(m_this.m_ccw) {
if(C<=0) return true;
} else {
if(C>=0) return true;
}
}}
tools_GL2PSvertex vertices[3];
if(m_this.m_light_on) { // same logic as toolx/wasm/webgl.js:
float nx = (a_n1x+a_n2x+a_n3x)/3.0f;
float ny = (a_n1y+a_n2y+a_n3y)/3.0f;
float nz = (a_n1z+a_n2z+a_n3z)/3.0f;
m_this.m_normal_matrix.mul_dir_3f(nx,ny,nz);
vec3f _normal(nx,ny,nz);_normal.normalize();
float _dot = _normal.dot(m_this.m_light_direction);
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 a_color(_r,_g,_b,_a);
colorf frag_color = a_color;
if(_dot<0.0) {
_dot *= -1.0;
colorf _tmp = m_this.m_light_color;
_tmp *= _dot;
_tmp += m_this.m_light_ambient;
frag_color *= _tmp;
} else {
frag_color *= m_this.m_light_ambient;
}
frag_color.clamp();
frag_color.set_a(a_color.a());
float r = frag_color.r();
float g = frag_color.g();
float b = frag_color.b();
float a = frag_color.a();
m_this.set_vtx(vertices,0, p1x,p1y,p1z, r,g,b,a);
m_this.set_vtx(vertices,1, p2x,p2y,p2z, r,g,b,a);
m_this.set_vtx(vertices,2, p3x,p3y,p3z, r,g,b,a);
} else {
m_this.set_vtx(vertices,0, p1x,p1y,p1z, a_r1,a_g1,a_b1,a_a1);
m_this.set_vtx(vertices,1, p2x,p2y,p2z, a_r2,a_g2,a_b2,a_a2);
m_this.set_vtx(vertices,2, p3x,p3y,p3z, a_r3,a_g3,a_b3,a_a3);
}
tools_GLint offset = 0;
tools_GLfloat ofactor = 0;
tools_GLfloat ounits = 0;
tools_GLushort pattern = 0;
tools_GLint factor = 0;
tools_GLfloat lwidth = m_this.m_line_width;
tools_GLint linecap = 0;
tools_GLint linejoin = 0;
char boundary = 0;
::tools_gl2psAddPolyPrimitive(m_this.m_gl2ps_context,_GL2PS_TRIANGLE(),3,vertices,offset,ofactor,ounits,pattern,factor,lwidth,linecap,linejoin,boundary);
return true;
}
protected:
gl2ps_action& m_this;
};
@@ -667,6 +761,7 @@ protected:
primvis m_pv;
colorf m_light_color;
colorf m_light_ambient;
vec3f m_light_direction;
vec3f m_normal;
@@ -686,9 +781,9 @@ protected:
bool m_DEPTH_TEST;
};
inline bool s2format(const std::string& a_format,int& a_gl2ps_format) {
inline bool gl2ps_s2format(const std::string& a_format,int& a_gl2ps_format) {
if(a_format=="gl2ps_eps") {a_gl2ps_format = TOOLS_GL2PS_EPS;return true;}
if(a_format=="gl2ps_ps") {a_gl2ps_format = TOOLS_GL2PS_PS;return true;}
if(a_format=="gl2ps_ps") {a_gl2ps_format = TOOLS_GL2PS_PS; return true;}
if(a_format=="gl2ps_pdf") {a_gl2ps_format = TOOLS_GL2PS_PDF;return true;}
if(a_format=="gl2ps_svg") {a_gl2ps_format = TOOLS_GL2PS_SVG;return true;}
if(a_format=="gl2ps_tex") {a_gl2ps_format = TOOLS_GL2PS_TEX;return true;}
@@ -697,6 +792,54 @@ inline bool s2format(const std::string& a_format,int& a_gl2ps_format) {
return false;
}
inline bool gl2ps_s2sort(const std::string& a_sort,int& a_gl2ps_sort) {
if(a_sort=="NO_SORT") {a_gl2ps_sort = TOOLS_GL2PS_NO_SORT; return true;}
if(a_sort=="SIMPLE_SORT") {a_gl2ps_sort = TOOLS_GL2PS_SIMPLE_SORT;return true;}
if(a_sort=="BSP_SORT") {a_gl2ps_sort = TOOLS_GL2PS_BSP_SORT; return true;}
a_gl2ps_sort = TOOLS_GL2PS_NO_SORT;
return false;
}
}}
#include "../words"
#include "../forit"
#include "../touplow"
#include "../sout"
namespace tools {
namespace sg {
inline bool gl2ps_s2options(const std::string& a_opts,int& a_gl2ps_opts) {
std::vector<std::string> opts;
words(a_opts,"|",false,opts);
a_gl2ps_opts = 0;
tools_vforit(std::string,opts,it) {
touppercase(*it);
const std::string& item = *it;
if(item=="NONE") a_gl2ps_opts |= TOOLS_GL2PS_NONE;
else if(item=="DRAW_BACKGROUND") a_gl2ps_opts |= TOOLS_GL2PS_DRAW_BACKGROUND;
else if(item=="SIMPLE_LINE_OFFSET") a_gl2ps_opts |= TOOLS_GL2PS_SIMPLE_LINE_OFFSET;
else if(item=="SILENT") a_gl2ps_opts |= TOOLS_GL2PS_SILENT;
else if(item=="BEST_ROOT") a_gl2ps_opts |= TOOLS_GL2PS_BEST_ROOT;
else if(item=="OCCLUSION_CULL") a_gl2ps_opts |= TOOLS_GL2PS_OCCLUSION_CULL;
else if(item=="NO_TEXT") a_gl2ps_opts |= TOOLS_GL2PS_NO_TEXT;
else if(item=="LANDSCAPE") a_gl2ps_opts |= TOOLS_GL2PS_LANDSCAPE;
else if(item=="NO_PS3_SHADING") a_gl2ps_opts |= TOOLS_GL2PS_NO_PS3_SHADING;
else if(item=="NO_PIXMAP") a_gl2ps_opts |= TOOLS_GL2PS_NO_PIXMAP;
else if(item=="USE_CURRENT_VIEWPORT") a_gl2ps_opts |= TOOLS_GL2PS_USE_CURRENT_VIEWPORT;
else if(item=="COMPRESS") a_gl2ps_opts |= TOOLS_GL2PS_COMPRESS;
else if(item=="NO_BLENDING") a_gl2ps_opts |= TOOLS_GL2PS_NO_BLENDING;
else if(item=="TIGHT_BOUNDING_BOX") a_gl2ps_opts |= TOOLS_GL2PS_TIGHT_BOUNDING_BOX;
else if(item=="NO_OPENGL_CONTEXT") a_gl2ps_opts |= TOOLS_GL2PS_NO_OPENGL_CONTEXT;
else if(item=="NO_TEX_FONTSIZE") a_gl2ps_opts |= TOOLS_GL2PS_NO_TEX_FONTSIZE;
else if(item=="PORTABLE_SORT") a_gl2ps_opts |= TOOLS_GL2PS_PORTABLE_SORT;
else {a_gl2ps_opts = 0;return false;}
}
return true;
}
}}
#endif
+2 -2
View File
@@ -30,8 +30,8 @@ public:
{mat4f mtx;
state.m_camera_orientation.value(mtx);
mtx.mul_dir_3f(dx,dy,dz);}
state.m_GL_LIGHTING = true; //for separator
a_action.enable_light(state.m_light,vec3f(dx,dy,dz),color.value());
state.m_GL_LIGHTING = true;
a_action.enable_light(state.m_light,vec3f(dx,dy,dz),color.value(),ambient.value());
state.m_light++;
}
public:
+7
View File
@@ -601,6 +601,13 @@ public:
xyzs.add(a_y);
xyzs.add(a_z);
}
void add_allocated(size_t& a_pos,float a_x,float a_y,float a_z) {
std::vector<float>& v = xyzs.values();
v[a_pos] = a_x;a_pos++;
v[a_pos] = a_y;a_pos++;
v[a_pos] = a_z;a_pos++;
xyzs.touch();
}
bool add(const std::vector<float>& a_v) {
std::vector<float>::size_type _number = a_v.size()/3;
if(3*_number!=a_v.size()) return false;
-3
View File
@@ -938,7 +938,6 @@ protected:
m_sep.clear();
unsigned int index = 0;
for(unsigned int irow=0;irow<rows;irow++) {
for(unsigned int icol=0;icol<cols;icol++) {
separator* sep = new separator;
@@ -958,8 +957,6 @@ protected:
//sep->add(tsf); //TSF()
sep->add(new plotter(m_ttf)); //PLOTTER()
index++;
}
}
+14 -18
View File
@@ -80,14 +80,13 @@ public:
bool write_inzb_png(png_writer a_writer,const std::string& a_file,unsigned int a_width,unsigned int a_height) {
// for example :
// #include <tools/png>
// #include <toolx/png>
// ...
// viewer.write_inzb_png(tools::png::write,"out.png");
// viewer.write_inzb_png(toolx::png::write,"out.png");
//
zb_action action(m_zb_mgr,m_out,a_width,a_height);
action.zbuffer().clear_color_buffer(0);
action.add_color(m_clear_color.r(),m_clear_color.g(),m_clear_color.b(),m_clear_color.a());
action.zbuffer().clear_depth_buffer();
action.clear_color_buffer(m_clear_color);
action.clear_depth_buffer();
sg().render(action);
unsigned int bpp = 3;
@@ -97,7 +96,7 @@ public:
return false;
}
unsigned char* pos = buffer;
zb_action::VCol r,g,b;
float r,g,b;
for(unsigned int row=0;row<a_height;row++) {
for(unsigned int col=0;col<a_width;col++) {
zb_action::get_rgb(&action,col,a_height-row-1,r,g,b);
@@ -123,14 +122,13 @@ public:
bool write_inzb_jpeg(jpeg_writer a_writer,const std::string& a_file,unsigned int a_width,unsigned int a_height,int a_quality = 100) {
// for example :
// #include <tools/jpeg>
// #include <toolx/jpeg>
// ...
// viewer.write_inzb_jpeg(tools::jpeg::write,"out.jpeg");
// viewer.write_inzb_jpeg(toolx::jpeg::write,"out.jpeg");
//
zb_action action(m_zb_mgr,m_out,a_width,a_height);
action.zbuffer().clear_color_buffer(0);
action.add_color(m_clear_color.r(),m_clear_color.g(),m_clear_color.b(),m_clear_color.a());
action.zbuffer().clear_depth_buffer();
action.clear_color_buffer(m_clear_color);
action.clear_depth_buffer();
sg().render(action);
unsigned int bpp = 3;
@@ -140,7 +138,7 @@ public:
return false;
}
unsigned char* pos = buffer;
zb_action::VCol r,g,b;
float r,g,b;
for(unsigned int row=0;row<a_height;row++) {
for(unsigned int col=0;col<a_width;col++) {
zb_action::get_rgb(&action,col,a_height-row-1,r,g,b);
@@ -164,9 +162,8 @@ public:
bool write_inzb_ps(const std::string& a_file,unsigned int a_width,unsigned int a_height,bool a_anonymous = false) {
zb_action action(m_zb_mgr,m_out,a_width,a_height);
action.zbuffer().clear_color_buffer(0);
action.add_color(m_clear_color.r(),m_clear_color.g(),m_clear_color.b(),m_clear_color.a());
action.zbuffer().clear_depth_buffer();
action.clear_color_buffer(m_clear_color);
action.clear_depth_buffer();
sg().render(action);
wps wps(m_out);
if(!wps.open_file(a_file,a_anonymous)) {
@@ -194,9 +191,8 @@ public:
}
bool write_inzb_ps_page(unsigned int a_width,unsigned int a_height) {
sg::zb_action action(m_zb_mgr,m_out,a_width,a_height);
action.zbuffer().clear_color_buffer(0);
action.add_color(m_clear_color.r(),m_clear_color.g(),m_clear_color.b(),m_clear_color.a());
action.zbuffer().clear_depth_buffer();
action.clear_color_buffer(m_clear_color);
action.clear_depth_buffer();
sg().render(action);
m_wps.PS_BEGIN_PAGE();
m_wps.PS_PAGE_SCALE(float(a_width),float(a_height));
+2 -4
View File
@@ -6814,7 +6814,6 @@ protected: //rep
vtxs->mode = gl::points();
separator->add(vtxs);
int ipt = 0;
float xdbin = xe - xx;
float ydbin = ye - yy;
for(int count=0;count<npt;count++) {
@@ -6826,7 +6825,6 @@ protected: //rep
(yyy>=0)&&(yyy<=1) ) {
vtxs->add(xxx,yyy,a_zz);
empty = false;
ipt++;
}
}
}
@@ -6894,7 +6892,7 @@ protected: //rep
if(ye>1) ye = 1;
char sval[32];
::sprintf (sval,"%d",ival);
//::sprintf (sval,"%d",ival);
SbString sbval(sval);
int charn = sbval.getLength();
if(charn<=0) continue;
@@ -6903,7 +6901,7 @@ protected: //rep
separator->addChild(sep);
{char s[128];
::sprintf(s,"%d %d",a_bins[index].fI,a_bins[index].fJ);
//::sprintf(s,"%d %d",a_bins[index].fI,a_bins[index].fJ);
sep->setInfos(s);}
{std::string sp;
if(!p2sx(sep->getInfos(),sp)){}
+8 -6
View File
@@ -68,8 +68,9 @@ public:
virtual void set_depth_test(bool) = 0;
virtual unsigned int max_lights() = 0;
virtual void enable_light(unsigned int,
float,float,float, //directrion
float,float,float,float) = 0; //RGBA
float,float,float, //directrion
float,float,float,float, //diffuse RGBA
float,float,float,float) = 0; //ambient RGBA
virtual void set_lighting(bool) = 0;
virtual void set_blend(bool) = 0;
virtual void restore_state(unsigned int) = 0;
@@ -101,8 +102,8 @@ public:
bool have_to_do_transparency() const {return m_have_to_do_transparency;}
bool have_to_render() {
bool transparent = state().m_color.a()!=1?true:false;
if(transparent) {
bool transparent = state().m_color.a()!=1.0f?true:false;
if(transparent && state().m_GL_BLEND) {
if(m_do_transparency) return true;
m_have_to_do_transparency = true;
return false;
@@ -130,10 +131,11 @@ public:
void enable_light(unsigned int a_light,
const vec3f& a_dir,
const colorf& a_col) {
const colorf& a_col,const colorf& a_ambient) {
enable_light(a_light,
a_dir[0],a_dir[1],a_dir[2],
a_col[0],a_col[1],a_col[2],1);
a_col[0],a_col[1],a_col[2],a_col[3],
a_ambient[0],a_ambient[1],a_ambient[2],a_ambient[3]);
}
void draw_vertex_array(gl::mode_t a_mode,const std::vector<float>& a_xyzs){
+9 -3
View File
@@ -19,13 +19,15 @@ class torche : public node {
TOOLS_NODE(torche,tools::sg::torche,node)
public:
sf_vec<colorf,float> color;
sf_vec<colorf,float> ambient;
sf_vec3f direction;
sf<bool> on;
public:
virtual const desc_fields& node_desc_fields() const {
TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::torche)
static const desc_fields s_v(parent::node_desc_fields(),3, //WARNING : take care of count.
static const desc_fields s_v(parent::node_desc_fields(),4, //WARNING : take care of count.
TOOLS_ARG_FIELD_DESC(color),
TOOLS_ARG_FIELD_DESC(ambient),
TOOLS_ARG_FIELD_DESC(direction),
TOOLS_ARG_FIELD_DESC(on)
);
@@ -34,6 +36,7 @@ public:
private:
void add_fields(){
add_field(&color);
add_field(&ambient);
add_field(&direction);
add_field(&on);
}
@@ -47,14 +50,15 @@ public:
<< std::endl;
return;
}
state.m_GL_LIGHTING = true; //for separator
a_action.enable_light(state.m_light,direction.value(),color.value());
state.m_GL_LIGHTING = true;
a_action.enable_light(state.m_light,direction.value(),color.value(),ambient.value());
state.m_light++;
}
public:
torche()
:parent()
,color(colorf_white())
,ambient(colorf_black())
,direction(vec3f(0,0,-1))
,on(true)
{
@@ -65,6 +69,7 @@ public:
torche(const torche& a_from)
:parent(a_from)
,color(a_from.color)
,ambient(a_from.ambient)
,direction(a_from.direction)
,on(a_from.on)
{
@@ -73,6 +78,7 @@ public:
torche& operator=(const torche& a_from){
parent::operator=(a_from);
color = a_from.color;
ambient = a_from.ambient;
direction = a_from.direction;
on = a_from.on;
return *this;
+86 -11
View File
@@ -14,9 +14,9 @@
// gl2ps_tex: gl2ps producing tex
// gl2ps_pgf: gl2ps producing pgf
// By using the zb_action (zb for zbuffer):
// zb_ps: tools::sg offscreen zbuffer put in a PostScript file.
// zb_png: zbuffer put in a png file. It needs to provide a "png_writer" function.
// zb_jpeg: zbuffer put in a jpeg file. It needs to provide a "jpeg_writer" function.
// inzb_ps: tools::sg offscreen zbuffer put in a PostScript file.
// inzb_png: zbuffer put in a png file. It needs to provide a "png_writer" function.
// inzb_jpeg: zbuffer put in a jpeg file. It needs to provide a "jpeg_writer" function.
#include "zb_action"
#include "node"
@@ -40,25 +40,70 @@ inline bool write_paper(std::ostream& a_out,
float a_back_r,float a_back_g,float a_back_b,float a_back_a,
node& a_scene_graph,
unsigned int a_width,unsigned int a_height,
const std::string& a_file,const std::string& a__format) {
const std::string& a_file,const std::string& a__format,
bool a_do_transparency,
bool a_top_to_bottom,
const std::string& a_opts_1,const std::string& a_opts_2) {
if(!a_width || !a_height) return false;
std::string a_format = a__format;
tolowercase(a_format); //handle legacy.
int gl2ps_format;
if(s2format(a_format,gl2ps_format)) {
if(gl2ps_s2format(a_format,gl2ps_format)) {
int sort = -1;
if(a_opts_1.size() && !gl2ps_s2sort(a_opts_1,sort)) {
a_out << "tools::sg::write_paper: bad gl2ps sort " << sout(a_opts_1) << "." << std::endl;
return false;
}
int options = -1;
if(a_opts_2.size() && !gl2ps_s2options(a_opts_2,options)) {
a_out << "tools::sg::write_paper: bad gl2ps options " << sout(a_opts_2) << "." << std::endl;
return false;
}
gl2ps_action action(a_gl2ps_mgr,a_out,a_width,a_height);
action.clear_color(a_back_r,a_back_g,a_back_b,a_back_a);
if(!action.open(a_file,gl2ps_format)) return false;
if(!action.open(a_file,gl2ps_format,sort,options)) return false;
action.set_do_transparency(false);
action.set_have_to_do_transparency(false);
a_scene_graph.render(action);
if(!action.end()) { //check that matrices stack are ok.
a_out << "tools::sg::write_paper: bad gl2ps_action end." << std::endl;
action.close();
return false;
} else if(a_do_transparency) {
if(action.have_to_do_transparency()) {
//a_out << "tools::sg::write_paper: warning: gl2ps does not handle transparency." << std::endl;
action.set_do_transparency(true);
a_scene_graph.render(action);
if(!action.end()) { //check that matrices stack are ok.
a_out << "tools::sg::write_paper: bad gl2ps_action end." << std::endl;
action.close();
return false;
}
}
}
action.close();
return true;
}
zb_action action(a_zb_mgr,a_out,a_width,a_height);
action.zbuffer().clear_color_buffer(0);
action.add_color(a_back_r,a_back_g,a_back_b,a_back_a);
action.zbuffer().clear_depth_buffer();
action.clear_color_buffer(a_back_r,a_back_g,a_back_b,a_back_a);
action.clear_depth_buffer();
action.set_do_transparency(false);
action.set_have_to_do_transparency(false);
a_scene_graph.render(action);
if(!action.end()) { //check that matrices stack are ok.
a_out << "tools::sg::write_paper: bad zb_action end." << std::endl;
return false;
} else if(a_do_transparency) {
if(action.have_to_do_transparency()) {
action.set_do_transparency(true);
a_scene_graph.render(action);
if(!action.end()) { //check that matrices stack are ok.
a_out << "tools::sg::write_paper: bad zb_action end." << std::endl;
return false;
}
}
}
if((a_format=="zb_ps")||(a_format=="inzb_ps")) {
wps wps(a_out);
@@ -81,7 +126,7 @@ inline bool write_paper(std::ostream& a_out,
}
size_t sz;
unsigned char* buffer = action.get_rgbas(sz);
unsigned char* buffer = action.get_rgbas(sz,a_top_to_bottom);
if(!buffer) {
a_out << "tools::sg::write_paper : can't get rgba image." << std::endl;
return false;
@@ -104,7 +149,7 @@ inline bool write_paper(std::ostream& a_out,
}
size_t sz;
unsigned char* buffer = action.get_rgbs(sz);
unsigned char* buffer = action.get_rgbs(sz,a_top_to_bottom);
if(!buffer) {
a_out << "tools::sg::write_paper : can't get rgb image." << std::endl;
return false;
@@ -123,6 +168,36 @@ inline bool write_paper(std::ostream& a_out,
return false;
}
inline bool write_paper(std::ostream& a_out,
gl2ps_manager& a_gl2ps_mgr,zb_manager& a_zb_mgr,
png_writer a_png_writer,jpeg_writer a_jpeg_writer,
const tools::colorf& a_back,
node& a_scene_graph,
unsigned int a_width,unsigned int a_height,
const std::string& a_file,const std::string& a_format,
bool a_do_transparency,bool a_top_to_bottom,
const std::string& a_opts_1,const std::string& a_opts_2) {
return tools::sg::write_paper(a_out,a_gl2ps_mgr,a_zb_mgr,
a_png_writer,a_jpeg_writer,
a_back.r(),a_back.g(),a_back.b(),a_back.a(),
a_scene_graph,a_width,a_height,a_file,a_format,
a_do_transparency,a_top_to_bottom,a_opts_1,a_opts_2);
}
inline bool write_paper(std::ostream& a_out,
gl2ps_manager& a_gl2ps_mgr,zb_manager& a_zb_mgr,
png_writer a_png_writer,jpeg_writer a_jpeg_writer,
const tools::colorf& a_back,
node& a_scene_graph,
unsigned int a_width,unsigned int a_height,
const std::string& a_file,const std::string& a_format) {
return tools::sg::write_paper(a_out,a_gl2ps_mgr,a_zb_mgr,
a_png_writer,a_jpeg_writer,
a_back.r(),a_back.g(),a_back.b(),a_back.a(),
a_scene_graph,a_width,a_height,a_file,a_format,
true,true,std::string(),std::string());
}
}}
#endif
+234 -248
View File
@@ -12,13 +12,10 @@
#include "../zb/buffer"
#include "../colorfs"
#include "../lina/plane"
#include "../mathf"
#include "../hls"
#include "../colorfs"
#include "../lina/vec2f"
#include "../lina/vec3d" //ZZ=double
#include "../lina/geom2"
namespace tools {
namespace sg {
@@ -54,8 +51,9 @@ public:
}
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);
zb::buffer::ZPixel pix;
zb::buffer::rgba2pix(a_r,a_g,a_b,a_a,pix);
m_zb.clear_color_buffer(pix);
}
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);
@@ -80,32 +78,38 @@ public:
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 void load_model_matrix(const mat4f& a_mtx) {
m_model = a_mtx;
set_normal_matrix();
}
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){
float a_r,float a_g,float a_b,float a_a,
float a_ar,float a_ag,float a_ab,float a_aa){
m_light_color.set_value(a_r,a_g,a_b,a_a);
m_light_ambient.set_value(a_ar,a_ag,a_ab,a_aa);
m_light_direction.set_value(a_dx,a_dy,a_dz);
m_light_direction.normalize();
m_light_on = true;
}
virtual void set_lighting(bool a_on) {m_light_on = a_on;}
virtual void set_blend(bool) {}
virtual void set_lighting(bool a_value) {m_light_on = a_value;}
virtual void set_blend(bool a_value) {m_blend = a_value;}
virtual void restore_state(unsigned int /*a_ret_num_light*/) {
const sg::state& _state = state();
m_proj = _state.m_proj;
m_model = _state.m_model;
if(!m_proj.invert(m_proj_1)){}
set_normal_matrix();
m_rgba = _state.m_color;
m_normal = _state.m_normal;
m_ccw = (_state.m_winding==winding_ccw?true:false);
m_POLYGON_OFFSET_FILL = _state.m_GL_POLYGON_OFFSET_FILL;
m_CULL_FACE = _state.m_GL_CULL_FACE;
@@ -115,7 +119,7 @@ public:
m_point_size = _state.m_point_size;
m_light_on = _state.m_GL_LIGHTING;
m_DEPTH_TEST = _state.m_GL_DEPTH_TEST;
m_blend = _state.m_GL_BLEND;
/*
if(_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
@@ -166,6 +170,7 @@ public:
,m_mgr(a_mgr)
,m_pv(get_me())
,m_light_color(colorf_white())
,m_light_ambient(colorf_black())
,m_light_direction(vec3f(0,0,-1))
,m_normal(0,0,1)
@@ -178,14 +183,19 @@ public:
,m_point_size(1)
,m_light_on(false)
,m_DEPTH_TEST(true)
,m_blend(false)
{
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();
//m_zb.clear_color_buffer(0);
//m_zb.clear_depth_buffer();
m_proj.set_identity();
m_model.set_identity();
m_normal_matrix.set_identity();
}
virtual ~zb_action(){}
protected:
@@ -193,15 +203,15 @@ protected:
:parent(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_ambient(a_from.m_light_ambient)
,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_normal_matrix(a_from.m_normal_matrix)
,m_rgba(a_from.m_rgba)
,m_ccw(a_from.m_ccw)
,m_POLYGON_OFFSET_FILL(a_from.m_POLYGON_OFFSET_FILL)
@@ -212,19 +222,20 @@ protected:
,m_point_size(a_from.m_point_size)
,m_light_on(a_from.m_light_on)
,m_DEPTH_TEST(a_from.m_DEPTH_TEST)
,m_blend(a_from.m_blend)
{}
zb_action& operator=(const zb_action& a_from){
parent::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_ambient = a_from.m_light_ambient;
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_normal_matrix = a_from.m_normal_matrix;
m_rgba = a_from.m_rgba;
m_ccw = a_from.m_ccw;
m_POLYGON_OFFSET_FILL = a_from.m_POLYGON_OFFSET_FILL;
@@ -235,148 +246,124 @@ protected:
m_point_size = a_from.m_point_size;
m_light_on = a_from.m_light_on;
m_DEPTH_TEST = a_from.m_DEPTH_TEST;
m_blend = a_from.m_blend;
return *this;
}
public:
void reset() {
m_cmap.clear();
m_rcmap.clear();
}
void reset() {}
const zb::buffer& zbuffer() const {return m_zb;}
zb::buffer& zbuffer() {return m_zb;}
void clear_color_buffer(float a_r,float a_g,float a_b,float a_a){
clear_color(a_r,a_g,a_b,a_a);
}
void clear_color_buffer(const colorf& a_color){
clear_color(a_color.r(),a_color.g(),a_color.b(),a_color.a());
}
void clear_depth_buffer() {m_zb.clear_depth_buffer();}
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 : zb_action::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 = (zb::buffer::ZPixel)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);
}
bool find_color(zb::buffer::ZPixel a_pix,colorf& a_rgba) const {
cmap_t::const_iterator it;
for(it=m_cmap.begin();it!=m_cmap.end();++it){
if((*it).second==a_pix) {a_rgba = (*it).first;return true;}
}
return false;
}
typedef std::map<zb::buffer::ZPixel,colorf> rcmap_t;
const rcmap_t& rcolormap() const {return m_rcmap;}
rcmap_t& rcolormap() {return m_rcmap;}
typedef unsigned char uchar;
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;
}
static void color2pix(const colorf& a_rgba,zb::buffer::ZPixel& a_pix) {
zb::buffer::rgba2pix(a_rgba.r(),a_rgba.g(),a_rgba.b(),a_rgba.a(),a_pix);
}
public:
//typedef wps::VCol VCol;
typedef float VCol;
zb::buffer::ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {return m_zb.get_color_buffer(a_width,a_height);}
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 wps.
zb_action* rzb = (zb_action*)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;
}
unsigned char* get_rgbas(size_t& a_sz) {
unsigned char* get_rgbas(size_t& a_sz,bool a_top_to_bottom = true) {
if(!m_ww || !m_wh) {a_sz = 0;return 0;}
a_sz = 4 * m_ww * m_wh;
typedef unsigned char uchar;
uchar* rgbas = new uchar[a_sz];
if(!rgbas) {a_sz = 0;return 0;}
uchar* pos = rgbas;
VCol r,g,b;
VCol a = 1;
zb::buffer::ZPixel pix;
uchar* _pix = 0;
for(unsigned int row=0;row<m_wh;row++) {
for(unsigned int col=0;col<m_ww;col++) {
get_rgb(this,col,m_wh-row-1,r,g,b);
*pos = (uchar)(r*255.0F);pos++;
*pos = (uchar)(g*255.0F);pos++;
*pos = (uchar)(b*255.0F);pos++;
*pos = (uchar)(a*255.0F);pos++;
if(!m_zb.get_clipped_pixel(col,a_top_to_bottom?row:m_wh-1-row,pix)){
m_out << "tools::sg::zb_action::get_rgbas : can't get zbuffer pixel" << std::endl;
*pos = 0xFF;pos++;
*pos = 0x00;pos++;
*pos = 0x00;pos++;
*pos = 0xFF;pos++;
} else {
_pix = (uchar*)&pix;
*pos = *_pix;_pix++;pos++;
*pos = *_pix;_pix++;pos++;
*pos = *_pix;_pix++;pos++;
*pos = *_pix;_pix++;pos++;
}
}
}
/*{size_t number = 4 * m_ww * m_wh;
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("zb_action::rgbas : not_255 : %lu\n",count_not_255);}*/
return rgbas;
}
unsigned char* get_rgbs(size_t& a_sz) {
unsigned char* get_rgbs(size_t& a_sz,bool a_top_to_bottom = true) {
if(!m_ww || !m_wh) {a_sz = 0;return 0;}
a_sz = 3 * m_ww * m_wh;
typedef unsigned char uchar;
uchar* rgbs = new uchar[a_sz];
if(!rgbs) {a_sz = 0;return 0;}
uchar* pos = rgbs;
VCol r,g,b;
zb::buffer::ZPixel pix;
uchar* _pix = 0;
for(unsigned int row=0;row<m_wh;row++) {
for(unsigned int col=0;col<m_ww;col++) {
get_rgb(this,col,m_wh-row-1,r,g,b);
*pos = (uchar)(r*255.0F);pos++;
*pos = (uchar)(g*255.0F);pos++;
*pos = (uchar)(b*255.0F);pos++;
if(!m_zb.get_clipped_pixel(col,a_top_to_bottom?row:m_wh-1-row,pix)){
m_out << "tools::sg::zb_action::get_rgbs : can't get zbuffer pixel" << std::endl;
*pos = 0xFF;pos++;
*pos = 0x00;pos++;
*pos = 0x00;pos++;
} else {
_pix = (uchar*)&pix;
*pos = *_pix;_pix++;pos++;
*pos = *_pix;_pix++;pos++;
*pos = *_pix;_pix++;pos++;
}
}
}
return rgbs;
}
public:
static bool get_rgb(void* a_tag,unsigned int a_col,unsigned int a_row,float& a_r,float& a_g,float& a_b){
//used with wps.
zb_action* rzb = (zb_action*)a_tag;
zb::buffer::ZPixel pix;
if(!rzb->m_zb.get_clipped_pixel(a_col,rzb->wh()-1-a_row,pix)){
rzb->out() << "tools::sg;:zb_action::get_rgb: can't get zbuffer pixel" << std::endl;
a_r = 1;
a_g = 0;
a_b = 0;
return false;
}
float a;
zb::buffer::pix2rgba(pix,a_r,a_g,a_b,a);
return true;
}
static bool get_rgba(void* a_tag,unsigned int a_col,unsigned int a_row,float& a_r,float& a_g,float& a_b,float& a_a){
zb_action* rzb = (zb_action*)a_tag;
zb::buffer::ZPixel pix;
if(!rzb->m_zb.get_clipped_pixel(a_col,rzb->wh()-1-a_row,pix)){
rzb->out() << "tools::sg;:zb_action::get_rgba : can't get zbuffer pixel" << std::endl;
a_r = 1;
a_g = 0;
a_b = 0;
a_a = 1;
return false;
}
zb::buffer::pix2rgba(pix,a_r,a_g,a_b,a_a);
return true;
}
protected:
void set_normal_matrix() {
mat4f tmp(m_model);
tmp.no_translate();
if(!tmp.invert(m_normal_matrix)) {
m_out << "tools::sg::zb_action::set_normal_matrix : can't invert model matrix." << std::endl;
}
m_normal_matrix.transpose();
}
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);
@@ -396,10 +383,10 @@ protected:
class primvis : public primitive_visitor {
protected:
virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) {
return m_zb_action.project_point(a_x,a_y,a_z,a_w);
return m_this.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_zb_action.m_rgba);
return _add_point(a_x,a_y,a_z,m_this.m_rgba);
}
virtual bool add_point(float a_x,float a_y,float a_z,float,
@@ -410,8 +397,8 @@ protected:
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_zb_action.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
m_zb_action.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
m_this.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
m_this.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
a_bz *= -1;
a_ez *= -1;
@@ -421,8 +408,12 @@ protected:
zb::point end;
zinit(end,a_ex,a_ey,a_ez);
m_zb_action.m_zb.set_depth_test(m_zb_action.m_DEPTH_TEST);
m_zb_action.m_zb.draw_line(beg,end,m_zb_action.get_pix(m_zb_action.m_rgba),npix(m_zb_action.m_line_width));
m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
m_this.m_zb.set_blend(m_this.m_blend);
zb::buffer::ZPixel pix;
color2pix(m_this.m_rgba,pix);
m_this.m_zb.draw_line(beg,end,pix,npix(m_this.m_line_width));
return true;
}
@@ -431,8 +422,8 @@ protected:
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_zb_action.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
m_zb_action.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
m_this.m_vp_mtx.mul_3f(a_bx,a_by,a_bz);
m_this.m_vp_mtx.mul_3f(a_ex,a_ey,a_ez);
a_bz *= -1;
a_ez *= -1;
@@ -442,10 +433,13 @@ protected:
zb::point end;
zinit(end,a_ex,a_ey,a_ez);
m_zb_action.m_zb.set_depth_test(m_zb_action.m_DEPTH_TEST);
m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
m_this.m_zb.set_blend(m_this.m_blend);
// interpolate color with beg,end ?
m_zb_action.m_zb.draw_line(beg,end,m_zb_action.get_pix(colorf(a_br,a_bg,a_bb,a_ba)),npix(m_zb_action.m_line_width));
zb::buffer::ZPixel pix;
zb::buffer::rgba2pix(a_br,a_bg,a_bb,a_ba,pix);
m_this.m_zb.draw_line(beg,end,pix,npix(m_this.m_line_width));
return true;
}
@@ -454,9 +448,18 @@ protected:
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,
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
a_p2x,a_p2y,a_p2z,a_p2w,
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
a_p3x,a_p3y,a_p3z,a_p3w,
m_zb_action.m_rgba);
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
m_this.m_rgba);
}
virtual bool add_triangle(
@@ -474,26 +477,33 @@ protected:
colorf col(r,g,b,a);
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
a_p2x,a_p2y,a_p2z,a_p2w,
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
a_p3x,a_p3y,a_p3z,a_p3w,
m_this.m_normal.x(),
m_this.m_normal.y(),
m_this.m_normal.z(),
col);
}
virtual bool project_normal(float&,float&,float&) {
//return m_zb_action.project_normal(a_x,a_y,a_z);
//return m_this.project_normal(a_x,a_y,a_z);
return true;
}
virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
float /*a_nx*/,float /*a_ny*/,float /*a_nz*/) {
add_point(a_x,a_y,a_z,a_w);
//m_this.m_points.add_normal(a_nx,a_ny,a_nz);
return true;
}
virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
float /*a_nx*/,float /*a_ny*/,float /*a_nz*/,
float a_r,float a_g,float a_b,float a_a) {
add_point(a_x,a_y,a_z,a_w,a_r,a_g,a_b,a_a);
//m_this.m_points.add_normal(a_nx,a_ny,a_nz);
return true;
}
virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw,
@@ -501,8 +511,6 @@ protected:
float a_ex,float a_ey,float a_ez,float a_ew,
float /*a_enx*/,float /*a_eny*/,float /*a_enz*/) {
add_line(a_bx,a_by,a_bz,a_bw, a_ex,a_ey,a_ez,a_ew);
//m_this.m_lines.add_normal(a_bnx,a_bny,a_bnz);
//m_this.m_lines.add_normal(a_enx,a_eny,a_enz);
return true;
}
virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw,
@@ -512,53 +520,58 @@ protected:
float /*a_enx*/,float /*a_eny*/,float /*a_enz*/,
float a_er,float a_eg,float a_eb,float a_ea){
add_line(a_bx,a_by,a_bz,a_bw, a_br,a_bg,a_bb,a_ba, a_ex,a_ey,a_ez,a_ew, a_er,a_eg,a_eb,a_ea);
//m_this.m_lines.add_normal(a_bnx,a_bny,a_bnz);
//m_this.m_lines.add_normal(a_enx,a_eny,a_enz);
return true;
}
virtual bool add_triangle_normal(
float a_p1x,float a_p1y,float a_p1z,float a_p1w,
float /*a_n1x*/,float /*a_n1y*/,float /*a_n1z*/,
float a_n1x,float a_n1y,float a_n1z,
float a_p2x,float a_p2y,float a_p2z,float a_p2w,
float /*a_n2x*/,float /*a_n2y*/,float /*a_n2z*/,
float a_n2x,float a_n2y,float a_n2z,
float a_p3x,float a_p3y,float a_p3z,float a_p3w,
float /*a_n3x*/,float /*a_n3y*/,float /*a_n3z*/) {
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_this.m_triangles.add_normal(a_n1x,a_n1y,a_n1z);
//m_this.m_triangles.add_normal(a_n2x,a_n2y,a_n2z);
//m_this.m_triangles.add_normal(a_n3x,a_n3y,a_n3z);
float a_n3x,float a_n3y,float a_n3z) {
return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
a_n1x,a_n1y,a_n1z,
a_p2x,a_p2y,a_p2z,a_p2w,
a_n2x,a_n2y,a_n2z,
a_p3x,a_p3y,a_p3z,a_p3w,
a_n3x,a_n3y,a_n3z,
m_this.m_rgba);
return true;
}
virtual bool add_triangle_normal(
float a_p1x,float a_p1y,float a_p1z,float a_p1w,
float /*a_n1x*/,float /*a_n1y*/,float /*a_n1z*/,
float a_n1x,float a_n1y,float a_n1z,
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_n2x*/,float /*a_n2y*/,float /*a_n2z*/,
float a_n2x,float a_n2y,float a_n2z,
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_n3x*/,float /*a_n3y*/,float /*a_n3z*/,
float a_n3x,float a_n3y,float a_n3z,
float a_r3,float a_g3,float a_b3,float a_a3){
add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
a_r1,a_g1,a_b1,a_a1,
a_p2x,a_p2y,a_p2z,a_p2w,
a_r2,a_g2,a_b2,a_a2,
a_p3x,a_p3y,a_p3z,a_p3w,
a_r3,a_g3,a_b3,a_a3);
//m_this.m_triangles.add_normal(a_n1x,a_n1y,a_n1z);
//m_this.m_triangles.add_normal(a_n2x,a_n2y,a_n2z);
//m_this.m_triangles.add_normal(a_n3x,a_n3y,a_n3z);
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_n1x,a_n1y,a_n1z,
a_p2x,a_p2y,a_p2z,a_p2w,
a_n2x,a_n2y,a_n2z,
a_p3x,a_p3y,a_p3z,a_p3w,
a_n3x,a_n3y,a_n3z,
col);
return true;
}
public:
primvis(zb_action& a_zb):m_zb_action(a_zb){}
primvis(zb_action& a_zb):m_this(a_zb){}
virtual ~primvis(){}
public:
primvis(const primvis& a_from)
:primitive_visitor(a_from)
,m_zb_action(a_from.m_zb_action)
,m_this(a_from.m_this)
{}
primvis& operator=(const primvis& a_from){
primitive_visitor::operator=(a_from);
@@ -586,55 +599,45 @@ protected:
}
bool _add_point(float a_x,float a_y,float a_z,const colorf& a_color){
m_zb_action.m_zb.set_depth_test(m_zb_action.m_DEPTH_TEST);
m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
m_this.m_zb.set_blend(m_this.m_blend);
m_zb_action.m_vp_mtx.mul_3f(a_x,a_y,a_z);
m_this.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);
float alpha = a_color.a();
zb::buffer::ZPixel px;
if(alpha<1.0f) {
zb::buffer::ZPixel old_px = 0;
if(!m_zb_action.m_zb.get_pixel(p,old_px)) return false;
colorf old_color;
if(!m_zb_action.find_color(old_px,old_color)) return false;
float one_alpha = 1.0f-alpha;
colorf _color;
_color.set_r(a_color.r()*alpha+old_color.r()*one_alpha);
_color.set_g(a_color.g()*alpha+old_color.g()*one_alpha);
_color.set_b(a_color.b()*alpha+old_color.b()*one_alpha);
px = m_zb_action.get_pix(_color);
} else {
px = m_zb_action.get_pix(a_color);
}
m_zb_action.m_zb.draw_point(p,px,npix(m_zb_action.m_point_size));
zb::buffer::ZPixel pix;
color2pix(a_color,pix);
m_this.m_zb.draw_point(p,pix,npix(m_this.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,
bool _add_triangle(float a_p1x,float a_p1y,float a_p1z,float /*a_p1w*/,
float a_n1x,float a_n1y,float a_n1z,
float a_p2x,float a_p2y,float a_p2z,float /*a_p2w*/,
float a_n2x,float a_n2y,float a_n2z,
float a_p3x,float a_p3y,float a_p3z,float /*a_p3w*/,
float a_n3x,float a_n3y,float a_n3z,
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_zb_action.m_vp_mtx.mul_3f(p1x,p1y,p1z);
m_zb_action.m_vp_mtx.mul_3f(p2x,p2y,p2z);
m_zb_action.m_vp_mtx.mul_3f(p3x,p3y,p3z);
m_this.m_vp_mtx.mul_3f(p1x,p1y,p1z);
m_this.m_vp_mtx.mul_3f(p2x,p2y,p2z);
m_this.m_vp_mtx.mul_3f(p3x,p3y,p3z);
p1z *= -1;
p2z *= -1;
p3z *= -1;
if(m_zb_action.m_POLYGON_OFFSET_FILL){
if(m_this.m_POLYGON_OFFSET_FILL){
//note : gopaw pawex9,14,15,21 with "lego" (drawing cubes) are sensitive to the below epsil.
// zs are in [-1,1]
float epsil = 1e-5f;
//float epsil = 1e-4f;
float epsil = 1e-4f;
p1z -= epsil;
p2z -= epsil;
p3z -= epsil;
@@ -654,8 +657,8 @@ protected:
ZZ C = pn.normal()[2];
if(m_zb_action.m_CULL_FACE){ // check back facing or by the edge :
if(m_zb_action.m_ccw) {
if(m_this.m_CULL_FACE){
if(m_this.m_ccw) {
if(C<=0) return true;
} else {
if(C>=0) return true;
@@ -674,67 +677,50 @@ protected:
zinit(list[1],p2x,p2y,p2z);
zinit(list[2],p3x,p3y,p3z);
m_zb_action.m_zb.set_depth_test(m_zb_action.m_DEPTH_TEST);
m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
m_this.m_zb.set_blend(m_this.m_blend);
if(m_zb_action.m_light_on) {
colorf frag_color = 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;
if(m_this.m_light_on) { // same logic as toolx/wasm/webgl.js:
_p1x *= _p1w;_p1y *= _p1w;_p1z *= _p1w;
_p2x *= _p2w;_p2y *= _p2w;_p2z *= _p2w;
_p3x *= _p3w;_p3y *= _p3w;_p3z *= _p3w;
float nx = (a_n1x+a_n2x+a_n3x)/3.0f;
float ny = (a_n1y+a_n2y+a_n3y)/3.0f;
float nz = (a_n1z+a_n2z+a_n3z)/3.0f;
m_zb_action.m_proj_1.mul_4f(_p1x,_p1y,_p1z,_p1w);
m_zb_action.m_proj_1.mul_4f(_p2x,_p2y,_p2z,_p2w);
m_zb_action.m_proj_1.mul_4f(_p3x,_p3y,_p3z,_p3w);
m_this.m_normal_matrix.mul_dir_3f(nx,ny,nz);
plane<vec3d> _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_zb_action.m_light_direction;
float dx = m_zb_action.m_light_direction.x();
float dy = m_zb_action.m_light_direction.y();
float dz = m_zb_action.m_light_direction.z();
m_zb_action.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;
vec3f _normal(nx,ny,nz);_normal.normalize();
// colorf c
// (a_color.r()*dot,a_color.g()*dot,a_color.b()*dot,a_color.a());
float _dot = _normal.dot(m_this.m_light_direction);
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);
if(_dot<0.0f) {
_dot *= -1.0f;
colorf c(r,g,b,a_color.a());
colorf _tmp = m_this.m_light_color;
_tmp *= _dot;
// _tmp *= 1.4f; //to have same intensity as GL on desktops.
_tmp += m_this.m_light_ambient;
m_zb_action.m_zb.draw_polygon(3,list,A,B,C,D,m_zb_action.get_pix(c));
//m_zb_action.m_zb.draw_polygon(3,list,A,B,C,D,m_zb_action.get_pix(a_color));
}
}
}
frag_color *= _tmp;
} else {
frag_color *= m_this.m_light_ambient;
}
frag_color.clamp();
frag_color.set_a(a_color.a());
} else {
m_zb_action.m_zb.draw_polygon(3,list,A,B,C,D,m_zb_action.get_pix(a_color));
}
zb::buffer::ZPixel pix;
color2pix(frag_color,pix);
m_this.m_zb.draw_polygon(3,list,A,B,C,D,pix);
return true;
}
protected:
zb_action& m_zb_action;
zb_action& m_this;
};
protected:
@@ -742,16 +728,15 @@ protected:
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;
colorf m_light_ambient;
vec3f m_light_direction;
vec3f m_normal;
// to be restored in restore_state() :
mat4f m_proj;
mat4f m_model;
mat4f m_normal_matrix;
colorf m_rgba;
bool m_ccw;
bool m_POLYGON_OFFSET_FILL;
@@ -762,6 +747,7 @@ protected:
float m_point_size;
bool m_light_on;
bool m_DEPTH_TEST;
bool m_blend;
};
}}
+5 -5
View File
@@ -203,7 +203,7 @@ protected:
static int TMath_FloorNint(double x) { return TMath_Nint(::floor(x)); }
size_t find_x(double x) const {
int klow=0, khig=fNp-1;
int klow=0, khig=int(fNp-1);
//
// If out of boundaries, extrapolate
// It may be badly wrong
@@ -277,7 +277,7 @@ protected:
// f at tau(i), i=1,...,n, is generated and then solved by gauss elim-
// ination, with s(i) ending up in c(2,i), all i.
// c(3,.) and c(4,.) are used initially for temporary storage.
l = fNp-1;
l = int(fNp-1);
// compute first differences of x sequence and store in C also,
// compute first divided difference of data and store in D.
{for (size_t m=1; m<fNp ; ++m) {
@@ -450,12 +450,12 @@ protected:
// If out of boundaries, extrapolate
// It may be badly wrong
if(x<=fXmin) klow=0;
else if(x>=fXmax) klow=fNp-1;
else if(x>=fXmax) klow=int(fNp-1);
else {
if(fKstep) { // Equidistant knots, use histogramming :
klow = mn<int>(int((x-fXmin)/fDelta),fNp-1);
klow = mn<int>(int((x-fXmin)/fDelta),int(fNp-1));
} else {
int khig=fNp-1;
int khig=int(fNp-1);
int khalf;
// Non equidistant knots, binary search
while((khig-klow)>1) {
+116
View File
@@ -0,0 +1,116 @@
#ifndef tools_toojpeg
#define tools_toojpeg
// G.Barrand: pure header version of toojpeg found at https://github.com/stbrumme/toojpeg
// The original namespace TooJpeg had been changed to tools::toojpeg to avoid
// clashes with potential other usage of toojpeg within the same software.
/*
zlib License
Copyright (c) 2011-2016 Stephan Brumme
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// //////////////////////////////////////////////////////////
// toojpeg.h
// written by Stephan Brumme, 2018-2019
// see https://create.stephan-brumme.com/toojpeg/
//
// This is a compact baseline JPEG/JFIF writer, written in C++ (but looks like C for the most part).
// Its interface has only one function: writeJpeg() - and that's it !
namespace tools {
namespace toojpeg
{
// write one byte (to disk, memory, ...)
typedef void (*WRITE_ONE_BYTE)(unsigned char,void*);
// this callback is called for every byte generated by the encoder and behaves similar to fputc
// if you prefer stylish C++11 syntax then it can be a lambda, too:
// auto myOutput = [](unsigned char oneByte) { fputc(oneByte, output); };
// output - callback that stores a single byte (writes to disk, memory, ...)
// pixels - stored in RGB format or grayscale, stored from upper-left to lower-right
// width,height - image size
// isRGB - true if RGB format (3 bytes per pixel); false if grayscale (1 byte per pixel)
// quality - between 1 (worst) and 100 (best)
// downsample - if true then YCbCr 4:2:0 format is used (smaller size, minor quality loss) instead of 4:4:4, not relevant for grayscale
// comment - optional JPEG comment (0/NULL if no comment), must not contain ASCII code 0xFF
bool writeJpeg(WRITE_ONE_BYTE output,void*, const void* pixels, unsigned short width, unsigned short height,
bool isRGB = true, unsigned char quality = 90, bool downsample = false, const char* comment = 0/*nullptr*/);
}}
// My main inspiration was Jon Olick's Minimalistic JPEG writer
// ( https://www.jonolick.com/code.html => direct link is https://www.jonolick.com/uploads/7/9/2/1/7921194/jo_jpeg.cpp ).
// However, his code documentation is quite sparse - probably because it wasn't written from scratch and is (quote:) "based on a javascript jpeg writer",
// most likely Andreas Ritter's code: https://github.com/eugeneware/jpeg-js/blob/master/lib/encoder.js
//
// Therefore I wrote the whole lib from scratch and tried hard to add tons of comments to my code, especially describing where all those magic numbers come from.
// And I managed to remove the need for any external includes ...
// yes, that's right: my library has no (!) includes at all, not even #include <stdlib.h>
// Depending on your callback WRITE_ONE_BYTE, the library writes either to disk, or in-memory, or wherever you wish.
// Moreover, no dynamic memory allocations are performed, just a few bytes on the stack.
//
// In contrast to Jon's code, compression can be significantly improved in many use cases:
// a) grayscale JPEG images need just a single Y channel, no need to save the superfluous Cb + Cr channels
// b) YCbCr 4:2:0 downsampling is often about 20% more efficient (=smaller) than the default YCbCr 4:4:4 with only little visual loss
//
// TooJpeg 1.2+ compresses about twice as fast as jo_jpeg (and about half as fast as libjpeg-turbo).
// A few benchmark numbers can be found on my website https://create.stephan-brumme.com/toojpeg/#benchmark
//
// Last but not least you can optionally add a JPEG comment.
//
// Your C++ compiler needs to support a reasonable subset of C++11 (g++ 4.7 or Visual C++ 2013 are sufficient).
// I haven't tested the code on big-endian systems or anything that smells like an apple.
//
// USE AT YOUR OWN RISK. Because you are a brave soul :-)
#include "toojpeg.icc"
//G.Barrand specific:
#include "sout"
#include <cstdio>
#include <ostream>
namespace tools {
namespace toojpeg {
inline void write_one_byte(unsigned char a_byte,void* a_tag) {::fputc(a_byte,(FILE*)a_tag);}
inline bool write(std::ostream& a_out,
const std::string& a_file,
unsigned char* a_buffer,
unsigned int a_width,
unsigned int a_height,
unsigned int a_bpp,
int a_quality) {
if(a_bpp!=3) {
a_out << "tools::toojpeg::write : bpp " << a_bpp << " not handled." << std::endl;
return false;
}
FILE* file = ::fopen(a_file.c_str(),"wb");
if(!file) {
a_out << "tools::toojpeg::write : can't open file " << sout(a_file) << "." << std::endl;
return false;
}
if(!writeJpeg(write_one_byte,file,a_buffer,(unsigned short)a_width,(unsigned short)a_height,true,(unsigned char)a_quality)) {
::fclose(file);
a_out << "tools::toojpeg::write : writeJpeg failed for file " << sout(a_file) << "." << std::endl;
return false;
}
::fclose(file);
return true;
}
}}
#endif
+678
View File
@@ -0,0 +1,678 @@
// G.Barrand: pure header version of toojpeg found at https://github.com/stbrumme/toojpeg
// //////////////////////////////////////////////////////////
// toojpeg.cpp
// written by Stephan Brumme, 2018-2019
// see https://create.stephan-brumme.com/toojpeg/
//
#include <cstddef> //size_t
// - the "official" specifications: https://www.w3.org/Graphics/JPEG/itu-t81.pdf and https://www.w3.org/Graphics/JPEG/jfif3.pdf
// - Wikipedia has a short description of the JFIF/JPEG file format: https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
// - the popular STB Image library includes Jon's JPEG encoder as well: https://github.com/nothings/stb/blob/master/stb_image_write.h
// - the most readable JPEG book (from a developer's perspective) is Miano's "Compressed Image File Formats" (1999, ISBN 0-201-60443-4),
// used copies are really cheap nowadays and include a CD with C++ sources as well (plus great format descriptions of GIF & PNG)
// - much more detailled is Mitchell/Pennebaker's "JPEG: Still Image Data Compression Standard" (1993, ISBN 0-442-01272-1)
// which contains the official JPEG standard, too - fun fact: I bought a signed copy in a second-hand store without noticing
namespace tools {
namespace toojpeg {
// ////////////////////////////////////////
// data types
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef int int32_t; // at least four bytes
// ////////////////////////////////////////
// constants
// quantization tables from JPEG Standard, Annex K
const uint8_t DefaultQuantLuminance[8*8] =
{ 16, 11, 10, 16, 24, 40, 51, 61, // there are a few experts proposing slightly more efficient values,
12, 12, 14, 19, 26, 58, 60, 55, // e.g. https://www.imagemagick.org/discourse-server/viewtopic.php?t=20333
14, 13, 16, 24, 40, 57, 69, 56, // btw: Google's Guetzli project optimizes the quantization tables per image
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68,109,103, 77,
24, 35, 55, 64, 81,104,113, 92,
49, 64, 78, 87,103,121,120,101,
72, 92, 95, 98,112,100,103, 99 };
const uint8_t DefaultQuantChrominance[8*8] =
{ 17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99 };
// 8x8 blocks are processed in zig-zag order
// most encoders use a zig-zag "forward" table, I switched to its inverse for performance reasons
// note: ZigZagInv[ZigZag[i]] = i
const uint8_t ZigZagInv[8*8] =
{ 0, 1, 8,16, 9, 2, 3,10, // ZigZag[] = 0, 1, 5, 6,14,15,27,28,
17,24,32,25,18,11, 4, 5, // 2, 4, 7,13,16,26,29,42,
12,19,26,33,40,48,41,34, // 3, 8,12,17,25,30,41,43,
27,20,13, 6, 7,14,21,28, // 9,11,18,24,31,40,44,53,
35,42,49,56,57,50,43,36, // 10,19,23,32,39,45,52,54,
29,22,15,23,30,37,44,51, // 20,22,33,38,46,51,55,60,
58,59,52,45,38,31,39,46, // 21,34,37,47,50,56,59,61,
53,60,61,54,47,55,62,63 }; // 35,36,48,49,57,58,62,63
// static Huffman code tables from JPEG standard Annex K
// - CodesPerBitsize tables define how many Huffman codes will have a certain bitsize (plus 1 because there nothing with zero bits),
// e.g. DcLuminanceCodesPerBitsize[2] = 5 because there are 5 Huffman codes being 2+1=3 bits long
// - Values tables are a list of values ordered by their Huffman code bitsize,
// e.g. AcLuminanceValues => Huffman(0x01,0x02 and 0x03) will have 2 bits, Huffman(0x00) will have 3 bits, Huffman(0x04,0x11 and 0x05) will have 4 bits, ...
// Huffman definitions for first DC/AC tables (luminance / Y channel)
const uint8_t DcLuminanceCodesPerBitsize[16] = { 0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 }; // sum = 12
const uint8_t DcLuminanceValues [12] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; // => 12 codes
const uint8_t AcLuminanceCodesPerBitsize[16] = { 0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125 }; // sum = 162
const uint8_t AcLuminanceValues [162] = // => 162 codes
{ 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08, // 16*10+2 symbols because
0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28, // upper 4 bits can be 0..F
0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59, // while lower 4 bits can be 1..A
0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89, // plus two special codes 0x00 and 0xF0
0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6, // order of these symbols was determined empirically by JPEG committee
0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA };
// Huffman definitions for second DC/AC tables (chrominance / Cb and Cr channels)
const uint8_t DcChrominanceCodesPerBitsize[16] = { 0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; // sum = 12
const uint8_t DcChrominanceValues [12] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; // => 12 codes (identical to DcLuminanceValues)
const uint8_t AcChrominanceCodesPerBitsize[16] = { 0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119 }; // sum = 162
const uint8_t AcChrominanceValues [162] = // => 162 codes
{ 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, // same number of symbol, just different order
0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26, // (which is more efficient for AC coding)
0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,
0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA };
const int16_t CodeWordLimit = 2048; // +/-2^11, maximum value after DCT
// ////////////////////////////////////////
// structs
// represent a single Huffman code
struct BitCode
{
//BitCode() = default; // undefined state, must be initialized at a later time
BitCode():code(0),numBits(0) {}
BitCode(const BitCode& a_from):code(a_from.code),numBits(a_from.numBits) {}
BitCode& operator=(const BitCode& a_from) {
code = a_from.code;
numBits = a_from.numBits;
return *this;
}
BitCode(uint16_t code_, uint8_t numBits_)
: code(code_), numBits(numBits_) {}
uint16_t code; // JPEG's Huffman codes are limited to 16 bits
uint8_t numBits; // number of valid bits
};
// wrapper for bit output operations
struct BitWriter
{
// user-supplied callback that writes/stores one byte
WRITE_ONE_BYTE output;
void* tag;
// initialize writer
explicit BitWriter(WRITE_ONE_BYTE output_,void* tag_) : output(output_),tag(tag_) {
buffer.data = 0;
buffer.numBits = 0;
}
// store the most recently encoded bits that are not written yet
struct BitBuffer
{
int32_t data /*= 0*/; // actually only at most 24 bits are used
uint8_t numBits /*= 0*/; // number of valid bits (the right-most bits)
} buffer;
// write Huffman bits stored in BitCode, keep excess bits in BitBuffer
BitWriter& operator<<(const BitCode& data)
{
// append the new bits to those bits leftover from previous call(s)
buffer.numBits += data.numBits;
buffer.data <<= data.numBits;
buffer.data |= data.code;
// write all "full" bytes
while (buffer.numBits >= 8)
{
// extract highest 8 bits
buffer.numBits -= 8;
uint8_t oneByte = uint8_t(buffer.data >> buffer.numBits);
output(oneByte,tag);
if (oneByte == 0xFF) // 0xFF has a special meaning for JPEGs (it's a block marker)
output(0,tag); // therefore pad a zero to indicate "nope, this one ain't a marker, it's just a coincidence"
// note: I don't clear those written bits, therefore buffer.bits may contain garbage in the high bits
// if you really want to "clean up" (e.g. for debugging purposes) then uncomment the following line
//buffer.bits &= (1 << buffer.numBits) - 1;
}
return *this;
}
// write all non-yet-written bits, fill gaps with 1s (that's a strange JPEG thing)
void flush()
{
// at most seven set bits needed to "fill" the last byte: 0x7F = binary 0111 1111
*this << BitCode(0x7F, 7); // I should set buffer.numBits = 0 but since there are no single bits written after flush() I can safely ignore it
}
// NOTE: all the following BitWriter functions IGNORE the BitBuffer and write straight to output !
// write a single byte
BitWriter& operator<<(uint8_t oneByte)
{
output(oneByte,tag);
return *this;
}
// write an array of bytes
template <typename T, int Size>
BitWriter& operator<<(T (&manyBytes)[Size])
{
//for (auto c : manyBytes)
// output(c);
for(size_t i=0;i<Size;i++) output(manyBytes[i],tag);
return *this;
}
// start a new JFIF block
void addMarker(uint8_t id, uint16_t length)
{
output(0xFF,tag); output(id,tag); // ID, always preceded by 0xFF
output(uint8_t(length >> 8),tag); // length of the block (big-endian, includes the 2 length bytes as well)
output(uint8_t(length & 0xFF),tag);
}
};
// ////////////////////////////////////////
// functions / templates
// same as std::min()
template <typename Number>
inline Number minimum(Number value, Number maximum)
{
return value <= maximum ? value : maximum;
}
// restrict a value to the interval [minimum, maximum]
template <typename Number, typename Limit>
inline Number clamp(Number value, Limit minValue, Limit maxValue)
{
if (value <= minValue) return minValue; // never smaller than the minimum
if (value >= maxValue) return maxValue; // never bigger than the maximum
return value; // value was inside interval, keep it
}
// convert from RGB to YCbCr, constants are similar to ITU-R, see https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
inline float rgb2y (float r, float g, float b) { return +0.299f * r +0.587f * g +0.114f * b; }
inline float rgb2cb(float r, float g, float b) { return -0.16874f * r -0.33126f * g +0.5f * b; }
inline float rgb2cr(float r, float g, float b) { return +0.5f * r -0.41869f * g -0.08131f * b; }
// forward DCT computation "in one dimension" (fast AAN algorithm by Arai, Agui and Nakajima: "A fast DCT-SQ scheme for images")
inline void DCT(float block[8*8], uint8_t stride) // stride must be 1 (=horizontal) or 8 (=vertical)
{
const float SqrtHalfSqrt = 1.306562965f; // sqrt((2 + sqrt(2)) / 2) = cos(pi * 1 / 8) * sqrt(2)
const float InvSqrt = 0.707106781f; // 1 / sqrt(2) = cos(pi * 2 / 8)
const float HalfSqrtSqrt = 0.382683432f; // sqrt(2 - sqrt(2)) / 2 = cos(pi * 3 / 8)
const float InvSqrtSqrt = 0.541196100f; // 1 / sqrt(2 - sqrt(2)) = cos(pi * 3 / 8) * sqrt(2)
// modify in-place
float& block0 = block[0 ];
float& block1 = block[1 * stride];
float& block2 = block[2 * stride];
float& block3 = block[3 * stride];
float& block4 = block[4 * stride];
float& block5 = block[5 * stride];
float& block6 = block[6 * stride];
float& block7 = block[7 * stride];
// based on https://dev.w3.org/Amaya/libjpeg/jfdctflt.c , the original variable names can be found in my comments
float add07 = block0 + block7; float sub07 = block0 - block7; // tmp0, tmp7
float add16 = block1 + block6; float sub16 = block1 - block6; // tmp1, tmp6
float add25 = block2 + block5; float sub25 = block2 - block5; // tmp2, tmp5
float add34 = block3 + block4; float sub34 = block3 - block4; // tmp3, tmp4
float add0347 = add07 + add34; float sub07_34 = add07 - add34; // tmp10, tmp13 ("even part" / "phase 2")
float add1256 = add16 + add25; float sub16_25 = add16 - add25; // tmp11, tmp12
block0 = add0347 + add1256; block4 = add0347 - add1256; // "phase 3"
float z1 = (sub16_25 + sub07_34) * InvSqrt; // all temporary z-variables kept their original names
block2 = sub07_34 + z1; block6 = sub07_34 - z1; // "phase 5"
float sub23_45 = sub25 + sub34; // tmp10 ("odd part" / "phase 2")
float sub12_56 = sub16 + sub25; // tmp11
float sub01_67 = sub16 + sub07; // tmp12
float z5 = (sub23_45 - sub01_67) * HalfSqrtSqrt;
float z2 = sub23_45 * InvSqrtSqrt + z5;
float z3 = sub12_56 * InvSqrt;
float z4 = sub01_67 * SqrtHalfSqrt + z5;
float z6 = sub07 + z3; // z11 ("phase 5")
float z7 = sub07 - z3; // z13
block1 = z6 + z4; block7 = z6 - z4; // "phase 6"
block5 = z7 + z2; block3 = z7 - z2;
}
// run DCT, quantize and write Huffman bit codes
inline int16_t encodeBlock(BitWriter& writer, float block[8][8], const float scaled[8*8], int16_t lastDC,
const BitCode huffmanDC[256], const BitCode huffmanAC[256], const BitCode* codewords)
{
// "linearize" the 8x8 block, treat it as a flat array of 64 floats
float* block64 = (float*) block;
// DCT: rows
for (size_t offset = 0; offset < 8; offset++)
DCT(block64 + offset*8, 1);
// DCT: columns
for (size_t offset = 0; offset < 8; offset++)
DCT(block64 + offset*1, 8);
// scale
for (size_t i = 0; i < 8*8; i++)
block64[i] *= scaled[i];
// encode DC (the first coefficient is the "average color" of the 8x8 block)
int DC = int(block64[0] + (block64[0] >= 0 ? +0.5f : -0.5f)); // C++11's nearbyint() achieves a similar effect
// quantize and zigzag the other 63 coefficients
size_t posNonZero = 0; // find last coefficient which is not zero (because trailing zeros are encoded differently)
int16_t quantized[8*8];
for (size_t i = 1; i < 8*8; i++) // start at 1 because block64[0]=DC was already processed
{
float value = block64[ZigZagInv[i]];
// round to nearest integer
quantized[i] = int(value + (value >= 0 ? +0.5f : -0.5f)); // C++11's nearbyint() achieves a similar effect
// remember offset of last non-zero coefficient
if (quantized[i] != 0)
posNonZero = i;
}
// same "average color" as previous block ?
int diff = DC - lastDC;
if (diff == 0)
writer << huffmanDC[0x00]; // yes, write a special short symbol
else
{
const BitCode bits = codewords[diff]; // nope, encode the difference to previous block's average color
writer << huffmanDC[bits.numBits] << bits;
}
// encode ACs (quantized[1..63])
size_t offset = 0; // upper 4 bits count the number of consecutive zeros
for (size_t i = 1; i <= posNonZero; i++) // quantized[0] was already written, skip all trailing zeros, too
{
// zeros are encoded in a special way
while (quantized[i] == 0) // found another zero ?
{
offset += 0x10; // add 1 to the upper 4 bits
// split into blocks of at most 16 consecutive zeros
if (offset > 0xF0) // remember, the counter is in the upper 4 bits, 0xF = 15
{
writer << huffmanAC[0xF0]; // 0xF0 is a special code for "16 zeros"
offset = 0;
}
i++;
}
const BitCode encoded = codewords[quantized[i]];
// combine number of zeros with the number of bits of the next non-zero value
writer << huffmanAC[offset + encoded.numBits] << encoded; // and the value itself
offset = 0;
}
// send end-of-block code (0x00), only needed if there are trailing zeros
if (posNonZero < 8*8 - 1) // = 63
writer << huffmanAC[0x00];
return DC;
}
// Jon's code includes the pre-generated Huffman codes
// I don't like these "magic constants" and compute them on my own :-)
inline void generateHuffmanTable(const uint8_t numCodes[16], const uint8_t* values, BitCode result[256])
{
// process all bitsizes 1 thru 16, no JPEG Huffman code is allowed to exceed 16 bits
uint16_t huffmanCode = 0;
for (uint8_t numBits = 1; numBits <= 16; numBits++)
{
// ... and each code of these bitsizes
for (uint8_t i = 0; i < numCodes[numBits - 1]; i++) // note: numCodes array starts at zero, but smallest bitsize is 1
result[*values++] = BitCode(huffmanCode++, numBits);
// next Huffman code needs to be one bit wider
huffmanCode <<= 1;
}
}
// -------------------- externally visible code --------------------
// the only exported function ...
inline bool writeJpeg(WRITE_ONE_BYTE output, void* tag,const void* pixels_, unsigned short width, unsigned short height,
bool isRGB, unsigned char quality_, bool downsample, const char* comment)
{
// reject invalid pointers
if (output == 0/*nullptr*/ || pixels_ == 0/*nullptr*/)
return false;
// check image format
if (width == 0 || height == 0)
return false;
// number of components
const uint16_t numComponents = isRGB ? 3 : 1;
// note: if there is just one component (=grayscale), then only luminance needs to be stored in the file
// thus everything related to chrominance need not to be written to the JPEG
// I still compute a few things, like quantization tables to avoid a complete code mess
// grayscale images can't be downsampled (because there are no Cb + Cr channels)
if (!isRGB)
downsample = false;
// wrapper for all output operations
BitWriter bitWriter(output,tag);
// ////////////////////////////////////////
// JFIF headers
const uint8_t HeaderJfif[2+2+16] =
{ 0xFF,0xD8, // SOI marker (start of image)
0xFF,0xE0, // JFIF APP0 tag
0,16, // length: 16 bytes (14 bytes payload + 2 bytes for this length field)
'J','F','I','F',0, // JFIF identifier, zero-terminated
1,1, // JFIF version 1.1
0, // no density units specified
0,1,0,1, // density: 1 pixel "per pixel" horizontally and vertically
0,0 }; // no thumbnail (size 0 x 0)
bitWriter << HeaderJfif;
// ////////////////////////////////////////
// comment (optional)
if (comment != 0/*nullptr*/)
{
// look for zero terminator
uint16_t length = 0; // = strlen(comment);
while (comment[length] != 0)
length++;
// write COM marker
bitWriter.addMarker(0xFE, 2+length); // block size is number of bytes (without zero terminator) + 2 bytes for this length field
// ... and write the comment itself
for (uint16_t i = 0; i < length; i++)
bitWriter << comment[i];
}
// ////////////////////////////////////////
// adjust quantization tables to desired quality
// quality level must be in 1 ... 100
uint16_t quality = clamp<uint16_t>(quality_, 1, 100);
// convert to an internal JPEG quality factor, formula taken from libjpeg
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
uint8_t quantLuminance [8*8];
uint8_t quantChrominance[8*8];
for (size_t i = 0; i < 8*8; i++)
{
int luminance = (DefaultQuantLuminance [ZigZagInv[i]] * quality + 50) / 100;
int chrominance = (DefaultQuantChrominance[ZigZagInv[i]] * quality + 50) / 100;
// clamp to 1..255
quantLuminance [i] = clamp(luminance, 1, 255);
quantChrominance[i] = clamp(chrominance, 1, 255);
}
// write quantization tables
bitWriter.addMarker(0xDB, 2 + (isRGB ? 2 : 1) * (1 + 8*8)); // length: 65 bytes per table + 2 bytes for this length field
// each table has 64 entries and is preceded by an ID byte
bitWriter << 0x00 << quantLuminance; // first quantization table
if (isRGB)
bitWriter << 0x01 << quantChrominance; // second quantization table, only relevant for color images
// ////////////////////////////////////////
// write image infos (SOF0 - start of frame)
bitWriter.addMarker(0xC0, 2+6+3*numComponents); // length: 6 bytes general info + 3 per channel + 2 bytes for this length field
// 8 bits per channel
bitWriter << 0x08
// image dimensions (big-endian)
<< (height >> 8) << (height & 0xFF)
<< (width >> 8) << (width & 0xFF);
// sampling and quantization tables for each component
bitWriter << numComponents; // 1 component (grayscale, Y only) or 3 components (Y,Cb,Cr)
for (uint16_t id = 1; id <= numComponents; id++)
bitWriter << id // component ID (Y=1, Cb=2, Cr=3)
// bitmasks for sampling: highest 4 bits: horizontal, lowest 4 bits: vertical
<< (id == 1 && downsample ? 0x22 : 0x11) // 0x11 is default YCbCr 4:4:4 and 0x22 stands for YCbCr 4:2:0
<< (id == 1 ? 0 : 1); // use quantization table 0 for Y, table 1 for Cb and Cr
// ////////////////////////////////////////
// Huffman tables
// DHT marker - define Huffman tables
bitWriter.addMarker(0xC4, isRGB ? (2+208+208) : (2+208));
// 2 bytes for the length field, store chrominance only if needed
// 1+16+12 for the DC luminance
// 1+16+162 for the AC luminance (208 = 1+16+12 + 1+16+162)
// 1+16+12 for the DC chrominance
// 1+16+162 for the AC chrominance (208 = 1+16+12 + 1+16+162, same as above)
// store luminance's DC+AC Huffman table definitions
bitWriter << 0x00 // highest 4 bits: 0 => DC, lowest 4 bits: 0 => Y (baseline)
<< DcLuminanceCodesPerBitsize
<< DcLuminanceValues;
bitWriter << 0x10 // highest 4 bits: 1 => AC, lowest 4 bits: 0 => Y (baseline)
<< AcLuminanceCodesPerBitsize
<< AcLuminanceValues;
// compute actual Huffman code tables (see Jon's code for precalculated tables)
BitCode huffmanLuminanceDC[256];
BitCode huffmanLuminanceAC[256];
generateHuffmanTable(DcLuminanceCodesPerBitsize, DcLuminanceValues, huffmanLuminanceDC);
generateHuffmanTable(AcLuminanceCodesPerBitsize, AcLuminanceValues, huffmanLuminanceAC);
// chrominance is only relevant for color images
BitCode huffmanChrominanceDC[256];
BitCode huffmanChrominanceAC[256];
if (isRGB)
{
// store luminance's DC+AC Huffman table definitions
bitWriter << 0x01 // highest 4 bits: 0 => DC, lowest 4 bits: 1 => Cr,Cb (baseline)
<< DcChrominanceCodesPerBitsize
<< DcChrominanceValues;
bitWriter << 0x11 // highest 4 bits: 1 => AC, lowest 4 bits: 1 => Cr,Cb (baseline)
<< AcChrominanceCodesPerBitsize
<< AcChrominanceValues;
// compute actual Huffman code tables (see Jon's code for precalculated tables)
generateHuffmanTable(DcChrominanceCodesPerBitsize, DcChrominanceValues, huffmanChrominanceDC);
generateHuffmanTable(AcChrominanceCodesPerBitsize, AcChrominanceValues, huffmanChrominanceAC);
}
// ////////////////////////////////////////
// start of scan (there is only a single scan for baseline JPEGs)
bitWriter.addMarker(0xDA, 2+1+2*numComponents+3); // 2 bytes for the length field, 1 byte for number of components,
// then 2 bytes for each component and 3 bytes for spectral selection
// assign Huffman tables to each component
bitWriter << numComponents;
for (uint16_t id = 1; id <= numComponents; id++)
// highest 4 bits: DC Huffman table, lowest 4 bits: AC Huffman table
bitWriter << id << (id == 1 ? 0x00 : 0x11); // Y: tables 0 for DC and AC; Cb + Cr: tables 1 for DC and AC
// constant values for our baseline JPEGs (which have a single sequential scan)
static const uint8_t Spectral[3] = { 0, 63, 0 }; // spectral selection: must be from 0 to 63; successive approximation must be 0
bitWriter << Spectral;
// ////////////////////////////////////////
// adjust quantization tables with AAN scaling factors to simplify DCT
float scaledLuminance [8*8];
float scaledChrominance[8*8];
for (size_t i = 0; i < 8*8; i++)
{
size_t row = ZigZagInv[i] / 8; // same as ZigZagInv[i] >> 3
size_t column = ZigZagInv[i] % 8; // same as ZigZagInv[i] & 7
// scaling constants for AAN DCT algorithm: AanScaleFactors[0] = 1, AanScaleFactors[k=1..7] = cos(k*PI/16) * sqrt(2)
static const float AanScaleFactors[8] = { 1, 1.387039845f, 1.306562965f, 1.175875602f, 1, 0.785694958f, 0.541196100f, 0.275899379f };
float factor = 1 / (AanScaleFactors[row] * AanScaleFactors[column] * 8);
scaledLuminance [ZigZagInv[i]] = factor / quantLuminance [i];
scaledChrominance[ZigZagInv[i]] = factor / quantChrominance[i];
// if you really want JPEGs that are bitwise identical to Jon Olick's code then you need slightly different formulas (note: sqrt(8) = 2.828427125f)
//static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; // line 240 of jo_jpeg.cpp
//scaledLuminance [ZigZagInv[i]] = 1 / (quantLuminance [i] * aasf[row] * aasf[column]); // lines 266-267 of jo_jpeg.cpp
//scaledChrominance[ZigZagInv[i]] = 1 / (quantChrominance[i] * aasf[row] * aasf[column]);
}
// ////////////////////////////////////////
// precompute JPEG codewords for quantized DCT
BitCode codewordsArray[2 * CodeWordLimit]; // note: quantized[i] is found at codewordsArray[quantized[i] + CodeWordLimit]
BitCode* codewords = &codewordsArray[CodeWordLimit]; // allow negative indices, so quantized[i] is at codewords[quantized[i]]
uint8_t numBits = 1; // each codeword has at least one bit (value == 0 is undefined)
int32_t mask = 1; // mask is always 2^numBits - 1, initial value 2^1-1 = 2-1 = 1
for (int16_t value = 1; value < CodeWordLimit; value++)
{
// numBits = position of highest set bit (ignoring the sign)
// mask = (2^numBits) - 1
if (value > mask) // one more bit ?
{
numBits++;
mask = (mask << 1) | 1; // append a set bit
}
codewords[-value] = BitCode(mask - value, numBits); // note that I use a negative index => codewords[-value] = codewordsArray[CodeWordLimit value]
codewords[+value] = BitCode( value, numBits);
}
// just convert image data from void*
const uint8_t* pixels = (const uint8_t*)pixels_;
// the next two variables are frequently used when checking for image borders
const unsigned short maxWidth = width - 1; // "last row"
const unsigned short maxHeight = height - 1; // "bottom line"
// process MCUs (minimum codes units) => image is subdivided into a grid of 8x8 or 16x16 tiles
const unsigned short sampling = downsample ? 2 : 1; // 1x1 or 2x2 sampling
const unsigned short mcuSize = 8 * sampling;
// average color of the previous MCU
int16_t lastYDC = 0, lastCbDC = 0, lastCrDC = 0;
// convert from RGB to YCbCr
float Y[8][8], Cb[8][8], Cr[8][8];
for (unsigned short mcuY = 0; mcuY < height; mcuY += mcuSize) // each step is either 8 or 16 (=mcuSize)
for (unsigned short mcuX = 0; mcuX < width; mcuX += mcuSize)
{
// YCbCr 4:4:4 format: each MCU is a 8x8 block - the same applies to grayscale images, too
// YCbCr 4:2:0 format: each MCU represents a 16x16 block, stored as 4x 8x8 Y-blocks plus 1x 8x8 Cb and 1x 8x8 Cr block)
for (unsigned short blockY = 0; blockY < mcuSize; blockY += 8) // iterate once (YCbCr444 and grayscale) or twice (YCbCr420)
for (unsigned short blockX = 0; blockX < mcuSize; blockX += 8)
{
// now we finally have an 8x8 block ...
for (unsigned short deltaY = 0; deltaY < 8; deltaY++)
{
size_t column = minimum(uint16_t(mcuX + blockX) , maxWidth); // must not exceed image borders, replicate last row/column if needed
size_t row = minimum(uint16_t(mcuY + blockY + deltaY), maxHeight);
for (size_t deltaX = 0; deltaX < 8; deltaX++)
{
// find actual pixel position within the current image
size_t pixelPos = row * int(width) + column; // the cast ensures that we don't run into multiplication overflows
if (column < maxWidth)
column++;
// grayscale images have solely a Y channel which can be easily derived from the input pixel by shifting it by 128
if (!isRGB)
{
Y[deltaY][deltaX] = pixels[pixelPos] - 128.f;
continue;
}
// RGB: 3 bytes per pixel (whereas grayscale images have only 1 byte per pixel)
uint8_t r = pixels[3 * pixelPos ];
uint8_t g = pixels[3 * pixelPos + 1];
uint8_t b = pixels[3 * pixelPos + 2];
Y [deltaY][deltaX] = rgb2y (r, g, b) - 128; // again, the JPEG standard requires Y to be shifted by 128
// YCbCr444 is easy - the more complex YCbCr420 has to be computed about 20 lines below in a second pass
if (!downsample)
{
Cb[deltaY][deltaX] = rgb2cb(r, g, b); // standard RGB-to-YCbCr conversion
Cr[deltaY][deltaX] = rgb2cr(r, g, b);
}
}
}
// encode Y channel
lastYDC = encodeBlock(bitWriter, Y, scaledLuminance, lastYDC, huffmanLuminanceDC, huffmanLuminanceAC, codewords);
// Cb and Cr are encoded about 50 lines below
}
// grayscale images don't need any Cb and Cr information
if (!isRGB)
continue;
// ////////////////////////////////////////
// the following lines are only relevant for YCbCr420:
// average/downsample chrominance of four pixels while respecting the image borders
if (downsample)
for (short deltaY = 7; downsample && deltaY >= 0; deltaY--) // iterating loop in reverse increases cache read efficiency
{
size_t row = minimum(uint16_t(mcuY + 2*deltaY), maxHeight); // each deltaX/Y step covers a 2x2 area
size_t column = mcuX; // column is updated inside next loop
size_t pixelPos = (row * int(width) + column) * 3; // numComponents = 3
// deltas (in bytes) to next row / column, must not exceed image borders
size_t rowStep = (row < maxHeight) ? 3 * int(width) : 0; // always numComponents*width except for bottom line
size_t columnStep = (column < maxWidth ) ? 3 : 0; // always numComponents except for rightmost pixel
for (short deltaX = 0; deltaX < 8; deltaX++)
{
// let's add all four samples (2x2 area)
size_t right = pixelPos + columnStep;
size_t down = pixelPos + rowStep;
size_t downRight = pixelPos + columnStep + rowStep;
// note: cast from 8 bits to >8 bits to avoid overflows when adding
short r = short(pixels[pixelPos ]) + pixels[right ] + pixels[down ] + pixels[downRight ];
short g = short(pixels[pixelPos + 1]) + pixels[right + 1] + pixels[down + 1] + pixels[downRight + 1];
short b = short(pixels[pixelPos + 2]) + pixels[right + 2] + pixels[down + 2] + pixels[downRight + 2];
// convert to Cb and Cr
Cb[deltaY][deltaX] = rgb2cb(r, g, b) / 4; // I still have to divide r,g,b by 4 to get their average values
Cr[deltaY][deltaX] = rgb2cr(r, g, b) / 4; // it's a bit faster if done AFTER CbCr conversion
// step forward to next 2x2 area
pixelPos += 2*3; // 2 pixels => 6 bytes (2*numComponents)
column += 2;
// reached right border ?
if (column >= maxWidth)
{
columnStep = 0;
pixelPos = ((row + 1) * int(width) - 1) * 3; // same as (row * width + maxWidth) * numComponents => current's row last pixel
}
}
} // end of YCbCr420 code for Cb and Cr
// encode Cb and Cr
lastCbDC = encodeBlock(bitWriter, Cb, scaledChrominance, lastCbDC, huffmanChrominanceDC, huffmanChrominanceAC, codewords);
lastCrDC = encodeBlock(bitWriter, Cr, scaledChrominance, lastCrDC, huffmanChrominanceDC, huffmanChrominanceAC, codewords);
}
bitWriter.flush(); // now image is completely encoded, write any bits still left in the buffer
// ///////////////////////////
// EOI marker
bitWriter << 0xFF << 0xD9; // this marker has no length, therefore I can't use addMarker()
return true;
} // writeJpeg()
}}
+26 -6
View File
@@ -25,20 +25,40 @@ typedef unsigned __int64 uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%lu";return s_v;}
#ifdef _WIN64
typedef unsigned long long diff_pointer_t;
#else
typedef unsigned long diff_pointer_t;
#endif
#ifdef _WIN64
typedef unsigned long long upointer;
inline const char* upointer_format() {static const char s_v[] = "%llu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%llx";return s_v;}
typedef unsigned long long diff_pointer_t;
#else
typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}
typedef unsigned long diff_pointer_t;
#endif
#elif defined(__MINGW32__)
typedef int int32;
typedef long long int64;
inline const char* int32_format() {static const char s_v[] = "%d";return s_v;}
inline const char* int64_format() {static const char s_v[] = "%ld";return s_v;}
typedef unsigned int uint32;
typedef unsigned long long uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%lu";return s_v;}
#ifdef __MINGW64__
typedef unsigned long long upointer;
inline const char* upointer_format() {static const char s_v[] = "%llu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%llx";return s_v;}
typedef unsigned long long diff_pointer_t;
#else
typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}
typedef unsigned long diff_pointer_t;
#endif
#elif defined(_LP64)
+5 -5
View File
@@ -5,13 +5,13 @@
#define tools_version
#define TOOLS_MAJOR_VERSION 6
#define TOOLS_MINOR_VERSION 0
#define TOOLS_PATCH_VERSION 1
#define TOOLS_VERSION "6.0.1"
#define TOOLS_VERSION_VRP "v6r0p1"
#define TOOLS_MINOR_VERSION 1
#define TOOLS_PATCH_VERSION 0
#define TOOLS_VERSION "6.1.0"
#define TOOLS_VERSION_VRP "v6r1p0"
namespace tools {
inline unsigned int version() {return 60001;}
inline unsigned int version() {return 60100;}
}
#endif
+1 -1
View File
@@ -22,7 +22,7 @@ inline date get_date(){
// Date is stored with the origin being the 1st january 1995.
// Time has 1 second precision.
time_t tloc = ::time(0);
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
struct tm *tp = (tm*)::localtime(&tloc); //not thread safe (but exist on Windows).
#else
struct tm tpa;
+4 -4
View File
@@ -21,7 +21,7 @@
#include <errno.h>
#include <sys/stat.h>
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <direct.h>
#include <io.h>
#else
@@ -62,7 +62,7 @@ public: //ifile
#if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
if (::lseek64(m_file, a_offset, whence) < 0) {
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) || defined(__MINGW32__)
if (::_lseeki64(m_file, a_offset, whence) < 0) {
#else
if (::lseek(m_file, a_offset, whence) < 0) {
@@ -143,7 +143,7 @@ public: //ifile
<< std::endl;
return false;
}
#elif defined(__MINGW32__) || defined(__MINGW64__)
#elif defined(__MINGW32__)
return true;
#else
if (::fsync(m_file) < 0) {
@@ -253,7 +253,7 @@ public:
}
m_file = _open(a_path.c_str(),
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
O_RDWR | O_CREAT | O_BINARY,S_IREAD | S_IWRITE
#else
O_RDWR | O_CREAT,0644
+50 -30
View File
@@ -73,15 +73,6 @@ protected:
m_size = a_from.m_size;
return *this;
}
public:
bool get_pixel(ZPos a_x,ZPos a_y,ZZ /*a_z*/,ZPixel& a_pixel) const {
if((a_x<m_buffer.m_begX) || (a_x>m_buffer.m_endX)) {a_pixel=0;return false;}
if((a_y<m_buffer.m_begY) || (a_y>m_buffer.m_endY)) {a_pixel=0;return false;}
unsigned long offset = a_y * m_buffer.m_zbw + a_x;
ZPixel* zimage = m_buffer.m_zimage + offset;
a_pixel = *zimage;
return true;
}
protected:
void _write(ZPos a_x,ZPos a_y,ZZ a_z) {
if((a_x<m_buffer.m_begX) || (a_x>m_buffer.m_endX)) return;
@@ -95,13 +86,8 @@ protected:
ZPixel* zimage = m_buffer.m_zimage + offset;
/* transparency :
ZPixel old_pix = *zimage;
// need the alpha of m_pixel !
*/
*zbuff = zpoint;
*zimage = m_pixel;
m_buffer.blend(*zimage,m_pixel);
}
protected:
buffer& m_buffer;
@@ -156,6 +142,7 @@ protected:
public:
buffer()
:m_depth_test(true)
,m_blend(false)
,m_zbuffer(0)
//,m_zmin(0),m_zmax(0)
,m_zimage(0)
@@ -175,14 +162,18 @@ public:
protected:
buffer(const buffer& a_from)
:m_depth_test(a_from.m_depth_test)
,m_blend(a_from.m_blend)
{}
buffer& operator=(const buffer& a_from){
m_depth_test = a_from.m_depth_test;
m_blend = a_from.m_blend;
return *this;
}
public:
void set_depth_test(bool a_on) {m_depth_test = a_on;}
//bool depth_test() const {return m_depth_test;}
void set_blend(bool a_value) {m_blend = a_value;}
bool change_size(unsigned int a_width,unsigned int a_height){
if(!a_width||!a_height) return false;
@@ -228,8 +219,7 @@ public:
return true;
}
ZPixel* get_color_buffer(unsigned int& a_width,
unsigned int& a_height) const {
ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {
a_width = m_zbw;
a_height = m_zbh;
return m_zimage;
@@ -257,13 +247,9 @@ public:
}
}
//ZPixel get_pixel(ZPos a_x,ZPos a_y) const {
// return *(m_zimage + a_y * m_zbw + a_x);
//}
bool get_clipped_pixel(ZPos a_x,ZPos a_y,ZPixel& a_pixel) const {
if((a_x<m_begX) || (a_x>m_endX)) return false;
if((a_y<m_begY) || (a_y>m_endY)) return false;
if((a_x<m_begX) || (a_x>m_endX)) {a_pixel = 0;return false;}
if((a_y<m_begY) || (a_y>m_endY)) {a_pixel = 0;return false;}
a_pixel = *(m_zimage + a_y * m_zbw + a_x);
return true;
}
@@ -288,11 +274,6 @@ public:
pw.write(a_p.x,a_p.y,a_p.z);
}
bool get_pixel(const point& a_p,ZPixel& a_pixel){
point_writer pw(a_pixel,*this,1);
return pw.get_pixel(a_p.x,a_p.y,a_p.z,a_pixel);
}
void draw_line(const point& a_beg,const point& a_end,ZPixel a_pixel,unsigned int a_size){
point_writer pw(a_pixel,*this,a_size);
WriteLine(a_beg,a_end,pw);
@@ -379,6 +360,22 @@ public:
}
}
*/
typedef unsigned char uchar;
static void rgba2pix(float a_r,float a_g,float a_b,float a_a,ZPixel& a_pix) {
uchar* _px = (uchar*)&a_pix;
*_px = (uchar)(255.0F * a_r);_px++;
*_px = (uchar)(255.0F * a_g);_px++;
*_px = (uchar)(255.0F * a_b);_px++;
*_px = (uchar)(255.0F * a_a);_px++;
}
static void pix2rgba(const ZPixel& a_pix,float& a_r,float& a_g,float& a_b,float& a_a) {
uchar* _px = (uchar*)&a_pix;
a_r = (*_px)/255.0f;_px++;
a_g = (*_px)/255.0f;_px++;
a_b = (*_px)/255.0f;_px++;
a_a = (*_px)/255.0f;_px++;
}
protected:
class scan_writer {
public:
@@ -459,6 +456,28 @@ protected:
writer& m_writer;
};
void blend(ZPixel& a_pix,const ZPixel& a_new) {
if(!m_blend) {
a_pix = a_new;
return;
}
float _or,_og,_ob,_oa;
pix2rgba(a_pix,_or,_og,_ob,_oa);
float nr,ng,nb,na;
pix2rgba(a_new,nr,ng,nb,na);
if((0.0f<=na)&&(na<1.0f)) {
// same as glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA):
float one_minus_na = 1.0f-na;
float pr = nr*na+_or*one_minus_na;
float pg = ng*na+_og*one_minus_na;
float pb = nb*na+_ob*one_minus_na;
float pa = 1;
rgba2pix(pr,pg,pb,pa,a_pix);
} else {
a_pix = a_new;
}
}
static void WriteScanLine(void* a_tag,int a_beg,int a_end,int a_y){
buffer& a_buffer = *((buffer*)a_tag);
@@ -489,11 +508,11 @@ protected:
// &&(zpoint<=a_buffer.m_zmax)
){
*zbuff = zpoint;
*zimage = a_buffer.m_scan_pixel;
a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
}
} else {
*zbuff = zpoint;
*zimage = a_buffer.m_scan_pixel;
a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
}
zbuff ++;
zimage ++;
@@ -595,6 +614,7 @@ protected:
protected:
bool m_depth_test;
bool m_blend;
ZReal* m_zbuffer;
//ZReal m_zmin,m_zmax;
+1 -1
View File
@@ -70,7 +70,7 @@ public:
QApplication* qapp() const {return m_qapp;}
QWidget* create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
if(!m_qapp) return 0;
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
if(a_y<=0) a_y = 60;
#endif
QWidget* top = new QWidget();
+5 -4
View File
@@ -15,6 +15,7 @@
#include <string>
#if defined(_MSC_VER) && _MSC_VER < 1900
#elif defined(__MINGW32__)
#else
#define TOOLX_WINDOWS_TOUCH
#endif
@@ -57,12 +58,12 @@ class glarea {
}
public:
virtual void resize(unsigned int,unsigned int){}
virtual void paint(unsigned int a_w,unsigned int a_h) {}
virtual void paint(unsigned int,unsigned int) {}
virtual void close(){}
virtual void left_button_up(unsigned int a_x,unsigned int a_y) {}
virtual void left_button_down(unsigned int a_x,unsigned int a_y) {}
virtual void mouse_move(unsigned int a_x,unsigned int a_y,bool) {}
virtual void left_button_up(unsigned int,unsigned int) {}
virtual void left_button_down(unsigned int,unsigned int) {}
virtual void mouse_move(unsigned int,unsigned int,bool) {}
public:
glarea(HWND a_parent)
:m_parent(a_parent)
+28 -20
View File
@@ -30,13 +30,13 @@ typedef struct {
XEvent* event;
} XoAnyCallbackStruct;
#define XoNdoubleBufferOn "doubleBufferOn"
#define XoNpaintCallback "paintCallback"
#define XoNeventCallback "eventCallback"
#define XoCR_PAINT 1
#define XoCR_EVENT 2
#define XoNdoubleBufferOn toolx::Xt::OpenGLArea::XoN_doubleBufferOn()
#define XoNpaintCallback toolx::Xt::OpenGLArea::XoN_paintCallback()
#define XoNeventCallback toolx::Xt::OpenGLArea::XoN_eventCallback()
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
@@ -71,6 +71,13 @@ typedef struct _OpenGLAreaRec {
///////////////////////////////////////////////////////////
class OpenGLArea {
protected:
static const char* class_name() {static const char* s_s = "OpenGLArea";return s_s;}
static const char* XoC_DoubleBufferOn() {static const char* s_s = "DoubleBufferOn";return s_s;}
public:
static const char* XoN_doubleBufferOn() {static const char* s_s = "doubleBufferOn";return s_s;}
static const char* XoN_paintCallback() {static const char* s_s = "paintCallback";return s_s;}
static const char* XoN_eventCallback() {static const char* s_s = "eventCallback";return s_s;}
public:
static void paint(Widget a_this) {
if(!XtIsRealized(a_this)) return;
@@ -90,7 +97,7 @@ protected:
if(a_request->core.width<=0) a_this->core.width = 100;
if(a_request->core.height<=0) a_this->core.height = 100;
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
::printf ("debug : OpenGLArea : InitializeWidget : %s\n",::XtName(a_this));
#endif
@@ -190,13 +197,13 @@ protected:
::XtAddEventHandler
(a_this,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask,0,event_handler,NULL);
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : InitializeWidget : end\n");
#endif
}
static void realize_widget(Widget a_this,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : realize_widget : %s\n",XtName(a_this));
#endif
@@ -216,13 +223,13 @@ protected:
//make_current(a_this);
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : realize_widget : end\n");
#endif
}
static void destroy_widget(Widget a_this) {
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : destroy_widget : begin\n");
#endif
OpenGLAreaPart& athis = _athis(a_this);
@@ -236,7 +243,7 @@ protected:
::glXDestroyContext(XtDisplay(a_this),athis.glContext);
athis.glContext = NULL;
}
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : destroy_widget : end\n");
#endif
}
@@ -257,7 +264,7 @@ protected:
}
static void change_widget_size(Widget a_this) {
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : change_widget_size : %s\n",XtName(a_this));
#endif
@@ -265,13 +272,13 @@ protected:
if(widget_class()->core_class.superclass->core_class.resize!=NULL)
(widget_class()->core_class.superclass->core_class.resize)(a_this);
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : change_widget_size : end\n");
#endif
}
static void draw_widget(Widget a_this,XEvent* a_event,Region a_region) {
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : %s\n",XtName(a_this));
#endif
@@ -279,7 +286,7 @@ protected:
(widget_class()->core_class.superclass->core_class.expose)(a_this,a_event,a_region);
if(make_current(a_this)==1) {
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : %s : make_current ok : call paintCallback...\n",XtName(a_this));
#endif
XoAnyCallbackStruct value;
@@ -290,7 +297,7 @@ protected:
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
}
#ifdef OPENGLAREA_DEBUG
#ifdef TOOLX_XT_OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : end\n");
#endif
}
@@ -414,12 +421,12 @@ protected:
public:
static WidgetClass widget_class() {
static XtResource s_resources [] = {
{(String)XoNdoubleBufferOn,(String)"DoubleBufferOn",XtRBoolean,sizeof(Boolean),
static XtResource s_resources[] = {
{(String)XoN_doubleBufferOn(),(String)XoC_DoubleBufferOn(),XtRBoolean,sizeof(Boolean),
XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
{(String)XoNpaintCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
{(String)XoN_paintCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
{(String)XoNeventCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
{(String)XoN_eventCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
};
@@ -427,7 +434,7 @@ public:
// Core Class Part :
{
(WidgetClass) &compositeClassRec, // pointer to superclass ClassRec
(String)"OpenGLArea", // widget resource class name
(String)class_name(), // widget resource class name
sizeof(OpenGLAreaRec), // size in bytes of widget record
initialize_class, // class_initialize
NULL, // dynamic initialization
@@ -478,4 +485,5 @@ public:
}}
#endif
+1 -1
View File
@@ -168,7 +168,7 @@ protected:
tools::key_code convert(KeySym a_key) {
if(a_key==XK_Shift_L) return tools::sg::key_shift();
if(a_key==XK_Shift_R) return tools::sg::key_shift();
return a_key;
return (tools::key_code)a_key;
}
protected:
session& m_session;
+1 -1
View File
@@ -16,7 +16,7 @@
#endif
// the below must be in sync with tools/typedefs
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
//typedef __int64 int64;
//typedef unsigned __int64 uint64;
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG_LONG
+8 -6
View File
@@ -421,7 +421,7 @@ public:
tmp.no_translate();
tools::mat4f normal_matrix;
if(!tmp.invert(normal_matrix)) {
m_out << "toolx::WebGL::render::load_model_matrix :"
m_out << "toolx::sg::GL_action::render::load_model_matrix :"
<< " can't invert model matrix."
<< std::endl;
}
@@ -441,7 +441,8 @@ public:
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){
float a_r,float a_g,float a_b,float a_a,
float a_ar,float a_ag,float a_ab,float a_aa){
::glEnable(GL_LIGHTING);
GLenum light = GL_LIGHT0+a_light;
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
@@ -465,10 +466,10 @@ public:
::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;
params[0] = a_ar;
params[1] = a_ag;
params[2] = a_ab;
params[3] = a_aa;
::glLightfv(light,GL_AMBIENT,params); //coin/SoDirectionalLight does that.
// coin/SoDirectionalLight does the below :
@@ -657,4 +658,5 @@ protected:
}}
#endif
+3 -3
View File
@@ -55,7 +55,7 @@ inline bool compress_buffer(std::ostream& a_out,
//a_out << "toolx::compress_buffer : ok "
// << stream.total_out << std::endl;
a_irep = stream.total_out;
a_irep = (unsigned)stream.total_out;
return true;
}
@@ -97,7 +97,7 @@ inline bool decompress_buffer(std::ostream& a_out,
//a_out << "toolx::decompress_buffer : zlib : ok "
// << stream.total_out << std::endl;
a_irep = stream.total_out;
a_irep = (unsigned)stream.total_out;
return true;
}
@@ -220,7 +220,7 @@ inline bool gunzip_buffer(std::ostream& a_out,
inflateEnd(&stream);
a_irep = stream.total_out;
a_irep = (unsigned)stream.total_out;
return true;
}