Import Geant4 11.1.0 source tree
This commit is contained in:
+29
-2
@@ -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
@@ -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
|
||||
+2766
File diff suppressed because it is too large
Load Diff
+73
-18
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user