/*
* v3dfile.cc
* V3D Export class
*
* Supakorn "Jamie" Rassameemasmuang <
[email protected]> and
* John C. Bowman
*/
#include "v3dfile.h"
#ifdef HAVE_LIBTIRPC
#ifdef HAVE_LIBGLM
#include "drawelement.h"
#include "makeUnique.h"
namespace camp
{
using settings::getSetting;
void v3dfile::writeInit()
{
uint32_t doubleprecision = !singleprecision;
getXDRFile() << v3dVersion << doubleprecision;
addHeaders();
camp::clearCenters();
camp::clearMaterials();
}
void v3dfile::addHeaders()
{
getXDRFile() << v3dtypes::header;
std::vector<std::unique_ptr<AHeader>> headers;
headers.emplace_back(make_unique<Uint32Header>(v3dheadertypes::canvasWidth, gl::fullWidth));
headers.emplace_back(make_unique<Uint32Header>(v3dheadertypes::canvasHeight, gl::fullHeight));
headers.emplace_back(make_unique<Uint32Header>(v3dheadertypes::absolute, getSetting<bool>("absolute")));
headers.emplace_back(make_unique<TripleHeader>(v3dheadertypes::minBound, triple(gl::Xmin, gl::Ymin, gl::Zmin)));
headers.emplace_back(make_unique<TripleHeader>(v3dheadertypes::maxBound, triple(gl::Xmax, gl:: Ymax, gl::Zmax)));
headers.emplace_back(make_unique<Uint32Header>(v3dheadertypes::orthographic, gl::orthographic));
headers.emplace_back(make_unique<DoubleHeader>(v3dheadertypes::angleOfView, gl::Angle));
headers.emplace_back(make_unique<DoubleHeader>(v3dheadertypes::initialZoom, gl::Zoom0));
if(gl::Shift != pair(0.0,0.0))
headers.emplace_back(make_unique<PairHeader>(v3dheadertypes::viewportShift, gl::Shift*gl::Zoom0));
headers.emplace_back(make_unique<PairHeader>(v3dheadertypes::viewportMargin, gl::Margin));
for(size_t i=0; i < gl::nlights; ++i) {
size_t i4=4*i;
headers.emplace_back(make_unique<LightHeader>(
gl::Lights[i],
prc::RGBAColour(gl::Diffuse[i4], gl::Diffuse[i4+1], gl::Diffuse[i4+2], 1.0)
));
}
headers.emplace_back(make_unique<RGBAHeader>(
v3dheadertypes::background,
prc::RGBAColour(gl::Background[0],gl::Background[1],gl::Background[2],gl::Background[3])));
headers.emplace_back(make_unique<DoubleHeader>(v3dheadertypes::zoomFactor, getSetting<double>("zoomfactor")));
headers.emplace_back(make_unique<DoubleHeader>(
v3dheadertypes::zoomPinchFactor, getSetting<double>("zoomPinchFactor")));
headers.emplace_back(make_unique<DoubleHeader>(
v3dheadertypes::zoomPinchCap, getSetting<double>("zoomPinchCap")));
headers.emplace_back(make_unique<DoubleHeader>(v3dheadertypes::zoomStep, getSetting<double>("zoomstep")));
headers.emplace_back(make_unique<DoubleHeader>(
v3dheadertypes::shiftHoldDistance, getSetting<double>("shiftHoldDistance")));
headers.emplace_back(make_unique<DoubleHeader>(
v3dheadertypes::shiftWaitTime, getSetting<double>("shiftWaitTime")));
headers.emplace_back(make_unique<DoubleHeader>(
v3dheadertypes::vibrateTime, getSetting<double>("vibrateTime")));
getXDRFile() << (uint32_t) headers.size();
for(const auto& header : headers) {
getXDRFile() << header->ty << header->getWordSize(singleprecision);
header->writeContent(getXDRFile());
}
}
void v3dfile::addCenters()
{
getXDRFile() << v3dtypes::centers;
size_t nelem=drawElement::centers.size();
getXDRFile() << (uint32_t) nelem;
if(nelem > 0)
addTriples(drawElement::centers.data(), nelem);
}
void v3dfile::addTriples(triple const* triples, size_t n)
{
for(size_t i=0; i < n; ++i)
getXDRFile() << triples[i];
}
void v3dfile::addColors(prc::RGBAColour const* col, size_t nc)
{
for(size_t i=0; i < nc; ++i)
getXDRFile() << col[i];
}
void v3dfile::addPatch(triple const* controls, prc::RGBAColour const* c)
{
getXDRFile() << (c ? v3dtypes::bezierPatchColor : v3dtypes::bezierPatch);
addTriples(controls,16);
addCenterIndexMat();
if(c)
addColors(c,4);
}
void v3dfile::addStraightPatch(triple const* controls,
prc::RGBAColour const* c)
{
getXDRFile() << (c ? v3dtypes::quadColor : v3dtypes::quad);
addTriples(controls,4);
addCenterIndexMat();
if(c)
addColors(c,4);
}
void v3dfile::addBezierTriangle(triple const* controls,
prc::RGBAColour const* c)
{
getXDRFile() << (c ? v3dtypes::bezierTriangleColor : v3dtypes::bezierTriangle);
addTriples(controls,10);
addCenterIndexMat();
if(c)
addColors(c,3);
}
void v3dfile::addStraightBezierTriangle(triple const* controls,
prc::RGBAColour const* c)
{
getXDRFile() << (c ? v3dtypes::triangleColor : v3dtypes::triangle);
addTriples(controls,3);
addCenterIndexMat();
if(c)
addColors(c,3);
}
void v3dfile::addMaterial(Material const& mat)
{
getXDRFile() << v3dtypes::material;
addvec4(mat.diffuse);
addvec4(mat.emissive);
addvec4(mat.specular);
glm::vec4 vec=mat.parameters;
getXDRFile() << static_cast<float>(vec.x) << static_cast<float>(vec.y)
<< static_cast<float>(vec.z);
}
void v3dfile::addCenterIndexMat()
{
getXDRFile() << (uint32_t) drawElement::centerIndex << (uint32_t) materialIndex;
}
void v3dfile::addvec4(glm::vec4 const& vec)
{
getXDRFile() << static_cast<float>(vec.x) << static_cast<float>(vec.y)
<< static_cast<float>(vec.z) << static_cast<float>(vec.w);
}
void v3dfile::addHemisphere(triple const& center, double radius, double const& polar, double const& azimuth)
{
getXDRFile() << v3dtypes::halfSphere << center << radius;
addCenterIndexMat();
getXDRFile() << polar << azimuth;
}
void v3dfile::addSphere(triple const& center, double radius)
{
getXDRFile() << v3dtypes::sphere << center << radius;
addCenterIndexMat();
}
void
v3dfile::addCylinder(triple const& center, double radius, double height, double const& polar, double const& azimuth,
bool core)
{
getXDRFile() << v3dtypes::cylinder << center << radius << height;
addCenterIndexMat();
getXDRFile() << polar << azimuth << core;
}
void v3dfile::addDisk(triple const& center, double radius, double const& polar, double const& azimuth)
{
getXDRFile() << v3dtypes::disk << center << radius;
addCenterIndexMat();
getXDRFile() << polar << azimuth;
}
void v3dfile::addTube(triple const* g, double width, bool core)
{
getXDRFile() << v3dtypes::tube;
for(int i=0; i < 4; ++i)
getXDRFile() << g[i];
getXDRFile() << width;
addCenterIndexMat();
getXDRFile() << core;
}
void v3dfile::addTriangles(size_t nP, triple const* P, size_t nN,
triple const* N, size_t nC,
prc::RGBAColour const* C, size_t nI,
uint32_t const (* PI)[3], uint32_t const (* NI)[3],
uint32_t const (* CI)[3])
{
getXDRFile() << v3dtypes::triangles;
getXDRFile() << (uint32_t) nI;
getXDRFile() << (uint32_t) nP;
addTriples(P,nP);
getXDRFile() << (uint32_t) nN;
addTriples(N,nN);
bool explicitNI=false;
for(size_t i=0; i < nI; ++i) {
const uint32_t *PIi=PI[i];
const uint32_t *NIi=NI[i];
if(distinct(NIi,PIi)) {
explicitNI=true;
break;
}
}
getXDRFile() << (uint32_t) explicitNI;
getXDRFile() << (uint32_t) nC;
bool explicitCI=false;
if(nC) {
addColors(C,nC);
for(size_t i=0; i < nI; ++i) {
const uint32_t *PIi=PI[i];
const uint32_t *CIi=CI[i];
if(distinct(CIi,PIi)) {
explicitNI=true;
break;
}
}
getXDRFile() << (uint32_t) explicitCI;
}
for(size_t i=0; i < nI; ++i) {
const uint32_t *PIi=PI[i];
const uint32_t *NIi=NI[i];
addIndices(PIi);
if(explicitNI)
addIndices(NIi);
if(nC) {
const uint32_t *CIi=CI[i];
if(explicitCI)
addIndices(CIi);
}
}
addCenterIndexMat();
}
void v3dfile::addIndices(uint32_t const* v)
{
getXDRFile() << v[0] << v[1] << v[2];
}
void v3dfile::addCurve(triple const& z0, triple const& c0, triple const& c1,
triple const& z1)
{
getXDRFile() << v3dtypes::curve << z0 << c0 << c1 << z1;
addCenterIndexMat();
}
void v3dfile::addCurve(triple const& z0, triple const& z1)
{
getXDRFile() << v3dtypes::line << z0 << z1;
addCenterIndexMat();
}
void v3dfile::addPixel(triple const& z0, double width)
{
getXDRFile() << v3dtypes::pixel << z0 << width;
getXDRFile() << (uint32_t) materialIndex;
}
void v3dfile::finalize()
{
if(!finalized) {
addCenters();
finalized=true;
}
}
// gzv3dfile
xdr::oxstream& gzv3dfile::getXDRFile()
{
return memxdrfile;
}
gzv3dfile::gzv3dfile(string const& name, bool singleprecision): v3dfile(singleprecision), memxdrfile(singleprecision), name(name), destroyed(false)
{
writeInit();
}
gzv3dfile::~gzv3dfile()
{
close();
}
void gzv3dfile::close()
{
if(!destroyed) {
finalize();
std::vector<uint8_t> const resultingData = memxdrfile.createCopyOfCurrentData();
memxdrfile.close();
gzFile file=gzopen(name.c_str(), "wb9");
gzwrite(file, resultingData.data(), resultingData.size());
gzclose(file);
if(settings::verbose > 0)
cout << "Wrote " << name << endl;
destroyed=true;
}
}
uint32_t LightHeader::getWordSize(bool singleprecision) const
{
return (singleprecision ? 1 : 2)*3+3;
}
void LightHeader::writeContent(xdr::oxstream& ox) const
{
ox << direction << (float) color.R << (float) color.G << (float) color.B;
}
LightHeader::LightHeader(triple const& direction, prc::RGBAColour const& color) :
AHeader(v3dheadertypes::light), direction(direction), color(color)
{
}
} //namespace camp
#endif
#endif