mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-21 11:35:43 +00:00
Merge branch 'annot6' into 'master'
Adding text annotations to rendering This adds bitmap font support and two types of text annotations - screen space text and world-space billboard text - as well as enables the labels in the axes. See merge request !423
This commit is contained in:
commit
298b9d2e6c
@ -170,7 +170,7 @@ main(int argc, char* argv[])
|
||||
vtkm::rendering::RenderSurfaceGL surface(W,H,bg);
|
||||
vtkm::rendering::SceneRendererGL<VTKM_DEFAULT_DEVICE_ADAPTER_TAG> sceneRenderer;
|
||||
|
||||
vtkm::rendering::Scene3D scene;
|
||||
vtkm::rendering::Scene scene;
|
||||
scene.Plots.push_back(vtkm::rendering::Plot(ds.GetCellSet(),
|
||||
ds.GetCoordinateSystem(),
|
||||
ds.GetField("pointvar"),
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <vtkm/rendering/RenderSurface.h>
|
||||
#include <vtkm/rendering/WorldAnnotator.h>
|
||||
#include <vtkm/rendering/AxisAnnotation.h>
|
||||
#include <vtkm/rendering/TextAnnotation.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
@ -39,15 +40,15 @@ protected:
|
||||
vtkm::Float64 min_tx, min_ty, min_toff;
|
||||
vtkm::Float64 x0, y0, x1, y1;
|
||||
vtkm::Float64 lower, upper;
|
||||
vtkm::Float64 fontscale;
|
||||
vtkm::Float32 fontscale;
|
||||
vtkm::Float32 linewidth;
|
||||
vtkm::rendering::Color color;
|
||||
bool logarithmic;
|
||||
#if 0
|
||||
eavlTextAnnotation::HorizontalAlignment halign;
|
||||
eavlTextAnnotation::VerticalAlignment valign;
|
||||
std::vector<eavlTextAnnotation*> labels;
|
||||
#endif
|
||||
|
||||
TextAnnotation::HorizontalAlignment halign;
|
||||
TextAnnotation::VerticalAlignment valign;
|
||||
std::vector<TextAnnotation*> labels;
|
||||
|
||||
|
||||
std::vector<vtkm::Float64> maj_positions;
|
||||
std::vector<vtkm::Float64> maj_proportions;
|
||||
@ -55,23 +56,17 @@ protected:
|
||||
std::vector<vtkm::Float64> min_positions;
|
||||
std::vector<vtkm::Float64> min_proportions;
|
||||
|
||||
///\todo: Don't need anymore??
|
||||
bool worldSpace;
|
||||
|
||||
int moreOrLessTickAdjustment;
|
||||
public:
|
||||
AxisAnnotation2D() : AxisAnnotation()
|
||||
{
|
||||
#if 0
|
||||
halign = eavlTextAnnotation::HCenter;
|
||||
valign = eavlTextAnnotation::VCenter;
|
||||
#endif
|
||||
fontscale = 0.05;
|
||||
halign = TextAnnotation::HCenter;
|
||||
valign = TextAnnotation::VCenter;
|
||||
fontscale = 0.05f;
|
||||
linewidth = 1.0;
|
||||
color = Color(1,1,1);
|
||||
logarithmic = false;
|
||||
moreOrLessTickAdjustment = 0;
|
||||
worldSpace = false;
|
||||
}
|
||||
virtual ~AxisAnnotation2D()
|
||||
{
|
||||
@ -82,10 +77,6 @@ public:
|
||||
logarithmic = l;
|
||||
}
|
||||
#endif
|
||||
void SetWorldSpace(bool ws)
|
||||
{
|
||||
worldSpace = ws;
|
||||
}
|
||||
void SetMoreOrLessTickAdjustment(int offset)
|
||||
{
|
||||
moreOrLessTickAdjustment = offset;
|
||||
@ -123,21 +114,17 @@ public:
|
||||
x1 = x1_;
|
||||
y1 = y1_;
|
||||
}
|
||||
#if 0
|
||||
void SetLabelAlignment(eavlTextAnnotation::HorizontalAlignment h,
|
||||
eavlTextAnnotation::VerticalAlignment v)
|
||||
void SetLabelAlignment(TextAnnotation::HorizontalAlignment h,
|
||||
TextAnnotation::VerticalAlignment v)
|
||||
{
|
||||
halign = h;
|
||||
valign = v;
|
||||
}
|
||||
#endif
|
||||
void SetLabelFontScale(vtkm::Float64 s)
|
||||
void SetLabelFontScale(vtkm::Float32 s)
|
||||
{
|
||||
fontscale = s;
|
||||
#if 0
|
||||
for (unsigned int i=0; i<labels.size(); i++)
|
||||
labels[i]->SetScale(s);
|
||||
#endif
|
||||
}
|
||||
void SetRangeForAutoTicks(vtkm::Float64 l, vtkm::Float64 u)
|
||||
{
|
||||
@ -173,33 +160,22 @@ public:
|
||||
min_proportions.clear();
|
||||
min_proportions.insert(min_proportions.begin(), prop.begin(), prop.end());
|
||||
}
|
||||
virtual void Render(View &,
|
||||
WorldAnnotator &,
|
||||
virtual void Render(View &view,
|
||||
WorldAnnotator &worldAnnotator,
|
||||
RenderSurface &renderSurface)
|
||||
{
|
||||
renderSurface.AddLine(x0,y0, x1,y1, linewidth, color);
|
||||
|
||||
// major ticks
|
||||
unsigned int nmajor = (unsigned int)maj_proportions.size();
|
||||
#if 0
|
||||
while (labels.size() < nmajor)
|
||||
{
|
||||
if (worldSpace)
|
||||
{
|
||||
labels.push_back(new eavlBillboardTextAnnotation(win,"test",
|
||||
color,
|
||||
fontscale,
|
||||
0,0,0, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
labels.push_back(new eavlScreenTextAnnotation(win,"test",
|
||||
color,
|
||||
fontscale,
|
||||
0,0, 0));
|
||||
}
|
||||
labels.push_back(new ScreenTextAnnotation("test",
|
||||
color,
|
||||
fontscale,
|
||||
0,0, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned int i=0; i<nmajor; ++i)
|
||||
{
|
||||
vtkm::Float64 xc = x0 + (x1-x0) * maj_proportions[i];
|
||||
@ -220,17 +196,13 @@ public:
|
||||
char val[256];
|
||||
snprintf(val, 256, "%g", maj_positions[i]);
|
||||
|
||||
#if 0
|
||||
labels[i]->SetText(val);
|
||||
//if (fabs(maj_positions[i]) < 1e-10)
|
||||
// labels[i]->SetText("0");
|
||||
if (worldSpace)
|
||||
((eavlBillboardTextAnnotation*)(labels[i]))->SetPosition(xs,ys,0);
|
||||
else
|
||||
((eavlScreenTextAnnotation*)(labels[i]))->SetPosition(xs,ys);
|
||||
((ScreenTextAnnotation*)(labels[i]))->SetPosition(vtkm::Float32(xs),
|
||||
vtkm::Float32(ys));
|
||||
|
||||
labels[i]->SetAlignment(halign,valign);
|
||||
#endif
|
||||
}
|
||||
|
||||
// minor ticks
|
||||
@ -250,13 +222,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int i=0; i<nmajor; ++i)
|
||||
for (unsigned int i=0; i<nmajor; ++i)
|
||||
{
|
||||
labels[i]->Render(view);
|
||||
labels[i]->Render(view, worldAnnotator, renderSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/WorldAnnotator.h>
|
||||
#include <vtkm/rendering/AxisAnnotation.h>
|
||||
#include <vtkm/rendering/TextAnnotation.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
@ -38,20 +39,22 @@ protected:
|
||||
vtkm::Float64 maj_size, maj_toff;
|
||||
vtkm::Float64 min_size, min_toff;
|
||||
int axis;
|
||||
vtkm::Float64 invertx, inverty, invertz;
|
||||
vtkm::Float32 invertx, inverty, invertz;
|
||||
vtkm::Float64 x0, y0, z0, x1, y1, z1;
|
||||
vtkm::Float64 lower, upper;
|
||||
vtkm::Float64 fontscale;
|
||||
vtkm::Float32 fontoffset;
|
||||
vtkm::Float32 linewidth;
|
||||
vtkm::rendering::Color color;
|
||||
//vector<BillboardTextAnnotation*> labels; ///<\todo: add text back in
|
||||
std::vector<BillboardTextAnnotation*> labels;
|
||||
int moreOrLessTickAdjustment;
|
||||
public:
|
||||
AxisAnnotation3D() : AxisAnnotation()
|
||||
{
|
||||
axis = 0;
|
||||
color = Color(1,1,1);
|
||||
fontscale = 0.05;
|
||||
fontoffset = 0.1f; // world space offset from axis
|
||||
fontscale = 0.05; // screen space font size
|
||||
linewidth = 1.0;
|
||||
color = Color(1,1,1);
|
||||
moreOrLessTickAdjustment = 0;
|
||||
@ -104,21 +107,24 @@ public:
|
||||
void SetLabelFontScale(vtkm::Float64 s)
|
||||
{
|
||||
fontscale = s;
|
||||
#if 0
|
||||
for (unsigned int i=0; i<labels.size(); i++)
|
||||
labels[i]->SetScale(s);
|
||||
#endif
|
||||
labels[i]->SetScale(vtkm::Float32(s));
|
||||
}
|
||||
void SetLabelFontOffset(vtkm::Float32 off)
|
||||
{
|
||||
fontoffset = off;
|
||||
}
|
||||
void SetRange(vtkm::Float64 l, vtkm::Float64 u)
|
||||
{
|
||||
lower = l;
|
||||
upper = u;
|
||||
}
|
||||
virtual void Render(View &,
|
||||
WorldAnnotator &worldannotator)
|
||||
virtual void Render(View &view,
|
||||
WorldAnnotator &worldAnnotator,
|
||||
RenderSurface &renderSurface)
|
||||
{
|
||||
bool infront = true;
|
||||
worldannotator.AddLine(x0,y0,z0,
|
||||
worldAnnotator.AddLine(x0,y0,z0,
|
||||
x1,y1,z1,
|
||||
linewidth, color, infront);
|
||||
|
||||
@ -127,15 +133,15 @@ public:
|
||||
// major ticks
|
||||
CalculateTicks(lower, upper, false, positions, proportions, moreOrLessTickAdjustment);
|
||||
unsigned int nmajor = (unsigned int)proportions.size();
|
||||
#if 0
|
||||
while ((int)labels.size() < nmajor)
|
||||
while (labels.size() < nmajor)
|
||||
{
|
||||
labels.push_back(new BillboardTextAnnotation(win,"test",
|
||||
color,
|
||||
fontscale,
|
||||
0,0,0, false, 0));
|
||||
labels.push_back(new BillboardTextAnnotation("test",
|
||||
color,
|
||||
vtkm::Float32(fontscale),
|
||||
0,0,0,
|
||||
0));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned int i=0; i<nmajor; ++i)
|
||||
{
|
||||
vtkm::Float64 xc = x0 + (x1-x0) * proportions[i];
|
||||
@ -160,33 +166,33 @@ public:
|
||||
vtkm::Float64 zs = zc - tz*maj_toff;
|
||||
vtkm::Float64 ze = zc + tz*(1. - maj_toff);
|
||||
|
||||
worldannotator.AddLine(xs,ys,zs,
|
||||
xe,ye,ze,
|
||||
linewidth, color, infront);
|
||||
worldAnnotator.AddLine(xs,ys,zs,
|
||||
xe,ye,ze,
|
||||
linewidth, color, infront);
|
||||
}
|
||||
|
||||
vtkm::Float64 tx=0, ty=0, tz=0;
|
||||
const vtkm::Float64 s = 0.4;
|
||||
vtkm::Float32 tx=0, ty=0, tz=0;
|
||||
const vtkm::Float32 s = 0.4f;
|
||||
switch (axis)
|
||||
{
|
||||
case 0: ty=s*fontscale; tz=s*fontscale; break;
|
||||
case 1: tx=s*fontscale; tz=s*fontscale; break;
|
||||
case 2: tx=s*fontscale; ty=s*fontscale; break;
|
||||
case 0: ty=s*fontoffset; tz=s*fontoffset; break;
|
||||
case 1: tx=s*fontoffset; tz=s*fontoffset; break;
|
||||
case 2: tx=s*fontoffset; ty=s*fontoffset; break;
|
||||
}
|
||||
tx *= invertx;
|
||||
ty *= inverty;
|
||||
tz *= invertz;
|
||||
|
||||
#if 0
|
||||
char val[256];
|
||||
snprintf(val, 256, "%g", positions[i]);
|
||||
labels[i]->SetText(val);
|
||||
//if (fabs(positions[i]) < 1e-10)
|
||||
// labels[i]->SetText("0");
|
||||
labels[i]->SetPosition(xc - tx, yc - ty, zc - tz);
|
||||
labels[i]->SetPosition(vtkm::Float32(xc - tx),
|
||||
vtkm::Float32(yc - ty),
|
||||
vtkm::Float32(zc - tz));
|
||||
labels[i]->SetAlignment(TextAnnotation::HCenter,
|
||||
TextAnnotation::VCenter);
|
||||
#endif
|
||||
}
|
||||
|
||||
// minor ticks
|
||||
@ -216,18 +222,16 @@ public:
|
||||
vtkm::Float64 zs = zc - tz*min_toff;
|
||||
vtkm::Float64 ze = zc + tz*(1. - min_toff);
|
||||
|
||||
worldannotator.AddLine(xs,ys,zs,
|
||||
worldAnnotator.AddLine(xs,ys,zs,
|
||||
xe,ye,ze,
|
||||
linewidth, color, infront);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (unsigned int i=0; i<nmajor; ++i)
|
||||
{
|
||||
labels[i]->Render(view);
|
||||
labels[i]->Render(view, worldAnnotator, renderSurface);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
689
vtkm/rendering/BitmapFont.h
Normal file
689
vtkm/rendering/BitmapFont.h
Normal file
@ -0,0 +1,689 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef vtk_m_BitmapFont_h
|
||||
#define vtk_m_BitmapFont_h
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
|
||||
class BitmapFont
|
||||
{
|
||||
public:
|
||||
struct Character
|
||||
{
|
||||
std::string id;
|
||||
char c;
|
||||
int offx, offy;
|
||||
int x, y, w, h;
|
||||
int adv;
|
||||
int kern[256];
|
||||
Character()
|
||||
{
|
||||
ResetKerning();
|
||||
}
|
||||
Character(const std::string &id_, char c_, int offx_, int offy_,
|
||||
int x_, int y_, int w_, int h_, int adv_)
|
||||
: id(id_), c(c_), offx(offx_), offy(offy_),
|
||||
x(x_), y(y_), w(w_), h(h_), adv(adv_)
|
||||
{
|
||||
ResetKerning();
|
||||
}
|
||||
Character(const std::string &id_, const int metrics[])
|
||||
: id(id_), c((char)metrics[0]), offx(metrics[1]), offy(metrics[2]),
|
||||
x(metrics[3]), y(metrics[4]), w(metrics[5]), h(metrics[6]),
|
||||
adv(metrics[7])
|
||||
{
|
||||
ResetKerning();
|
||||
}
|
||||
void ResetKerning()
|
||||
{
|
||||
for (int i=0; i<256; i++)
|
||||
kern[i]=0;
|
||||
}
|
||||
};
|
||||
|
||||
std::string Name;
|
||||
std::string ImageFile;
|
||||
int Height;
|
||||
int Ascender;
|
||||
int Descender;
|
||||
int ImgW, ImgH;
|
||||
int PadL, PadR, PadT, PadB;
|
||||
int ShortMap[256];
|
||||
std::vector<Character> Chars;
|
||||
|
||||
std::vector<unsigned char> RawImageFileData;
|
||||
|
||||
public:
|
||||
BitmapFont()
|
||||
{
|
||||
for (int i=0; i<256; ++i)
|
||||
ShortMap[i] = 0;
|
||||
this->PadL=0;
|
||||
this->PadR=0;
|
||||
this->PadT=0;
|
||||
this->PadB=0;
|
||||
}
|
||||
Character GetChar(char c)
|
||||
{
|
||||
return this->Chars[ShortMap[(unsigned char)c]];
|
||||
}
|
||||
std::vector<unsigned char> &GetRawImageData()
|
||||
{
|
||||
return this->RawImageFileData;
|
||||
}
|
||||
vtkm::Float32 GetTextWidth(const std::string &text)
|
||||
{
|
||||
vtkm::Float32 width = 0;
|
||||
for (unsigned int i=0; i<text.length(); ++i)
|
||||
{
|
||||
Character c = GetChar(text[i]);
|
||||
char nextchar = (i < text.length()-1) ? text[i+1] : 0;
|
||||
|
||||
const bool kerning = true;
|
||||
if (kerning && nextchar>0)
|
||||
width += vtkm::Float32(c.kern[int(nextchar)]) / vtkm::Float32(this->Height);
|
||||
width += vtkm::Float32(c.adv) / vtkm::Float32(this->Height);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
void GetCharPolygon(char character, vtkm::Float32 &x, vtkm::Float32 &y,
|
||||
vtkm::Float32 &vl, vtkm::Float32 &vr, vtkm::Float32 &vt, vtkm::Float32 &vb,
|
||||
vtkm::Float32 &tl, vtkm::Float32 &tr, vtkm::Float32 &tt, vtkm::Float32 &tb,
|
||||
char nextchar = 0)
|
||||
{
|
||||
Character c = GetChar(character);
|
||||
|
||||
// By default, the origin for the font is at the
|
||||
// baseline. That's nice, but we'd rather it
|
||||
// be at the actual bottom, so create an offset.
|
||||
vtkm::Float32 yoff = -vtkm::Float32(this->Descender) / vtkm::Float32(this->Height);
|
||||
|
||||
tl = vtkm::Float32(c.x + this->PadL) / vtkm::Float32(this->ImgW);
|
||||
tr = vtkm::Float32(c.x + c.w - this->PadR) / vtkm::Float32(this->ImgW);
|
||||
tt = 1.f - vtkm::Float32(c.y + this->PadT) / vtkm::Float32(this->ImgH);
|
||||
tb = 1.f - vtkm::Float32(c.y + c.h - this->PadB) / vtkm::Float32(this->ImgH);
|
||||
|
||||
vl = x + vtkm::Float32(c.offx + this->PadL) / vtkm::Float32(this->Height);
|
||||
vr = x + vtkm::Float32(c.offx + c.w - this->PadR) / vtkm::Float32(this->Height);
|
||||
vt = yoff + y + vtkm::Float32(c.offy - this->PadT) / vtkm::Float32(this->Height);
|
||||
vb = yoff + y + vtkm::Float32(c.offy - c.h + this->PadB) / vtkm::Float32(this->Height);
|
||||
|
||||
const bool kerning = true;
|
||||
if (kerning && nextchar>0)
|
||||
x += vtkm::Float32(c.kern[int(nextchar)]) / vtkm::Float32(this->Height);
|
||||
x += vtkm::Float32(c.adv) / vtkm::Float32(this->Height);
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
// Below is the PicoPNG source file obtained 2013-01-07 from
|
||||
// http://lodev.org/lodepng/picopng.cpp. It has the following
|
||||
// modifications relative to the original:
|
||||
// 1. decodePNG() was made static.
|
||||
// 2. std:: qualify size_t
|
||||
// 3. main() and helper code at the bottom of the file was removed.
|
||||
// 4. remove unused known_type variable.
|
||||
// 5. added explicit casts to remove compiler warnings
|
||||
// 6. renamed a function argument to avoid a shadowing warning
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
decodePNG: The picoPNG function, decodes a PNG file buffer in memory, into a raw pixel buffer.
|
||||
out_image: output parameter, this will contain the raw pixels after decoding.
|
||||
By default the output is 32-bit RGBA color.
|
||||
The std::vector is automatically resized to the correct size.
|
||||
image_width: output_parameter, this will contain the width of the image in pixels.
|
||||
image_height: output_parameter, this will contain the height of the image in pixels.
|
||||
in_png: pointer to the buffer of the PNG file in memory. To get it from a file on
|
||||
disk, load it and store it in a memory buffer yourself first.
|
||||
in_size: size of the input PNG file in bytes.
|
||||
convert_to_rgba32: optional parameter, true by default.
|
||||
Set to true to get the output in RGBA 32-bit (8 bit per channel) color format
|
||||
no matter what color type the original PNG image had. This gives predictable,
|
||||
useable data from any random input PNG.
|
||||
Set to false to do no color conversion at all. The result then has the same data
|
||||
type as the PNG image, which can range from 1 bit to 64 bits per pixel.
|
||||
Information about the color type or palette colors are not provided. You need
|
||||
to know this information yourself to be able to use the data so this only
|
||||
works for trusted PNG files. Use LodePNG instead of picoPNG if you need this information.
|
||||
return: 0 if success, not 0 if some error occured.
|
||||
*/
|
||||
static int decodePNG(std::vector<unsigned char>& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, std::size_t in_size, bool convert_to_rgba32=true)
|
||||
{
|
||||
// picoPNG version 20101224
|
||||
// Copyright (c) 2005-2010 Lode Vandevenne
|
||||
//
|
||||
// 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.
|
||||
|
||||
// picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for
|
||||
// programs that need only 1 .cpp file. Since it's a single function, it's very limited,
|
||||
// it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or
|
||||
// with no color conversion at all. For anything more complex, another tiny library
|
||||
// is available: LodePNG (lodepng.c(pp)), which is a single source and header file.
|
||||
// Apologies for the compact code style, it's to make this tiny.
|
||||
|
||||
static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258};
|
||||
static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
|
||||
static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
||||
static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
|
||||
static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths
|
||||
struct Zlib //nested functions for zlib decompression
|
||||
{
|
||||
static unsigned long readBitFromStream(std::size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;}
|
||||
static unsigned long readBitsFromStream(std::size_t& bitp, const unsigned char* bits, std::size_t nbits)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
for(std::size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
|
||||
return result;
|
||||
}
|
||||
struct HuffmanTree
|
||||
{
|
||||
int makeFromLengths(const std::vector<unsigned long>& bitlen, unsigned long maxbitlen)
|
||||
{ //make tree given the lengths
|
||||
unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
|
||||
std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
|
||||
for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length
|
||||
for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
|
||||
for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes
|
||||
tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet
|
||||
for(unsigned long n = 0; n < numcodes; n++) //the codes
|
||||
for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code
|
||||
{
|
||||
unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
|
||||
if(treepos > numcodes - 2) return 55;
|
||||
if(tree2d[2 * treepos + bit] == 32767) //not yet filled in
|
||||
{
|
||||
if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit
|
||||
else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes
|
||||
}
|
||||
else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int decode(bool& decoded, unsigned long& result, std::size_t& treepos, unsigned long bit) const
|
||||
{ //Decodes a symbol from the tree
|
||||
unsigned long numcodes = (unsigned long)tree2d.size() / 2;
|
||||
if(treepos >= numcodes) return 11; //error: you appeared outside the codetree
|
||||
result = tree2d[2 * treepos + bit];
|
||||
decoded = (result < numcodes);
|
||||
treepos = decoded ? 0 : result - numcodes;
|
||||
return 0;
|
||||
}
|
||||
std::vector<unsigned long> tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree.
|
||||
};
|
||||
struct Inflator
|
||||
{
|
||||
int error;
|
||||
void inflate(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, std::size_t inpos = 0)
|
||||
{
|
||||
std::size_t bp = 0, pos = 0; //bit pointer and byte pointer
|
||||
error = 0;
|
||||
unsigned long BFINAL = 0;
|
||||
while(!BFINAL && !error)
|
||||
{
|
||||
if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory
|
||||
BFINAL = readBitFromStream(bp, &in[inpos]);
|
||||
unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
|
||||
if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE
|
||||
else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
|
||||
else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
|
||||
}
|
||||
if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that
|
||||
}
|
||||
void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree
|
||||
{
|
||||
std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
|
||||
for(std::size_t i = 144; i <= 255; i++) bitlen[i] = 9;
|
||||
for(std::size_t i = 256; i <= 279; i++) bitlen[i] = 7;
|
||||
tree.makeFromLengths(bitlen, 15);
|
||||
treeD.makeFromLengths(bitlenD, 15);
|
||||
}
|
||||
HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes
|
||||
unsigned long huffmanDecodeSymbol(const unsigned char* in, std::size_t& bp, const HuffmanTree& lcodetree, std::size_t inlength)
|
||||
{ //decode a single symbol from given list of bits with given code tree. return value is the symbol
|
||||
bool decoded; unsigned long ct;
|
||||
for(std::size_t treepos = 0;;)
|
||||
{
|
||||
if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode
|
||||
error = lcodetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened
|
||||
if(decoded) return ct;
|
||||
}
|
||||
}
|
||||
void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, std::size_t& bp, std::size_t inlength)
|
||||
{ //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree
|
||||
std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
|
||||
if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory
|
||||
std::size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257
|
||||
std::size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1
|
||||
std::size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4
|
||||
std::vector<unsigned long> codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree
|
||||
for(std::size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
|
||||
error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return;
|
||||
std::size_t i = 0, replength;
|
||||
while(i < HLIT + HDIST)
|
||||
{
|
||||
unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return;
|
||||
if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code
|
||||
else if(code == 16) //repeat previous
|
||||
{
|
||||
if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
|
||||
replength = 3 + readBitsFromStream(bp, in, 2);
|
||||
unsigned long value; //set value to the previous code
|
||||
if((i - 1) < HLIT) value = bitlen[i - 1];
|
||||
else value = bitlenD[i - HLIT - 1];
|
||||
for(std::size_t n = 0; n < replength; n++) //repeat this value in the next lengths
|
||||
{
|
||||
if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes
|
||||
if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value;
|
||||
}
|
||||
}
|
||||
else if(code == 17) //repeat "0" 3-10 times
|
||||
{
|
||||
if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
|
||||
replength = 3 + readBitsFromStream(bp, in, 3);
|
||||
for(std::size_t n = 0; n < replength; n++) //repeat this value in the next lengths
|
||||
{
|
||||
if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes
|
||||
if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
|
||||
}
|
||||
}
|
||||
else if(code == 18) //repeat "0" 11-138 times
|
||||
{
|
||||
if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory
|
||||
replength = 11 + readBitsFromStream(bp, in, 7);
|
||||
for(std::size_t n = 0; n < replength; n++) //repeat this value in the next lengths
|
||||
{
|
||||
if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes
|
||||
if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0;
|
||||
}
|
||||
}
|
||||
else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen.
|
||||
}
|
||||
if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0
|
||||
error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done
|
||||
error = treeD.makeFromLengths(bitlenD, 15); if(error) return;
|
||||
}
|
||||
void inflateHuffmanBlock(std::vector<unsigned char>& out, const unsigned char* in, std::size_t& bp, std::size_t& pos, std::size_t inlength, unsigned long btype)
|
||||
{
|
||||
if(btype == 1) { generateFixedTrees(codetree, codetreeD); }
|
||||
else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; }
|
||||
for(;;)
|
||||
{
|
||||
unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return;
|
||||
if(code == 256) return; //end code
|
||||
else if(code <= 255) //literal symbol
|
||||
{
|
||||
if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room
|
||||
out[pos++] = (unsigned char)(code);
|
||||
}
|
||||
else if(code >= 257 && code <= 285) //length code
|
||||
{
|
||||
std::size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
|
||||
if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
|
||||
length += readBitsFromStream(bp, in, numextrabits);
|
||||
unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return;
|
||||
if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used)
|
||||
unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
|
||||
if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory
|
||||
dist += readBitsFromStream(bp, in, numextrabitsD);
|
||||
std::size_t start = pos, back = start - dist; //backwards
|
||||
if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room
|
||||
for(std::size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; }
|
||||
}
|
||||
}
|
||||
}
|
||||
void inflateNoCompression(std::vector<unsigned char>& out, const unsigned char* in, std::size_t& bp, std::size_t& pos, std::size_t inlength)
|
||||
{
|
||||
while((bp & 0x7) != 0) bp++; //go to first boundary of byte
|
||||
std::size_t p = bp / 8;
|
||||
if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory
|
||||
unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4;
|
||||
if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN
|
||||
if(pos + LEN >= out.size()) out.resize(pos + LEN);
|
||||
if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer
|
||||
for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data
|
||||
bp = p * 8;
|
||||
}
|
||||
};
|
||||
int decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in) //returns error value
|
||||
{
|
||||
Inflator inflator;
|
||||
if(in.size() < 2) { return 53; } //error, size of zlib data too small
|
||||
if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way
|
||||
unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
|
||||
if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec
|
||||
if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary."
|
||||
inflator.inflate(out, in, 2);
|
||||
return inflator.error; //note: adler32 checksum was skipped and ignored
|
||||
}
|
||||
};
|
||||
struct PNG //nested functions for PNG decoding
|
||||
{
|
||||
struct Info
|
||||
{
|
||||
unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b;
|
||||
bool key_defined; //is a transparent color key given?
|
||||
std::vector<unsigned char> palette;
|
||||
} info;
|
||||
int error;
|
||||
void decode(std::vector<unsigned char>& out, const unsigned char* in, std::size_t size, bool convert_to_rgba32)
|
||||
{
|
||||
error = 0;
|
||||
if(size == 0 || in == 0) { error = 48; return; } //the given data is empty
|
||||
readPngHeader(&in[0], size); if(error) return;
|
||||
std::size_t pos = 33; //first byte of the first chunk after the header
|
||||
std::vector<unsigned char> idat; //the data from idat chunks
|
||||
bool IEND = false;
|
||||
info.key_defined = false;
|
||||
while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer
|
||||
{
|
||||
if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk
|
||||
std::size_t chunkLength = read32bitInt(&in[pos]); pos += 4;
|
||||
if(chunkLength > 2147483647) { error = 63; return; }
|
||||
if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk
|
||||
if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data
|
||||
{
|
||||
idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
|
||||
pos += (4 + chunkLength);
|
||||
}
|
||||
else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; }
|
||||
else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE)
|
||||
{
|
||||
pos += 4; //go after the 4 letters
|
||||
info.palette.resize(4 * (chunkLength / 3));
|
||||
if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big
|
||||
for(std::size_t i = 0; i < info.palette.size(); i += 4)
|
||||
{
|
||||
for(std::size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB
|
||||
info.palette[i + 3] = 255; //alpha
|
||||
}
|
||||
}
|
||||
else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS)
|
||||
{
|
||||
pos += 4; //go after the 4 letters
|
||||
if(info.colorType == 3)
|
||||
{
|
||||
if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries
|
||||
for(std::size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++];
|
||||
}
|
||||
else if(info.colorType == 0)
|
||||
{
|
||||
if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image
|
||||
info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
|
||||
}
|
||||
else if(info.colorType == 2)
|
||||
{
|
||||
if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image
|
||||
info.key_defined = 1;
|
||||
info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2;
|
||||
info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2;
|
||||
info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
|
||||
}
|
||||
else { error = 42; return; } //error: tRNS chunk not allowed for other color models
|
||||
}
|
||||
else //it's not an implemented chunk type, so ignore it: skip over the data
|
||||
{
|
||||
if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0)
|
||||
pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk
|
||||
}
|
||||
pos += 4; //step over CRC (which is ignored)
|
||||
}
|
||||
unsigned long bpp = getBpp(info);
|
||||
std::vector<unsigned char> scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled
|
||||
Zlib zlib; //decompress with the Zlib decompressor
|
||||
error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error
|
||||
std::size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8;
|
||||
out.resize(outlength); //time to fill the out buffer
|
||||
unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization
|
||||
if(info.interlaceMethod == 0) //no interlace, just filter
|
||||
{
|
||||
std::size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte
|
||||
if(bpp >= 8) //byte per byte
|
||||
for(unsigned long y = 0; y < info.height; y++)
|
||||
{
|
||||
unsigned long filterType = scanlines[linestart];
|
||||
const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
|
||||
unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return;
|
||||
linestart += (1 + linelength); //go to start of next scanline
|
||||
}
|
||||
else //less than 8 bits per pixel, so fill it up bit per bit
|
||||
{
|
||||
std::vector<unsigned char> templine((info.width * bpp + 7) >> 3); //only used if bpp < 8
|
||||
for(std::size_t y = 0, obp = 0; y < info.height; y++)
|
||||
{
|
||||
unsigned long filterType = scanlines[linestart];
|
||||
const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
|
||||
unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return;
|
||||
for(std::size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0]));
|
||||
linestart += (1 + linelength); //go to start of next scanline
|
||||
}
|
||||
}
|
||||
}
|
||||
else //interlaceMethod is 1 (Adam7)
|
||||
{
|
||||
std::size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 };
|
||||
std::size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 };
|
||||
std::size_t passstart[7] = {0};
|
||||
std::size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes
|
||||
for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
|
||||
std::vector<unsigned char> scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline
|
||||
for(int i = 0; i < 7; i++)
|
||||
adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp);
|
||||
}
|
||||
if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed
|
||||
{
|
||||
std::vector<unsigned char> data = out;
|
||||
error = convert(out, &data[0], info, info.width, info.height);
|
||||
}
|
||||
}
|
||||
void readPngHeader(const unsigned char* in, std::size_t inlength) //read the information from the header and store it in the Info
|
||||
{
|
||||
if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header
|
||||
if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature
|
||||
if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk!
|
||||
info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]);
|
||||
info.bitDepth = in[24]; info.colorType = in[25];
|
||||
info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification
|
||||
info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification
|
||||
info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification
|
||||
error = checkColorValidity(info.colorType, info.bitDepth);
|
||||
}
|
||||
void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, std::size_t bytewidth, unsigned long filterType, std::size_t length)
|
||||
{
|
||||
switch(filterType)
|
||||
{
|
||||
case 0: for(std::size_t i = 0; i < length; i++) recon[i] = scanline[i]; break;
|
||||
case 1:
|
||||
for(std::size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i]);
|
||||
for(std::size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + recon[i - bytewidth]);
|
||||
break;
|
||||
case 2:
|
||||
if(precon) for(std::size_t i = 0; i < length; i++) recon[i] = (unsigned char)(scanline[i] + precon[i]);
|
||||
else for(std::size_t i = 0; i < length; i++) recon[i] = (unsigned char)(scanline[i]);
|
||||
break;
|
||||
case 3:
|
||||
if(precon)
|
||||
{
|
||||
for(std::size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + precon[i] / 2);
|
||||
for(std::size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i]);
|
||||
for(std::size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + recon[i - bytewidth] / 2);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(precon)
|
||||
{
|
||||
for(std::size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(0, precon[i], 0));
|
||||
for(std::size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i]);
|
||||
for(std::size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0));
|
||||
}
|
||||
break;
|
||||
default: error = 36; return; //error: unexisting filter type given
|
||||
}
|
||||
}
|
||||
void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, std::size_t passleft, std::size_t passtop, std::size_t spacex, std::size_t spacey, std::size_t passw, std::size_t passh, unsigned long bpp)
|
||||
{ //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already.
|
||||
if(passw == 0) return;
|
||||
std::size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
|
||||
for(unsigned long y = 0; y < passh; y++)
|
||||
{
|
||||
unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo;
|
||||
unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return;
|
||||
if(bpp >= 8) for(std::size_t i = 0; i < passw; i++) for(std::size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel
|
||||
out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b];
|
||||
else for(std::size_t i = 0; i < passw; i++)
|
||||
{
|
||||
std::size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp;
|
||||
for(std::size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0]));
|
||||
}
|
||||
unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new"
|
||||
}
|
||||
}
|
||||
static unsigned long readBitFromReversedStream(std::size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;}
|
||||
static unsigned long readBitsFromReversedStream(std::size_t& bitp, const unsigned char* bits, unsigned long nbits)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
for(std::size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
|
||||
return result;
|
||||
}
|
||||
void setBitOfReversedStream(std::size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (unsigned char)( (bit << (7 - (bitp & 0x7))) ); bitp++; }
|
||||
unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; }
|
||||
int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code
|
||||
{
|
||||
if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; }
|
||||
else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; }
|
||||
else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; }
|
||||
else return 31; //unexisting color type
|
||||
}
|
||||
unsigned long getBpp(const Info& linfo)
|
||||
{
|
||||
if(linfo.colorType == 2) return (3 * linfo.bitDepth);
|
||||
else if(linfo.colorType >= 4) return (linfo.colorType - 2) * linfo.bitDepth;
|
||||
else return linfo.bitDepth;
|
||||
}
|
||||
int convert(std::vector<unsigned char>& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h)
|
||||
{ //converts from any color type to 32-bit. return value = LodePNG error code
|
||||
std::size_t numpixels = w * h, bp = 0;
|
||||
out.resize(numpixels * 4);
|
||||
unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization
|
||||
if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i];
|
||||
out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255;
|
||||
}
|
||||
else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
for(std::size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c];
|
||||
out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255;
|
||||
}
|
||||
else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette)
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
if(4U * in[i] >= infoIn.palette.size()) return 46;
|
||||
for(std::size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette
|
||||
}
|
||||
else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0];
|
||||
out_[4 * i + 3] = in[2 * i + 1];
|
||||
}
|
||||
else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(std::size_t i = 0; i < numpixels; i++) for(std::size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha
|
||||
else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i];
|
||||
out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255;
|
||||
}
|
||||
else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
for(std::size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c];
|
||||
out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255;
|
||||
}
|
||||
else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte
|
||||
out_[4 * i + 3] = in[4 * i + 2];
|
||||
}
|
||||
else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(std::size_t i = 0; i < numpixels; i++) for(std::size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha
|
||||
else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255
|
||||
out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value);
|
||||
out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255;
|
||||
}
|
||||
else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette
|
||||
for(std::size_t i = 0; i < numpixels; i++)
|
||||
{
|
||||
unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth);
|
||||
if(4 * value >= infoIn.palette.size()) return 47;
|
||||
for(std::size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4
|
||||
{
|
||||
short p = short(a + b - c), pa = short(p > a ? (p - a) : (a - p)), pb = short(p > b ? (p - b) : (b - p)), pc = short(p > c ? (p - c) : (c - p));
|
||||
return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c);
|
||||
}
|
||||
};
|
||||
PNG decoder; decoder.decode(out_image, in_png, in_size, convert_to_rgba32);
|
||||
image_width = decoder.info.width; image_height = decoder.info.height;
|
||||
return decoder.error;
|
||||
}
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
||||
#endif
|
9691
vtkm/rendering/BitmapFontFactory.h
Normal file
9691
vtkm/rendering/BitmapFontFactory.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -77,6 +77,8 @@ public:
|
||||
axis.SetScreenPosition(l,b, r,b);
|
||||
axis.SetMajorTickSize(0, .02, 1.0);
|
||||
axis.SetMinorTickSize(0,0,0); // no minor ticks
|
||||
axis.SetLabelAlignment(TextAnnotation::HCenter,
|
||||
TextAnnotation::Top);
|
||||
axis.Render(view, worldAnnotator, renderSurface);
|
||||
}
|
||||
};
|
||||
|
281
vtkm/rendering/MatrixHelpers.h
Normal file
281
vtkm/rendering/MatrixHelpers.h
Normal file
@ -0,0 +1,281 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2016 Sandia Corporation.
|
||||
// Copyright 2016 UT-Battelle, LLC.
|
||||
// Copyright 2016 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_MatrixHelpers_h
|
||||
#define vtk_m_rendering_MatrixHelpers_h
|
||||
|
||||
#include <vtkm/Matrix.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
|
||||
struct MatrixHelpers
|
||||
{
|
||||
static VTKM_CONT_EXPORT
|
||||
void CreateOGLMatrix(const vtkm::Matrix<vtkm::Float32,4,4> &mtx,
|
||||
vtkm::Float32 *oglM)
|
||||
{
|
||||
oglM[ 0] = mtx[0][0];
|
||||
oglM[ 1] = mtx[1][0];
|
||||
oglM[ 2] = mtx[2][0];
|
||||
oglM[ 3] = mtx[3][0];
|
||||
oglM[ 4] = mtx[0][1];
|
||||
oglM[ 5] = mtx[1][1];
|
||||
oglM[ 6] = mtx[2][1];
|
||||
oglM[ 7] = mtx[3][1];
|
||||
oglM[ 8] = mtx[0][2];
|
||||
oglM[ 9] = mtx[1][2];
|
||||
oglM[10] = mtx[2][2];
|
||||
oglM[11] = mtx[3][2];
|
||||
oglM[12] = mtx[0][3];
|
||||
oglM[13] = mtx[1][3];
|
||||
oglM[14] = mtx[2][3];
|
||||
oglM[15] = mtx[3][3];
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ViewMatrix(const vtkm::Vec<vtkm::Float32,3> &position,
|
||||
const vtkm::Vec<vtkm::Float32,3> &lookAt,
|
||||
const vtkm::Vec<vtkm::Float32,3> &up)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32,3> viewDir = position-lookAt;
|
||||
vtkm::Vec<vtkm::Float32,3> right = vtkm::Cross(up,viewDir);
|
||||
vtkm::Vec<vtkm::Float32,3> ru = vtkm::Cross(viewDir,right);
|
||||
|
||||
vtkm::Normalize(viewDir);
|
||||
vtkm::Normalize(right);
|
||||
vtkm::Normalize(ru);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
||||
vtkm::MatrixIdentity(matrix);
|
||||
|
||||
matrix(0,0) = right[0];
|
||||
matrix(0,1) = right[1];
|
||||
matrix(0,2) = right[2];
|
||||
matrix(1,0) = ru[0];
|
||||
matrix(1,1) = ru[1];
|
||||
matrix(1,2) = ru[2];
|
||||
matrix(2,0) = viewDir[0];
|
||||
matrix(2,1) = viewDir[1];
|
||||
matrix(2,2) = viewDir[2];
|
||||
|
||||
matrix(0,3) = -vtkm::dot(right,position);
|
||||
matrix(1,3) = -vtkm::dot(ru,position);
|
||||
matrix(2,3) = -vtkm::dot(viewDir,position);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> WorldMatrix(const vtkm::Vec<vtkm::Float32,3> &neworigin,
|
||||
const vtkm::Vec<vtkm::Float32,3> &newx,
|
||||
const vtkm::Vec<vtkm::Float32,3> &newy,
|
||||
const vtkm::Vec<vtkm::Float32,3> &newz)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
||||
vtkm::MatrixIdentity(matrix);
|
||||
|
||||
matrix(0,0) = newx[0];
|
||||
matrix(0,1) = newy[0];
|
||||
matrix(0,2) = newz[0];
|
||||
matrix(1,0) = newx[1];
|
||||
matrix(1,1) = newy[1];
|
||||
matrix(1,2) = newz[1];
|
||||
matrix(2,0) = newx[2];
|
||||
matrix(2,1) = newy[2];
|
||||
matrix(2,2) = newz[2];
|
||||
|
||||
matrix(0,3) = neworigin[0];
|
||||
matrix(1,3) = neworigin[1];
|
||||
matrix(2,3) = neworigin[2];
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
||||
{
|
||||
return ScaleMatrix(v[0], v[1], v[2]);
|
||||
}
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &s)
|
||||
{
|
||||
return ScaleMatrix(s,s,s);
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &x,
|
||||
const vtkm::Float32 &y,
|
||||
const vtkm::Float32 &z)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> scaleMatrix(0.0f);
|
||||
scaleMatrix(0,0) = x;
|
||||
scaleMatrix(1,1) = y;
|
||||
scaleMatrix(2,2) = z;
|
||||
scaleMatrix(3,3) = 1.0f;
|
||||
return scaleMatrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
||||
{
|
||||
return TranslateMatrix(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Float32 &x,
|
||||
const vtkm::Float32 &y,
|
||||
const vtkm::Float32 &z)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> translateMatrix;
|
||||
vtkm::MatrixIdentity(translateMatrix);
|
||||
translateMatrix(0,3) = x;
|
||||
translateMatrix(1,3) = y;
|
||||
translateMatrix(2,3) = z;
|
||||
return translateMatrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> RotateXMatrix(vtkm::Float32 angleRadians)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> M;
|
||||
M(0,0) = 1.f;
|
||||
M(0,1) = 0.f;
|
||||
M(0,2) = 0.f;
|
||||
M(0,3) = 0.f;
|
||||
M(1,0) = 0.f;
|
||||
M(1,1) = cosf(angleRadians);
|
||||
M(1,2) = - sinf(angleRadians);
|
||||
M(1,3) = 0.f;
|
||||
M(2,0) = 0.f;
|
||||
M(2,1) = sinf(angleRadians);
|
||||
M(2,2) = cosf(angleRadians);
|
||||
M(2,3) = 0.f;
|
||||
M(3,0) = 0.f;
|
||||
M(3,1) = 0.f;
|
||||
M(3,2) = 0.f;
|
||||
M(3,3) = 1.f;
|
||||
return M;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> RotateYMatrix(vtkm::Float32 angleRadians)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> M;
|
||||
M(0,0) = cosf(angleRadians);
|
||||
M(0,1) = 0.f;
|
||||
M(0,2) = sinf(angleRadians);
|
||||
M(0,3) = 0.f;
|
||||
M(1,0) = 0.f;
|
||||
M(1,1) = 1.f;
|
||||
M(1,2) = 0.f;
|
||||
M(1,3) = 0.f;
|
||||
M(2,0) = - sinf(angleRadians);
|
||||
M(2,1) = 0.f;
|
||||
M(2,2) = cosf(angleRadians);
|
||||
M(2,3) = 0.f;
|
||||
M(3,0) = 0.f;
|
||||
M(3,1) = 0.f;
|
||||
M(3,2) = 0.f;
|
||||
M(3,3) = 1.f;
|
||||
return M;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> RotateZMatrix(vtkm::Float32 angleRadians)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> M;
|
||||
M(0,0) = cosf(angleRadians);
|
||||
M(0,1) = - sinf(angleRadians);
|
||||
M(0,2) = 0.f;
|
||||
M(0,3) = 0.f;
|
||||
M(1,0) = sinf(angleRadians);
|
||||
M(1,1) = cosf(angleRadians);
|
||||
M(1,2) = 0.f;
|
||||
M(1,3) = 0.f;
|
||||
M(2,0) = 0.f;
|
||||
M(2,1) = 0.f;
|
||||
M(2,2) = 1.f;
|
||||
M(2,3) = 0.f;
|
||||
M(3,0) = 0.f;
|
||||
M(3,1) = 0.f;
|
||||
M(3,2) = 0.f;
|
||||
M(3,3) = 1.f;
|
||||
return M;
|
||||
}
|
||||
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> TrackballMatrix(vtkm::Float32 p1x,
|
||||
vtkm::Float32 p1y,
|
||||
vtkm::Float32 p2x,
|
||||
vtkm::Float32 p2y)
|
||||
{
|
||||
const vtkm::Float32 RADIUS = 0.80f; //z value lookAt x = y = 0.0
|
||||
const vtkm::Float32 COMPRESSION = 3.5f; // multipliers for x and y.
|
||||
const vtkm::Float32 AR3 = RADIUS*RADIUS*RADIUS;
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
||||
|
||||
vtkm::MatrixIdentity(matrix);
|
||||
if (p1x==p2x && p1y==p2y) { return matrix; }
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> p1(p1x,p1y, AR3/((p1x*p1x+p1y*p1y)*COMPRESSION+AR3));
|
||||
vtkm::Vec<vtkm::Float32, 3> p2(p2x,p2y, AR3/((p2x*p2x+p2y*p2y)*COMPRESSION+AR3));
|
||||
vtkm::Vec<vtkm::Float32, 3> axis = vtkm::Normal(vtkm::Cross(p2,p1));
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> p2_p1(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]);
|
||||
vtkm::Float32 t = vtkm::Magnitude(p2_p1);
|
||||
t = vtkm::Min(vtkm::Max(t, -1.0f), 1.0f);
|
||||
vtkm::Float32 phi = static_cast<vtkm::Float32>(-2.0f*asin(t/(2.0f*RADIUS)));
|
||||
vtkm::Float32 val = static_cast<vtkm::Float32>(sin(phi/2.0f));
|
||||
axis[0] *= val;
|
||||
axis[1] *= val;
|
||||
axis[2] *= val;
|
||||
|
||||
//quaternion
|
||||
vtkm::Float32 q[4] = {axis[0], axis[1], axis[2], static_cast<vtkm::Float32>(cos(phi/2.0f))};
|
||||
|
||||
// normalize quaternion to unit magnitude
|
||||
t = 1.0f / static_cast<vtkm::Float32>(sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]));
|
||||
q[0] *= t;
|
||||
q[1] *= t;
|
||||
q[2] *= t;
|
||||
q[3] *= t;
|
||||
|
||||
matrix(0,0) = 1 - 2 * (q[1]*q[1] + q[2]*q[2]);
|
||||
matrix(0,1) = 2 * (q[0]*q[1] + q[2]*q[3]);
|
||||
matrix(0,2) = (2 * (q[2]*q[0] - q[1]*q[3]) );
|
||||
|
||||
matrix(1,0) = 2 * (q[0]*q[1] - q[2]*q[3]);
|
||||
matrix(1,1) = 1 - 2 * (q[2]*q[2] + q[0]*q[0]);
|
||||
matrix(1,2) = (2 * (q[1]*q[2] + q[0]*q[3]) );
|
||||
|
||||
matrix(2,0) = (2 * (q[2]*q[0] + q[1]*q[3]) );
|
||||
matrix(2,1) = (2 * (q[1]*q[2] - q[0]*q[3]) );
|
||||
matrix(2,2) = (1 - 2 * (q[1]*q[1] + q[0]*q[0]) );
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
||||
#endif // vtk_m_rendering_MatrixHelpers_h
|
@ -34,47 +34,54 @@ namespace rendering {
|
||||
class RenderSurface
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurface(std::size_t width=1024, std::size_t height=1024,
|
||||
const vtkm::rendering::Color &color=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: Width(width), Height(height), BackgroundColor(color)
|
||||
{
|
||||
this->ColorBuffer.resize(width*height*4);
|
||||
this->DepthBuffer.resize(width*height);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurface(std::size_t width=1024, std::size_t height=1024,
|
||||
const vtkm::rendering::Color &color=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: Width(width), Height(height), BackgroundColor(color)
|
||||
{
|
||||
this->ColorBuffer.resize(width*height*4);
|
||||
this->DepthBuffer.resize(width*height);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Activate() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Activate() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear() {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish() {}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToWorldSpace(vtkm::rendering::View &, bool) {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToScreenSpace(vtkm::rendering::View &, bool) {}
|
||||
VTKM_CONT_EXPORT
|
||||
void SetViewportClipping(vtkm::rendering::View &, bool) {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToWorldSpace(vtkm::rendering::View &, bool) {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToScreenSpace(vtkm::rendering::View &, bool) {}
|
||||
VTKM_CONT_EXPORT
|
||||
void SetViewportClipping(vtkm::rendering::View &, bool) {}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &) {}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &) {}
|
||||
|
||||
virtual void AddLine(vtkm::Float64, vtkm::Float64,
|
||||
vtkm::Float64, vtkm::Float64,
|
||||
vtkm::Float32,
|
||||
const vtkm::rendering::Color &) {}
|
||||
virtual void AddColorBar(vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32,
|
||||
const vtkm::rendering::ColorTable &,
|
||||
bool) {}
|
||||
virtual void AddLine(vtkm::Float64, vtkm::Float64,
|
||||
vtkm::Float64, vtkm::Float64,
|
||||
vtkm::Float32,
|
||||
const vtkm::rendering::Color &) {}
|
||||
virtual void AddColorBar(vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32,
|
||||
const vtkm::rendering::ColorTable &,
|
||||
bool) {}
|
||||
virtual void AddText(vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32,
|
||||
vtkm::Float32,
|
||||
vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32,
|
||||
Color,
|
||||
std::string) {}
|
||||
|
||||
std::size_t Width, Height;
|
||||
vtkm::rendering::Color BackgroundColor;
|
||||
std::vector<vtkm::Float32> ColorBuffer;
|
||||
std::vector<vtkm::Float32> DepthBuffer;
|
||||
std::size_t Width, Height;
|
||||
vtkm::rendering::Color BackgroundColor;
|
||||
std::vector<vtkm::Float32> ColorBuffer;
|
||||
std::vector<vtkm::Float32> DepthBuffer;
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
@ -24,6 +24,10 @@
|
||||
#include <vtkm/rendering/View.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/RenderSurface.h>
|
||||
#include <vtkm/rendering/BitmapFont.h>
|
||||
#include <vtkm/rendering/BitmapFontFactory.h>
|
||||
#include <vtkm/rendering/TextureGL.h>
|
||||
#include <vtkm/rendering/MatrixHelpers.h>
|
||||
#include <vtkm/rendering/internal/OpenGLHeaders.h>
|
||||
|
||||
#include <iostream>
|
||||
@ -35,193 +39,266 @@ namespace rendering {
|
||||
class RenderSurfaceGL : public RenderSurface
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceGL(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurface(w,h,c)
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceGL(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurface(w,h,c)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
glClearColor(this->BackgroundColor.Components[0],
|
||||
this->BackgroundColor.Components[1],
|
||||
this->BackgroundColor.Components[2],
|
||||
1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
{
|
||||
glFinish();
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToWorldSpace(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
vtkm::Float32 oglP[16], oglM[16];
|
||||
|
||||
MatrixHelpers::CreateOGLMatrix(v.CreateProjectionMatrix(), oglP);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(oglP);
|
||||
MatrixHelpers::CreateOGLMatrix(v.CreateViewMatrix(), oglM);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(oglM);
|
||||
|
||||
SetViewportClipping(v, clip);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToScreenSpace(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
vtkm::Float32 oglP[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
vtkm::Float32 oglM[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
|
||||
oglP[0*4+0] = 1.;
|
||||
oglP[1*4+1] = 1.;
|
||||
oglP[2*4+2] = -1.;
|
||||
oglP[3*4+3] = 1.;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(oglP);
|
||||
|
||||
oglM[0*4+0] = 1.;
|
||||
oglM[1*4+1] = 1.;
|
||||
oglM[2*4+2] = 1.;
|
||||
oglM[3*4+3] = 1.;
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(oglM);
|
||||
|
||||
SetViewportClipping(v, clip);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewportClipping(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
if (clip)
|
||||
{
|
||||
vtkm::Float32 vl, vr, vb, vt;
|
||||
v.GetRealViewport(vl,vr,vb,vt);
|
||||
vtkm::Float32 _x = static_cast<vtkm::Float32>(v.Width)*(1.f+vl)/2.f;
|
||||
vtkm::Float32 _y = static_cast<vtkm::Float32>(v.Height)*(1.f+vb)/2.f;
|
||||
vtkm::Float32 _w = static_cast<vtkm::Float32>(v.Width)*(vr-vl)/2.f;
|
||||
vtkm::Float32 _h = static_cast<vtkm::Float32>(v.Height)*(vt-vb)/2.f;
|
||||
|
||||
glViewport(static_cast<int>(_x), static_cast<int>(_y),
|
||||
static_cast<int>(_w), static_cast<int>(_h));
|
||||
}
|
||||
else
|
||||
{
|
||||
glViewport(0,0, v.Width, v.Height);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &fileName)
|
||||
{
|
||||
std::ofstream of(fileName.c_str());
|
||||
of << "P6" << std::endl
|
||||
<< this->Width << " " << this->Height <<std::endl
|
||||
<< 255 << std::endl;
|
||||
int height = static_cast<int>(this->Height);
|
||||
for (int yIndex=height-1; yIndex>=0; yIndex--)
|
||||
for (std::size_t xIndex=0; xIndex < this->Width; xIndex++)
|
||||
{
|
||||
const vtkm::Float32 *tuple =
|
||||
&(this->ColorBuffer[static_cast<std::size_t>(yIndex)*this->Width*4 + xIndex*4]);
|
||||
of<<(unsigned char)(tuple[0]*255);
|
||||
of<<(unsigned char)(tuple[1]*255);
|
||||
of<<(unsigned char)(tuple[2]*255);
|
||||
}
|
||||
of.close();
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void AddLine(vtkm::Float64 x0, vtkm::Float64 y0,
|
||||
vtkm::Float64 x1, vtkm::Float64 y1,
|
||||
vtkm::Float32 linewidth,
|
||||
const vtkm::rendering::Color &c)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3fv(c.Components);
|
||||
|
||||
glLineWidth(linewidth);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(float(x0),float(y0));
|
||||
glVertex2f(float(x1),float(y1));
|
||||
glEnd();
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void AddColorBar(vtkm::Float32 x, vtkm::Float32 y,
|
||||
vtkm::Float32 w, vtkm::Float32 h,
|
||||
const vtkm::rendering::ColorTable &ct,
|
||||
bool horizontal)
|
||||
{
|
||||
const int n = 256;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_QUADS);
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
vtkm::Float32 v0 = static_cast<vtkm::Float32>(i)/static_cast<vtkm::Float32>(n);
|
||||
vtkm::Float32 v1 = static_cast<vtkm::Float32>(i+1)/static_cast<vtkm::Float32>(n);
|
||||
Color c0 = ct.MapRGB(v0);
|
||||
Color c1 = ct.MapRGB(v1);
|
||||
if (horizontal)
|
||||
{
|
||||
vtkm::Float32 x0 = x + w*v0;
|
||||
vtkm::Float32 x1 = x + w*v1;
|
||||
vtkm::Float32 y0 = y;
|
||||
vtkm::Float32 y1 = y + h;
|
||||
glColor3fv(c0.Components);
|
||||
glVertex2f(x0,y0);
|
||||
glVertex2f(x0,y1);
|
||||
glColor3fv(c1.Components);
|
||||
glVertex2f(x1,y1);
|
||||
glVertex2f(x1,y0);
|
||||
}
|
||||
else // vertical
|
||||
{
|
||||
vtkm::Float32 x0 = x;
|
||||
vtkm::Float32 x1 = x + w;
|
||||
vtkm::Float32 y0 = y + h*v0;
|
||||
vtkm::Float32 y1 = y + h*v1;
|
||||
glColor3fv(c0.Components);
|
||||
glVertex2f(x0,y1);
|
||||
glVertex2f(x1,y1);
|
||||
glColor3fv(c1.Components);
|
||||
glVertex2f(x1,y0);
|
||||
glVertex2f(x0,y0);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void AddText(vtkm::Float32 x, vtkm::Float32 y,
|
||||
vtkm::Float32 scale,
|
||||
vtkm::Float32 angle,
|
||||
vtkm::Float32 windowaspect,
|
||||
vtkm::Float32 anchorx, vtkm::Float32 anchory,
|
||||
Color color,
|
||||
std::string text)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(x,y,0);
|
||||
glScalef(1.f/windowaspect, 1, 1);
|
||||
glRotatef(angle, 0,0,1);
|
||||
glColor3fv(color.Components);
|
||||
RenderText(scale, anchorx, anchory, text);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
private:
|
||||
BitmapFont Font;
|
||||
TextureGL FontTexture;
|
||||
|
||||
void RenderText(vtkm::Float32 scale,
|
||||
vtkm::Float32 anchorx, vtkm::Float32 anchory,
|
||||
std::string text)
|
||||
{
|
||||
if (this->FontTexture.ID == 0)
|
||||
{
|
||||
Font = BitmapFontFactory::CreateLiberation2Sans();
|
||||
std::vector<unsigned char> &rawpngdata = this->Font.GetRawImageData();
|
||||
|
||||
std::vector<unsigned char> rgba;
|
||||
unsigned long width, height;
|
||||
int error = decodePNG(rgba, width, height,
|
||||
&rawpngdata[0], rawpngdata.size());
|
||||
if (error != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->FontTexture.CreateAlphaFromRGBA(int(width),int(height),rgba);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
|
||||
this->FontTexture.Enable();
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glDisable(GL_LIGHTING);
|
||||
//glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -.5);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
vtkm::Float32 textwidth = this->Font.GetTextWidth(text);
|
||||
|
||||
vtkm::Float32 fx = -(.5f + .5f*anchorx) * textwidth;
|
||||
vtkm::Float32 fy = -(.5f + .5f*anchory);
|
||||
vtkm::Float32 fz = 0;
|
||||
for (unsigned int i=0; i<text.length(); ++i)
|
||||
{
|
||||
glClearColor(this->BackgroundColor.Components[0],
|
||||
this->BackgroundColor.Components[1],
|
||||
this->BackgroundColor.Components[2],
|
||||
1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
{
|
||||
glFinish();
|
||||
char c = text[i];
|
||||
char nextchar = (i < text.length()-1) ? text[i+1] : 0;
|
||||
|
||||
vtkm::Float32 vl,vr,vt,vb;
|
||||
vtkm::Float32 tl,tr,tt,tb;
|
||||
this->Font.GetCharPolygon(c, fx, fy,
|
||||
vl, vr, vt, vb,
|
||||
tl, tr, tt, tb, nextchar);
|
||||
|
||||
glTexCoord2f(tl, 1.f-tt);
|
||||
glVertex3f(scale*vl, scale*vt, fz);
|
||||
|
||||
glTexCoord2f(tl, 1.f-tb);
|
||||
glVertex3f(scale*vl, scale*vb, fz);
|
||||
|
||||
glTexCoord2f(tr, 1.f-tb);
|
||||
glVertex3f(scale*vr, scale*vb, fz);
|
||||
|
||||
glTexCoord2f(tr, 1.f-tt);
|
||||
glVertex3f(scale*vr, scale*vt, fz);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToWorldSpace(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
vtkm::Float32 oglP[16], oglM[16];
|
||||
glEnd();
|
||||
|
||||
CreateOGLMatrix(v.CreateProjectionMatrix(), oglP);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(oglP);
|
||||
CreateOGLMatrix(v.CreateViewMatrix(), oglM);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(oglM);
|
||||
this->FontTexture.Disable();
|
||||
|
||||
SetViewportClipping(v, clip);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewToScreenSpace(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
vtkm::Float32 oglP[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
vtkm::Float32 oglM[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
|
||||
oglP[0*4+0] = 1.;
|
||||
oglP[1*4+1] = 1.;
|
||||
oglP[2*4+2] = -1.;
|
||||
oglP[3*4+3] = 1.;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(oglP);
|
||||
|
||||
oglM[0*4+0] = 1.;
|
||||
oglM[1*4+1] = 1.;
|
||||
oglM[2*4+2] = 1.;
|
||||
oglM[3*4+3] = 1.;
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(oglM);
|
||||
|
||||
SetViewportClipping(v, clip);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SetViewportClipping(vtkm::rendering::View &v, bool clip)
|
||||
{
|
||||
if (clip)
|
||||
{
|
||||
vtkm::Float32 vl, vr, vb, vt;
|
||||
v.GetRealViewport(vl,vr,vb,vt);
|
||||
vtkm::Float32 _x = static_cast<vtkm::Float32>(v.Width)*(1.f+vl)/2.f;
|
||||
vtkm::Float32 _y = static_cast<vtkm::Float32>(v.Height)*(1.f+vb)/2.f;
|
||||
vtkm::Float32 _w = static_cast<vtkm::Float32>(v.Width)*(vr-vl)/2.f;
|
||||
vtkm::Float32 _h = static_cast<vtkm::Float32>(v.Height)*(vt-vb)/2.f;
|
||||
|
||||
glViewport(static_cast<int>(_x), static_cast<int>(_y),
|
||||
static_cast<int>(_w), static_cast<int>(_h));
|
||||
}
|
||||
else
|
||||
{
|
||||
glViewport(0,0, v.Width, v.Height);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void CreateOGLMatrix(const vtkm::Matrix<vtkm::Float32,4,4> &mtx,
|
||||
vtkm::Float32 *oglM)
|
||||
{
|
||||
oglM[ 0] = mtx[0][0];
|
||||
oglM[ 1] = mtx[1][0];
|
||||
oglM[ 2] = mtx[2][0];
|
||||
oglM[ 3] = mtx[3][0];
|
||||
oglM[ 4] = mtx[0][1];
|
||||
oglM[ 5] = mtx[1][1];
|
||||
oglM[ 6] = mtx[2][1];
|
||||
oglM[ 7] = mtx[3][1];
|
||||
oglM[ 8] = mtx[0][2];
|
||||
oglM[ 9] = mtx[1][2];
|
||||
oglM[10] = mtx[2][2];
|
||||
oglM[11] = mtx[3][2];
|
||||
oglM[12] = mtx[0][3];
|
||||
oglM[13] = mtx[1][3];
|
||||
oglM[14] = mtx[2][3];
|
||||
oglM[15] = mtx[3][3];
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &fileName)
|
||||
{
|
||||
std::ofstream of(fileName.c_str());
|
||||
of << "P6" << std::endl
|
||||
<< this->Width << " " << this->Height <<std::endl
|
||||
<< 255 << std::endl;
|
||||
int height = static_cast<int>(this->Height);
|
||||
for (int yIndex=height-1; yIndex>=0; yIndex--)
|
||||
for (std::size_t xIndex=0; xIndex < this->Width; xIndex++)
|
||||
{
|
||||
const vtkm::Float32 *tuple =
|
||||
&(this->ColorBuffer[static_cast<std::size_t>(yIndex)*this->Width*4 + xIndex*4]);
|
||||
of<<(unsigned char)(tuple[0]*255);
|
||||
of<<(unsigned char)(tuple[1]*255);
|
||||
of<<(unsigned char)(tuple[2]*255);
|
||||
}
|
||||
of.close();
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void AddLine(vtkm::Float64 x0, vtkm::Float64 y0,
|
||||
vtkm::Float64 x1, vtkm::Float64 y1,
|
||||
vtkm::Float32 linewidth,
|
||||
const vtkm::rendering::Color &c)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3fv(c.Components);
|
||||
|
||||
glLineWidth(linewidth);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(float(x0),float(y0));
|
||||
glVertex2f(float(x1),float(y1));
|
||||
glEnd();
|
||||
}
|
||||
|
||||
virtual void AddColorBar(vtkm::Float32 x, vtkm::Float32 y,
|
||||
vtkm::Float32 w, vtkm::Float32 h,
|
||||
const vtkm::rendering::ColorTable &ct,
|
||||
bool horizontal)
|
||||
{
|
||||
const int n = 256;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_QUADS);
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
vtkm::Float32 v0 = static_cast<vtkm::Float32>(i)/static_cast<vtkm::Float32>(n);
|
||||
vtkm::Float32 v1 = static_cast<vtkm::Float32>(i+1)/static_cast<vtkm::Float32>(n);
|
||||
Color c0 = ct.MapRGB(v0);
|
||||
Color c1 = ct.MapRGB(v1);
|
||||
if (horizontal)
|
||||
{
|
||||
vtkm::Float32 x0 = x + w*v0;
|
||||
vtkm::Float32 x1 = x + w*v1;
|
||||
vtkm::Float32 y0 = y;
|
||||
vtkm::Float32 y1 = y + h;
|
||||
glColor3fv(c0.Components);
|
||||
glVertex2f(x0,y0);
|
||||
glVertex2f(x0,y1);
|
||||
glColor3fv(c1.Components);
|
||||
glVertex2f(x1,y1);
|
||||
glVertex2f(x1,y0);
|
||||
}
|
||||
else // vertical
|
||||
{
|
||||
vtkm::Float32 x0 = x;
|
||||
vtkm::Float32 x1 = x + w;
|
||||
vtkm::Float32 y0 = y + h*v0;
|
||||
vtkm::Float32 y1 = y + h*v1;
|
||||
glColor3fv(c0.Components);
|
||||
glVertex2f(x0,y1);
|
||||
glVertex2f(x1,y1);
|
||||
glColor3fv(c1.Components);
|
||||
glVertex2f(x1,y0);
|
||||
glVertex2f(x0,y0);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
//glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
}
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
@ -36,54 +36,56 @@ namespace rendering {
|
||||
class RenderSurfaceGLX : public RenderSurfaceGL
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceGLX(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurfaceGL(w,h,c)
|
||||
{
|
||||
ctx = NULL;
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceGLX(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurfaceGL(w,h,c)
|
||||
{
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize()
|
||||
{
|
||||
ctx = glXGetCurrentContext();
|
||||
if (!ctx)
|
||||
throw vtkm::cont::ErrorControlBadValue("GL context creation failed.");
|
||||
rgba.resize(width*height*4);
|
||||
/*
|
||||
if (!OSMesaMakeCurrent(ctx, &rgba[0], GL_FLOAT, static_cast<GLsizei>(width), static_cast<GLsizei>(height)))
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context activation failed.");
|
||||
*/
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize()
|
||||
{
|
||||
ctx = glXGetCurrentContext();
|
||||
if (!ctx)
|
||||
throw vtkm::cont::ErrorControlBadValue("GL context creation failed.");
|
||||
/*
|
||||
rgba.resize(width*height*4);
|
||||
if (!OSMesaMakeCurrent(ctx, &rgba[0], GL_FLOAT, static_cast<GLsizei>(width), static_cast<GLsizei>(height)))
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context activation failed.");
|
||||
*/
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
glClearColor(bgColor.Components[0],bgColor.Components[1],bgColor.Components[2], 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
{
|
||||
RenderSurfaceGL::Finish();
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
glClearColor(this->BackgroundColor.Components[0],
|
||||
this->BackgroundColor.Components[1],
|
||||
this->BackgroundColor.Components[2], 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
{
|
||||
RenderSurfaceGL::Finish();
|
||||
|
||||
|
||||
/* TODO
|
||||
//Copy zbuff into floating point array.
|
||||
unsigned int *raw_zbuff;
|
||||
int zbytes, w, h;
|
||||
GLboolean ret;
|
||||
ret = OSMesaGetDepthBuffer(ctx, &w, &h, &zbytes, (void**)&raw_zbuff);
|
||||
if (!ret || static_cast<std::size_t>(w)!=width || static_cast<std::size_t>(h)!=height)
|
||||
throw vtkm::cont::ErrorControlBadValue("Wrong width/height in ZBuffer");
|
||||
std::size_t npixels = width*height;
|
||||
for (std::size_t i=0; i<npixels; i++)
|
||||
zbuff[i] = float(raw_zbuff[i]) / float(UINT_MAX);
|
||||
*/
|
||||
}
|
||||
/* TODO
|
||||
//Copy zbuff into floating point array.
|
||||
unsigned int *raw_zbuff;
|
||||
int zbytes, w, h;
|
||||
GLboolean ret;
|
||||
ret = OSMesaGetDepthBuffer(ctx, &w, &h, &zbytes, (void**)&raw_zbuff);
|
||||
if (!ret || static_cast<std::size_t>(w)!=width || static_cast<std::size_t>(h)!=height)
|
||||
throw vtkm::cont::ErrorControlBadValue("Wrong width/height in ZBuffer");
|
||||
std::size_t npixels = width*height;
|
||||
for (std::size_t i=0; i<npixels; i++)
|
||||
zbuff[i] = float(raw_zbuff[i]) / float(UINT_MAX);
|
||||
*/
|
||||
}
|
||||
|
||||
private:
|
||||
GLXContext ctx;
|
||||
|
@ -36,64 +36,64 @@ namespace rendering {
|
||||
class RenderSurfaceOSMesa : public RenderSurfaceGL
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceOSMesa(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurfaceGL(w,h,c)
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceOSMesa(std::size_t w=1024, std::size_t h=1024,
|
||||
const vtkm::rendering::Color &c=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurfaceGL(w,h,c)
|
||||
{
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize()
|
||||
{
|
||||
ctx = OSMesaCreateContextExt(OSMESA_RGBA, 32, 0, 0, NULL);
|
||||
if (!ctx)
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context creation failed.");
|
||||
this->ColorBuffer.resize(this->Width*this->Height*4);
|
||||
if (!OSMesaMakeCurrent(ctx,
|
||||
&this->ColorBuffer[0],
|
||||
GL_FLOAT,
|
||||
static_cast<GLsizei>(this->Width),
|
||||
static_cast<GLsizei>(this->Height)))
|
||||
{
|
||||
ctx = NULL;
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context activation failed.");
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Initialize()
|
||||
{
|
||||
ctx = OSMesaCreateContextExt(OSMESA_RGBA, 32, 0, 0, NULL);
|
||||
if (!ctx)
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context creation failed.");
|
||||
this->ColorBuffer.resize(this->Width*this->Height*4);
|
||||
if (!OSMesaMakeCurrent(ctx,
|
||||
&this->ColorBuffer[0],
|
||||
GL_FLOAT,
|
||||
static_cast<GLsizei>(this->Width),
|
||||
static_cast<GLsizei>(this->Height)))
|
||||
{
|
||||
throw vtkm::cont::ErrorControlBadValue("OSMesa context activation failed.");
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
glClearColor(this->BackgroundColor.Components[0],
|
||||
this->BackgroundColor.Components[1],
|
||||
this->BackgroundColor.Components[2],
|
||||
1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
{
|
||||
RenderSurfaceGL::Finish();
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
//Copy zbuff into floating point array.
|
||||
unsigned int *raw_zbuff;
|
||||
int zbytes, w, h;
|
||||
GLboolean ret;
|
||||
ret = OSMesaGetDepthBuffer(ctx, &w, &h, &zbytes, (void**)&raw_zbuff);
|
||||
if (!ret ||
|
||||
static_cast<std::size_t>(w)!=this->Width ||
|
||||
static_cast<std::size_t>(h)!=this->Height)
|
||||
{
|
||||
glClearColor(this->BackgroundColor.Components[0],
|
||||
this->BackgroundColor.Components[1],
|
||||
this->BackgroundColor.Components[2],
|
||||
1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
throw vtkm::cont::ErrorControlBadValue("Wrong width/height in ZBuffer");
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Finish()
|
||||
std::size_t npixels = this->Width*this->Height;
|
||||
for (std::size_t i=0; i<npixels; i++)
|
||||
{
|
||||
RenderSurfaceGL::Finish();
|
||||
|
||||
//Copy zbuff into floating point array.
|
||||
unsigned int *raw_zbuff;
|
||||
int zbytes, w, h;
|
||||
GLboolean ret;
|
||||
ret = OSMesaGetDepthBuffer(ctx, &w, &h, &zbytes, (void**)&raw_zbuff);
|
||||
if (!ret ||
|
||||
static_cast<std::size_t>(w)!=this->Width ||
|
||||
static_cast<std::size_t>(h)!=this->Height)
|
||||
{
|
||||
throw vtkm::cont::ErrorControlBadValue("Wrong width/height in ZBuffer");
|
||||
}
|
||||
std::size_t npixels = this->Width*this->Height;
|
||||
for (std::size_t i=0; i<npixels; i++)
|
||||
{
|
||||
this->DepthBuffer[i] = float(raw_zbuff[i]) / float(UINT_MAX);
|
||||
}
|
||||
this->DepthBuffer[i] = float(raw_zbuff[i]) / float(UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OSMesaContext ctx;
|
||||
|
@ -36,77 +36,77 @@ namespace rendering {
|
||||
class RenderSurfaceRayTracer : public RenderSurface
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceRayTracer(std::size_t width=1024, std::size_t height=1024,
|
||||
const vtkm::rendering::Color &color=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurface(width,height,color)
|
||||
{
|
||||
this->ColorArray = vtkm::cont::make_ArrayHandle(this->ColorBuffer);
|
||||
this->DepthArray = vtkm::cont::make_ArrayHandle(this->DepthBuffer);
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
RenderSurfaceRayTracer(std::size_t width=1024, std::size_t height=1024,
|
||||
const vtkm::rendering::Color &color=vtkm::rendering::Color(0.0f,0.0f,0.0f,1.0f))
|
||||
: RenderSurface(width,height,color)
|
||||
{
|
||||
this->ColorArray = vtkm::cont::make_ArrayHandle(this->ColorBuffer);
|
||||
this->DepthArray = vtkm::cont::make_ArrayHandle(this->DepthBuffer);
|
||||
}
|
||||
|
||||
class ClearBuffers : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::rendering::Color ClearColor;
|
||||
vtkm::Id NumPixels;
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
ClearBuffers(const vtkm::rendering::Color &clearColor,
|
||||
vtkm::Id numPixels)
|
||||
class ClearBuffers : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::rendering::Color ClearColor;
|
||||
vtkm::Id NumPixels;
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
ClearBuffers(const vtkm::rendering::Color &clearColor,
|
||||
vtkm::Id numPixels)
|
||||
: ClearColor(clearColor),
|
||||
NumPixels(numPixels)
|
||||
{}
|
||||
typedef void ControlSignature(FieldOut<>,
|
||||
ExecObject);
|
||||
typedef void ExecutionSignature(_1,
|
||||
_2,
|
||||
WorkIndex);
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Float32 &depth,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32> &colorBuffer,
|
||||
const vtkm::Id &index) const
|
||||
{}
|
||||
typedef void ControlSignature(FieldOut<>,
|
||||
ExecObject);
|
||||
typedef void ExecutionSignature(_1,
|
||||
_2,
|
||||
WorkIndex);
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Float32 &depth,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32> &colorBuffer,
|
||||
const vtkm::Id &index) const
|
||||
{
|
||||
if(index >= NumPixels) return;
|
||||
depth = 1.001f;
|
||||
vtkm::Id offset = index * 4;
|
||||
colorBuffer.Set(offset + 0, ClearColor.Components[0]);
|
||||
colorBuffer.Set(offset + 1, ClearColor.Components[1]);
|
||||
colorBuffer.Set(offset + 2, ClearColor.Components[2]);
|
||||
colorBuffer.Set(offset + 3, ClearColor.Components[3]);
|
||||
}
|
||||
}; //class ClearBuffers
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &fileName)
|
||||
{
|
||||
std::ofstream of(fileName.c_str());
|
||||
of<<"P6"<<std::endl<<this->Width<<" "<<this->Height<<std::endl<<255<<std::endl;
|
||||
int height = static_cast<int>(this->Height);
|
||||
for (int yIndex=height-1; yIndex>=0; yIndex--)
|
||||
for (std::size_t xIndex=0; xIndex < this->Width; xIndex++)
|
||||
{
|
||||
if(index >= NumPixels) return;
|
||||
depth = 1.001f;
|
||||
vtkm::Id offset = index * 4;
|
||||
colorBuffer.Set(offset + 0, ClearColor.Components[0]);
|
||||
colorBuffer.Set(offset + 1, ClearColor.Components[1]);
|
||||
colorBuffer.Set(offset + 2, ClearColor.Components[2]);
|
||||
colorBuffer.Set(offset + 3, ClearColor.Components[3]);
|
||||
const vtkm::Float32 *tuple =
|
||||
&(this->ColorBuffer[static_cast<std::size_t>(yIndex)*this->Width*4 + xIndex*4]);
|
||||
of<<(unsigned char)(tuple[0]*255);
|
||||
of<<(unsigned char)(tuple[1]*255);
|
||||
of<<(unsigned char)(tuple[2]*255);
|
||||
}
|
||||
}; //class ClearBuffers
|
||||
of.close();
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
this->ColorArray = vtkm::cont::make_ArrayHandle(this->ColorBuffer);
|
||||
this->DepthArray = vtkm::cont::make_ArrayHandle(this->DepthBuffer);
|
||||
vtkm::worklet::DispatcherMapField< ClearBuffers >(
|
||||
ClearBuffers( this->BackgroundColor,
|
||||
static_cast<vtkm::Int32>(this->Width*this->Height) ) )
|
||||
.Invoke( this->DepthArray,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>(this->ColorArray) );
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void SaveAs(const std::string &fileName)
|
||||
{
|
||||
std::ofstream of(fileName.c_str());
|
||||
of<<"P6"<<std::endl<<this->Width<<" "<<this->Height<<std::endl<<255<<std::endl;
|
||||
int height = static_cast<int>(this->Height);
|
||||
for (int yIndex=height-1; yIndex>=0; yIndex--)
|
||||
for (std::size_t xIndex=0; xIndex < this->Width; xIndex++)
|
||||
{
|
||||
const vtkm::Float32 *tuple =
|
||||
&(this->ColorBuffer[static_cast<std::size_t>(yIndex)*this->Width*4 + xIndex*4]);
|
||||
of<<(unsigned char)(tuple[0]*255);
|
||||
of<<(unsigned char)(tuple[1]*255);
|
||||
of<<(unsigned char)(tuple[2]*255);
|
||||
}
|
||||
of.close();
|
||||
}
|
||||
VTKM_CONT_EXPORT
|
||||
virtual void Clear()
|
||||
{
|
||||
this->ColorArray = vtkm::cont::make_ArrayHandle(this->ColorBuffer);
|
||||
this->DepthArray = vtkm::cont::make_ArrayHandle(this->DepthBuffer);
|
||||
vtkm::worklet::DispatcherMapField< ClearBuffers >(
|
||||
ClearBuffers( this->BackgroundColor,
|
||||
static_cast<vtkm::Int32>(this->Width*this->Height) ) )
|
||||
.Invoke( this->DepthArray,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>(this->ColorArray) );
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> ColorArray;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DepthArray;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> ColorArray;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DepthArray;
|
||||
|
||||
};
|
||||
|
||||
|
@ -31,12 +31,8 @@ class Scene
|
||||
{
|
||||
public:
|
||||
std::vector<vtkm::rendering::Plot> Plots;
|
||||
};
|
||||
|
||||
class Scene3D : public Scene
|
||||
{
|
||||
public:
|
||||
Scene3D() {}
|
||||
Scene() {}
|
||||
|
||||
template<typename SceneRendererType, typename SurfaceType>
|
||||
VTKM_CONT_EXPORT
|
||||
@ -68,26 +64,6 @@ protected:
|
||||
vtkm::Bounds SpatialBounds;
|
||||
};
|
||||
|
||||
class Scene2D : public Scene
|
||||
{
|
||||
public:
|
||||
Scene2D() {}
|
||||
|
||||
template<typename SceneRendererType, typename SurfaceType>
|
||||
VTKM_CONT_EXPORT
|
||||
void Render(SceneRendererType &sceneRenderer,
|
||||
SurfaceType &surface,
|
||||
vtkm::rendering::View &view)
|
||||
{
|
||||
for (std::size_t i = 0; i < this->Plots.size(); i++)
|
||||
{
|
||||
sceneRenderer.StartScene();
|
||||
this->Plots[i].Render(sceneRenderer, surface, view);
|
||||
sceneRenderer.EndScene();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
||||
#endif //vtk_m_rendering_Scene_h
|
||||
|
248
vtkm/rendering/TextAnnotation.h
Normal file
248
vtkm/rendering/TextAnnotation.h
Normal file
@ -0,0 +1,248 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_TextAnnotation_h
|
||||
#define vtk_m_rendering_TextAnnotation_h
|
||||
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
#include <vtkm/rendering/RenderSurface.h>
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
|
||||
class TextAnnotation
|
||||
{
|
||||
public:
|
||||
enum HorizontalAlignment
|
||||
{
|
||||
Left,
|
||||
HCenter,
|
||||
Right
|
||||
};
|
||||
enum VerticalAlignment
|
||||
{
|
||||
Bottom,
|
||||
VCenter,
|
||||
Top
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string Text;
|
||||
Color TextColor;
|
||||
vtkm::Float32 Scale;
|
||||
vtkm::Float32 AnchorX, AnchorY;
|
||||
|
||||
public:
|
||||
TextAnnotation(const std::string &txt, Color c, vtkm::Float32 s)
|
||||
: Text(txt), TextColor(c), Scale(s)
|
||||
{
|
||||
// default anchor: bottom-left
|
||||
AnchorX = -1;
|
||||
AnchorY = -1;
|
||||
}
|
||||
virtual ~TextAnnotation()
|
||||
{
|
||||
}
|
||||
void SetText(const std::string &txt)
|
||||
{
|
||||
Text = txt;
|
||||
}
|
||||
void SetRawAnchor(vtkm::Float32 h, vtkm::Float32 v)
|
||||
{
|
||||
AnchorX = h;
|
||||
AnchorY = v;
|
||||
}
|
||||
void SetAlignment(HorizontalAlignment h, VerticalAlignment v)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
case Left: AnchorX = -1.0f; break;
|
||||
case HCenter: AnchorX = 0.0f; break;
|
||||
case Right: AnchorX = +1.0f; break;
|
||||
}
|
||||
|
||||
// For vertical alignment, "center" is generally the center
|
||||
// of only the above-baseline contents of the font, so we
|
||||
// use a value slightly off of zero for VCenter.
|
||||
// (We don't use an offset value instead of -1.0 for the
|
||||
// bottom value, because generally we want a true minimum
|
||||
// extent, e.g. to have text sitting at the bottom of a
|
||||
// window, and in that case, we need to keep all the text,
|
||||
// including parts that descend below the baseline, above
|
||||
// the bottom of the window.
|
||||
switch (v)
|
||||
{
|
||||
case Bottom: AnchorY = -1.0f; break;
|
||||
case VCenter: AnchorY = -0.06f; break;
|
||||
case Top: AnchorY = +1.0f; break;
|
||||
}
|
||||
}
|
||||
void SetScale(vtkm::Float32 s)
|
||||
{
|
||||
Scale = s;
|
||||
}
|
||||
virtual void Render(View &view,
|
||||
WorldAnnotator &worldAnnotator,
|
||||
RenderSurface &renderSurface) = 0;
|
||||
};
|
||||
|
||||
class ScreenTextAnnotation : public TextAnnotation
|
||||
{
|
||||
protected:
|
||||
vtkm::Float32 XPos,YPos;
|
||||
vtkm::Float32 Angle;
|
||||
public:
|
||||
ScreenTextAnnotation(const std::string &txt, Color c, vtkm::Float32 s,
|
||||
vtkm::Float32 ox, vtkm::Float32 oy, vtkm::Float32 angleDeg = 0.)
|
||||
: TextAnnotation(txt,c,s)
|
||||
{
|
||||
XPos = ox;
|
||||
YPos = oy;
|
||||
Angle = angleDeg;
|
||||
}
|
||||
void SetPosition(vtkm::Float32 ox, vtkm::Float32 oy)
|
||||
{
|
||||
XPos = ox;
|
||||
YPos = oy;
|
||||
}
|
||||
virtual void Render(View &view,
|
||||
WorldAnnotator &,
|
||||
RenderSurface &renderSurface)
|
||||
{
|
||||
vtkm::Float32 WindowAspect = vtkm::Float32(view.Width) /
|
||||
vtkm::Float32(view.Height);
|
||||
|
||||
renderSurface.AddText(XPos,YPos,
|
||||
Scale,
|
||||
Angle,
|
||||
WindowAspect,
|
||||
AnchorX, AnchorY,
|
||||
TextColor, Text);
|
||||
}
|
||||
};
|
||||
|
||||
class BillboardTextAnnotation : public TextAnnotation
|
||||
{
|
||||
protected:
|
||||
vtkm::Float32 XPos,YPos,ZPos;
|
||||
vtkm::Float32 Angle;
|
||||
public:
|
||||
BillboardTextAnnotation(const std::string &txt, Color c, vtkm::Float32 s,
|
||||
vtkm::Float32 ox, vtkm::Float32 oy, vtkm::Float32 oz,
|
||||
vtkm::Float32 angleDeg = 0.)
|
||||
: TextAnnotation(txt,c,s)
|
||||
{
|
||||
XPos = ox;
|
||||
YPos = oy;
|
||||
ZPos = oz;
|
||||
Angle = angleDeg;
|
||||
}
|
||||
void SetPosition(vtkm::Float32 ox, vtkm::Float32 oy, vtkm::Float32 oz)
|
||||
{
|
||||
XPos = ox;
|
||||
YPos = oy;
|
||||
ZPos = oz;
|
||||
}
|
||||
|
||||
virtual void Render(View &view,
|
||||
WorldAnnotator &worldAnnotator,
|
||||
RenderSurface &renderSurface)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> V, P;
|
||||
V = view.CreateViewMatrix();
|
||||
P = view.CreateProjectionMatrix();
|
||||
|
||||
vtkm::Vec<vtkm::Float32,4> p4w(XPos,YPos,ZPos,1);
|
||||
vtkm::Vec<vtkm::Float32,4> p4s =
|
||||
vtkm::MatrixMultiply(vtkm::MatrixMultiply(P,V), p4w);
|
||||
|
||||
renderSurface.SetViewToScreenSpace(view,true);
|
||||
|
||||
vtkm::Float32 psx = p4s[0] / p4s[3];
|
||||
vtkm::Float32 psy = p4s[1] / p4s[3];
|
||||
vtkm::Float32 psz = p4s[2] / p4s[3];
|
||||
|
||||
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> T;
|
||||
T = MatrixHelpers::TranslateMatrix(psx,psy,-psz);
|
||||
|
||||
vtkm::Float32 WindowAspect =
|
||||
vtkm::Float32(view.Width) / vtkm::Float32(view.Height);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> SW;
|
||||
SW = MatrixHelpers::ScaleMatrix(1.f/WindowAspect, 1, 1);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> SV;
|
||||
vtkm::MatrixIdentity(SV);
|
||||
//if view type == 2D?
|
||||
{
|
||||
vtkm::Float32 vl, vr, vb, vt;
|
||||
view.GetRealViewport(vl,vr,vb,vt);
|
||||
vtkm::Float32 xs = (vr-vl);
|
||||
vtkm::Float32 ys = (vt-vb);
|
||||
SV = MatrixHelpers::ScaleMatrix(2.f/xs, 2.f/ys, 1);
|
||||
}
|
||||
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> R;
|
||||
R = MatrixHelpers::RotateZMatrix(Angle * 3.14159265f / 180.f);
|
||||
|
||||
vtkm::Vec<vtkm::Float32,4> origin4(0,0,0,1);
|
||||
vtkm::Vec<vtkm::Float32,4> right4(1,0,0,0);
|
||||
vtkm::Vec<vtkm::Float32,4> up4(0,1,0,0);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> M =
|
||||
vtkm::MatrixMultiply(T,
|
||||
vtkm::MatrixMultiply(SW,
|
||||
vtkm::MatrixMultiply(SV,
|
||||
R)));
|
||||
|
||||
vtkm::Vec<vtkm::Float32,4> new_origin4 =
|
||||
vtkm::MatrixMultiply(M, origin4);
|
||||
vtkm::Vec<vtkm::Float32,4> new_right4 =
|
||||
vtkm::MatrixMultiply(M, right4);
|
||||
vtkm::Vec<vtkm::Float32,4> new_up4 =
|
||||
vtkm::MatrixMultiply(M, up4);
|
||||
|
||||
vtkm::Float32 px = new_origin4[0] / new_origin4[3];
|
||||
vtkm::Float32 py = new_origin4[1] / new_origin4[3];
|
||||
vtkm::Float32 pz = new_origin4[2] / new_origin4[3];
|
||||
|
||||
vtkm::Float32 rx = new_right4[0];
|
||||
vtkm::Float32 ry = new_right4[1];
|
||||
vtkm::Float32 rz = new_right4[2];
|
||||
|
||||
vtkm::Float32 ux = new_up4[0];
|
||||
vtkm::Float32 uy = new_up4[1];
|
||||
vtkm::Float32 uz = new_up4[2];
|
||||
|
||||
worldAnnotator.AddText(px,py,pz,
|
||||
rx,ry,rz,
|
||||
ux,uy,uz,
|
||||
Scale,
|
||||
AnchorX, AnchorY,
|
||||
TextColor, Text);
|
||||
|
||||
renderSurface.SetViewToWorldSpace(view,true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
#endif //vtk_m_rendering_TextAnnotation_h
|
147
vtkm/rendering/TextureGL.h
Normal file
147
vtkm/rendering/TextureGL.h
Normal file
@ -0,0 +1,147 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef vtk_m_TextureGL_h
|
||||
#define vtk_m_TextureGL_h
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
|
||||
class TextureGL
|
||||
{
|
||||
public:
|
||||
GLuint ID;
|
||||
int Dimension;
|
||||
bool MIPMap;
|
||||
bool Linear2D;
|
||||
bool LinearMIP;
|
||||
public:
|
||||
TextureGL()
|
||||
{
|
||||
this->ID = 0;
|
||||
this->Dimension = 0;
|
||||
this->MIPMap = false;
|
||||
this->Linear2D = true;
|
||||
this->LinearMIP = true;
|
||||
}
|
||||
void Enable()
|
||||
{
|
||||
if (this->ID == 0)
|
||||
return;
|
||||
|
||||
if (this->Dimension == 1)
|
||||
{
|
||||
// no this->MIPMapping for 1D (at the moment)
|
||||
glBindTexture(GL_TEXTURE_1D, this->ID);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
if (this->Linear2D)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
glEnable(GL_TEXTURE_1D);
|
||||
}
|
||||
else if (this->Dimension == 2)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, this->ID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
if (this->Linear2D)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if (!this->MIPMap)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
else if (this->LinearMIP)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
if (!this->MIPMap)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
else if (this->LinearMIP)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
}
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
void Disable()
|
||||
{
|
||||
if (this->Dimension == 1)
|
||||
glDisable(GL_TEXTURE_1D);
|
||||
else if (this->Dimension == 2)
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
void CreateAlphaFromRGBA(int w, int h, std::vector<unsigned char> &rgba)
|
||||
{
|
||||
this->Dimension = 2;
|
||||
std::vector<unsigned char> alpha(rgba.size()/4);
|
||||
for (unsigned int i=0; i<alpha.size(); i++)
|
||||
{
|
||||
alpha[i] = rgba[i*4+3];
|
||||
}
|
||||
|
||||
if (this->ID == 0)
|
||||
{
|
||||
glGenTextures(1, &this->ID);
|
||||
}
|
||||
|
||||
if (this->Dimension == 1)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_1D, this->ID);
|
||||
}
|
||||
else if (this->Dimension == 2)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, this->ID);
|
||||
//#define HW_MIPMAPS
|
||||
#ifdef HW_MIPMAPS
|
||||
mpimap = true;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_ALPHA,
|
||||
w, h,
|
||||
0,
|
||||
GL_ALPHA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
(void*)(&(alpha[0])));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
||||
#endif //vtk_m_rendering_TextureGL_h
|
@ -108,67 +108,67 @@ public:
|
||||
void operator()(const CellNodeVecType &cellIndices,
|
||||
const vtkm::Id &cellIndex) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Id,4> triangle;
|
||||
if (DIM == 2)
|
||||
{
|
||||
const vtkm::Id triangleOffset = cellIndex * 2;
|
||||
// 0-1-2
|
||||
triangle[1] = cellIndices[0];
|
||||
triangle[2] = cellIndices[1];
|
||||
triangle[3] = cellIndices[2];
|
||||
triangle[0] = cellIndex;
|
||||
OutputIndices.Set(triangleOffset, triangle);
|
||||
// 0-3-2
|
||||
triangle[2] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+1, triangle);
|
||||
}
|
||||
else if (DIM == 3)
|
||||
{
|
||||
const vtkm::Id triangleOffset = cellIndex * 12;
|
||||
// 0-1-2
|
||||
triangle[1] = cellIndices[0];
|
||||
triangle[2] = cellIndices[1];
|
||||
triangle[3] = cellIndices[2];
|
||||
triangle[0] = cellIndex;
|
||||
OutputIndices.Set(triangleOffset, triangle);
|
||||
// 0-3-2
|
||||
triangle[2] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+1, triangle);
|
||||
// 0-3-7
|
||||
triangle[3] = cellIndices[7];
|
||||
OutputIndices.Set(triangleOffset+2, triangle);
|
||||
// 0-4-7
|
||||
triangle[2] = cellIndices[4];
|
||||
OutputIndices.Set(triangleOffset+3, triangle);
|
||||
// 5-4-7
|
||||
triangle[1] = cellIndices[5];
|
||||
OutputIndices.Set(triangleOffset+4, triangle);
|
||||
// 5-6-7
|
||||
triangle[2] = cellIndices[6];
|
||||
OutputIndices.Set(triangleOffset+5, triangle);
|
||||
// 3-6-7
|
||||
triangle[1] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+6, triangle);
|
||||
// 3-6-2
|
||||
triangle[3] = cellIndices[2];
|
||||
OutputIndices.Set(triangleOffset+7, triangle);
|
||||
// 1-6-2
|
||||
triangle[1] = cellIndices[1];
|
||||
OutputIndices.Set(triangleOffset+8, triangle);
|
||||
// 1-6-5
|
||||
triangle[3] = cellIndices[5];
|
||||
OutputIndices.Set(triangleOffset+9, triangle);
|
||||
// 1-4-5
|
||||
triangle[2] = cellIndices[4];
|
||||
OutputIndices.Set(triangleOffset+10, triangle);
|
||||
// 1-4-0
|
||||
triangle[3] = cellIndices[0];
|
||||
OutputIndices.Set(triangleOffset+11, triangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorControlBadType("Unsupported dimension for structured trianglulation");
|
||||
}
|
||||
vtkm::Vec<vtkm::Id,4> triangle;
|
||||
if (DIM == 2)
|
||||
{
|
||||
const vtkm::Id triangleOffset = cellIndex * 2;
|
||||
// 0-1-2
|
||||
triangle[1] = cellIndices[0];
|
||||
triangle[2] = cellIndices[1];
|
||||
triangle[3] = cellIndices[2];
|
||||
triangle[0] = cellIndex;
|
||||
OutputIndices.Set(triangleOffset, triangle);
|
||||
// 0-3-2
|
||||
triangle[2] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+1, triangle);
|
||||
}
|
||||
else if (DIM == 3)
|
||||
{
|
||||
const vtkm::Id triangleOffset = cellIndex * 12;
|
||||
// 0-1-2
|
||||
triangle[1] = cellIndices[0];
|
||||
triangle[2] = cellIndices[1];
|
||||
triangle[3] = cellIndices[2];
|
||||
triangle[0] = cellIndex;
|
||||
OutputIndices.Set(triangleOffset, triangle);
|
||||
// 0-3-2
|
||||
triangle[2] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+1, triangle);
|
||||
// 0-3-7
|
||||
triangle[3] = cellIndices[7];
|
||||
OutputIndices.Set(triangleOffset+2, triangle);
|
||||
// 0-4-7
|
||||
triangle[2] = cellIndices[4];
|
||||
OutputIndices.Set(triangleOffset+3, triangle);
|
||||
// 5-4-7
|
||||
triangle[1] = cellIndices[5];
|
||||
OutputIndices.Set(triangleOffset+4, triangle);
|
||||
// 5-6-7
|
||||
triangle[2] = cellIndices[6];
|
||||
OutputIndices.Set(triangleOffset+5, triangle);
|
||||
// 3-6-7
|
||||
triangle[1] = cellIndices[3];
|
||||
OutputIndices.Set(triangleOffset+6, triangle);
|
||||
// 3-6-2
|
||||
triangle[3] = cellIndices[2];
|
||||
OutputIndices.Set(triangleOffset+7, triangle);
|
||||
// 1-6-2
|
||||
triangle[1] = cellIndices[1];
|
||||
OutputIndices.Set(triangleOffset+8, triangle);
|
||||
// 1-6-5
|
||||
triangle[3] = cellIndices[5];
|
||||
OutputIndices.Set(triangleOffset+9, triangle);
|
||||
// 1-4-5
|
||||
triangle[2] = cellIndices[4];
|
||||
OutputIndices.Set(triangleOffset+10, triangle);
|
||||
// 1-4-0
|
||||
triangle[3] = cellIndices[0];
|
||||
OutputIndices.Set(triangleOffset+11, triangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorControlBadType("Unsupported dimension for structured trianglulation");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@ -540,7 +540,7 @@ public:
|
||||
vtkm::Id shapeTypeAsId = cellSetSingleType.GetCellShape(0);
|
||||
|
||||
if(shapeTypeAsId == vtkm::CellShapeTagTriangle::Id)
|
||||
{
|
||||
{
|
||||
//generate the outputIndices
|
||||
vtkm::Id totalTriangles = cellSetSingleType.GetNumberOfCells();
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> cellIdxs(0,1,totalTriangles);
|
||||
@ -549,16 +549,16 @@ public:
|
||||
vtkm::worklet::DispatcherMapField<Trianglulate>( Trianglulate(outputIndices,
|
||||
cellSetSingleType.GetConnectivityArray( PointTag(), CellTag() ),
|
||||
totalTriangles) )
|
||||
.Invoke(cellSetSingleType.GetShapesArray( PointTag(), CellTag() ),
|
||||
cellSetSingleType.GetIndexOffsetArray( PointTag(), CellTag()),
|
||||
cellIdxs );
|
||||
.Invoke(cellSetSingleType.GetShapesArray( PointTag(), CellTag() ),
|
||||
cellSetSingleType.GetIndexOffsetArray( PointTag(), CellTag()),
|
||||
cellIdxs );
|
||||
|
||||
outputTriangles = totalTriangles;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
throw vtkm::cont::ErrorControlBadType("Unsupported cell type for trianglulation with CellSetSingleType");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/Matrix.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/rendering/MatrixHelpers.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace rendering {
|
||||
@ -38,7 +39,7 @@ class View
|
||||
VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> CreateViewMatrix()
|
||||
{
|
||||
return View::ViewMatrix(this->Position, this->LookAt, this->Up);
|
||||
return MatrixHelpers::ViewMatrix(this->Position, this->LookAt, this->Up);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
@ -69,8 +70,8 @@ class View
|
||||
matrix(3,3) = 0.f;
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> T, Z;
|
||||
T = View::TranslateMatrix(this->XPan, this->YPan, 0);
|
||||
Z = View::ScaleMatrix(this->Zoom, this->Zoom, 1);
|
||||
T = MatrixHelpers::TranslateMatrix(this->XPan, this->YPan, 0);
|
||||
Z = MatrixHelpers::ScaleMatrix(this->Zoom, this->Zoom, 1);
|
||||
matrix = vtkm::MatrixMultiply(Z, vtkm::MatrixMultiply(T, matrix));
|
||||
return matrix;
|
||||
}
|
||||
@ -101,7 +102,7 @@ class View
|
||||
vtkm::Vec<vtkm::Float32,3> position = lookAt;
|
||||
position[2] = 1.f;
|
||||
vtkm::Vec<vtkm::Float32,3> up(0,1,0);
|
||||
return View::ViewMatrix(position, lookAt, up);
|
||||
return MatrixHelpers::ViewMatrix(position, lookAt, up);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
@ -133,144 +134,6 @@ class View
|
||||
vtkm::Float32 XScale;
|
||||
};
|
||||
|
||||
private:
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ViewMatrix(const vtkm::Vec<vtkm::Float32,3> &position,
|
||||
const vtkm::Vec<vtkm::Float32,3> &lookAt,
|
||||
const vtkm::Vec<vtkm::Float32,3> &up)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32,3> viewDir = position-lookAt;
|
||||
vtkm::Vec<vtkm::Float32,3> right = vtkm::Cross(up,viewDir);
|
||||
vtkm::Vec<vtkm::Float32,3> ru = vtkm::Cross(viewDir,right);
|
||||
|
||||
vtkm::Normalize(viewDir);
|
||||
vtkm::Normalize(right);
|
||||
vtkm::Normalize(ru);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
||||
vtkm::MatrixIdentity(matrix);
|
||||
|
||||
matrix(0,0) = right[0];
|
||||
matrix(0,1) = right[1];
|
||||
matrix(0,2) = right[2];
|
||||
matrix(1,0) = ru[0];
|
||||
matrix(1,1) = ru[1];
|
||||
matrix(1,2) = ru[2];
|
||||
matrix(2,0) = viewDir[0];
|
||||
matrix(2,1) = viewDir[1];
|
||||
matrix(2,2) = viewDir[2];
|
||||
|
||||
matrix(0,3) = -vtkm::dot(right,position);
|
||||
matrix(1,3) = -vtkm::dot(ru,position);
|
||||
matrix(2,3) = -vtkm::dot(viewDir,position);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
||||
{
|
||||
return ScaleMatrix(v[0], v[1], v[2]);
|
||||
}
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &s)
|
||||
{
|
||||
return ScaleMatrix(s,s,s);
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &x,
|
||||
const vtkm::Float32 &y,
|
||||
const vtkm::Float32 &z)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> scaleMatrix(0.0f);
|
||||
scaleMatrix(0,0) = x;
|
||||
scaleMatrix(1,1) = y;
|
||||
scaleMatrix(2,2) = z;
|
||||
scaleMatrix(3,3) = 1.0f;
|
||||
return scaleMatrix;
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
||||
{
|
||||
return TranslateMatrix(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
static VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Float32 &x,
|
||||
const vtkm::Float32 &y,
|
||||
const vtkm::Float32 &z)
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32,4,4> translateMatrix;
|
||||
vtkm::MatrixIdentity(translateMatrix);
|
||||
translateMatrix(0,3) = x;
|
||||
translateMatrix(1,3) = y;
|
||||
translateMatrix(2,3) = z;
|
||||
return translateMatrix;
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
vtkm::Matrix<vtkm::Float32,4,4>
|
||||
CreateTrackball(vtkm::Float32 p1x, vtkm::Float32 p1y, vtkm::Float32 p2x, vtkm::Float32 p2y)
|
||||
{
|
||||
const vtkm::Float32 RADIUS = 0.80f; //z value lookAt x = y = 0.0
|
||||
const vtkm::Float32 COMPRESSION = 3.5f; // multipliers for x and y.
|
||||
const vtkm::Float32 AR3 = RADIUS*RADIUS*RADIUS;
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
||||
|
||||
vtkm::MatrixIdentity(matrix);
|
||||
if (p1x==p2x && p1y==p2y) { return matrix; }
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> p1(p1x,p1y, AR3/((p1x*p1x+p1y*p1y)*COMPRESSION+AR3));
|
||||
vtkm::Vec<vtkm::Float32, 3> p2(p2x,p2y, AR3/((p2x*p2x+p2y*p2y)*COMPRESSION+AR3));
|
||||
vtkm::Vec<vtkm::Float32, 3> axis = vtkm::Normal(vtkm::Cross(p2,p1));
|
||||
//std::cout<<"Axis: "<<axis[0]<<" "<<axis[1]<<" "<<axis[2]<<std::endl;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> p2_p1(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]);
|
||||
vtkm::Float32 t = vtkm::Magnitude(p2_p1);
|
||||
t = vtkm::Min(vtkm::Max(t, -1.0f), 1.0f);
|
||||
vtkm::Float32 phi = static_cast<vtkm::Float32>(-2.0f*asin(t/(2.0f*RADIUS)));
|
||||
vtkm::Float32 val = static_cast<vtkm::Float32>(sin(phi/2.0f));
|
||||
axis[0] *= val;
|
||||
axis[1] *= val;
|
||||
axis[2] *= val;
|
||||
|
||||
//quaternion
|
||||
vtkm::Float32 q[4] = {axis[0], axis[1], axis[2], static_cast<vtkm::Float32>(cos(phi/2.0f))};
|
||||
|
||||
// normalize quaternion to unit magnitude
|
||||
t = 1.0f / static_cast<vtkm::Float32>(sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]));
|
||||
q[0] *= t;
|
||||
q[1] *= t;
|
||||
q[2] *= t;
|
||||
q[3] *= t;
|
||||
|
||||
/*
|
||||
std::cout<<"P1: "<<p1[0]<<" "<<p1[1]<<" "<<p1[2]<<std::endl;
|
||||
std::cout<<"P2: "<<p2[0]<<" "<<p2[1]<<" "<<p2[2]<<std::endl;
|
||||
std::cout<<"T= "<<t<<std::endl;
|
||||
std::cout<<"PHI= "<<phi<<std::endl;
|
||||
std::cout<<"QUAT: "<<q[0]<<" "<<q[1]<<" "<<q[2]<<" "<<q[3]<<std::endl;
|
||||
*/
|
||||
|
||||
matrix(0,0) = 1 - 2 * (q[1]*q[1] + q[2]*q[2]);
|
||||
matrix(0,1) = 2 * (q[0]*q[1] + q[2]*q[3]);
|
||||
matrix(0,2) = (2 * (q[2]*q[0] - q[1]*q[3]) );
|
||||
|
||||
matrix(1,0) = 2 * (q[0]*q[1] - q[2]*q[3]);
|
||||
matrix(1,1) = 1 - 2 * (q[2]*q[2] + q[0]*q[0]);
|
||||
matrix(1,2) = (2 * (q[1]*q[2] + q[0]*q[3]) );
|
||||
|
||||
matrix(2,0) = (2 * (q[2]*q[0] + q[1]*q[3]) );
|
||||
matrix(2,1) = (2 * (q[1]*q[2] - q[0]*q[3]) );
|
||||
matrix(2,2) = (1 - 2 * (q[1]*q[1] + q[0]*q[0]) );
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
enum ViewTypeEnum { VIEW_2D, VIEW_3D };
|
||||
ViewTypeEnum ViewType;
|
||||
@ -423,29 +286,13 @@ public:
|
||||
VTKM_CONT_EXPORT
|
||||
void TrackballRotate(vtkm::Float32 x1, vtkm::Float32 y1, vtkm::Float32 x2, vtkm::Float32 y2)
|
||||
{
|
||||
/*
|
||||
std::cout<<std::endl;
|
||||
std::cout<<"*****************************************************************"<<std::endl;
|
||||
std::cout<<x1<<" "<<y1<<" --> "<<x2<<" "<<y2<<std::endl;
|
||||
printVec("position", view3d.Position);
|
||||
printVec("lookAt", view3d.lookAt);
|
||||
printVec("up", view3d.up);
|
||||
std::cout<<"*****************************************************************"<<std::endl;
|
||||
*/
|
||||
vtkm::Matrix<vtkm::Float32,4,4> R1 = CreateTrackball(x1,y1, x2,y2);
|
||||
vtkm::Matrix<vtkm::Float32,4,4> R1 = MatrixHelpers::TrackballMatrix(x1,y1, x2,y2);
|
||||
|
||||
//Translate matrix
|
||||
vtkm::Matrix<vtkm::Float32,4,4> T1 = View::TranslateMatrix(-this->View3d.LookAt);
|
||||
//vtkm::MatrixIdentity(T1);
|
||||
//T1(0,3) = -view3d.lookAt[0];
|
||||
//T1(1,3) = -view3d.lookAt[1];
|
||||
//T1(2,3) = -view3d.lookAt[2];
|
||||
vtkm::Matrix<vtkm::Float32,4,4> T1 = MatrixHelpers::TranslateMatrix(-this->View3d.LookAt);
|
||||
|
||||
//Translate matrix
|
||||
vtkm::Matrix<vtkm::Float32,4,4> T2 = View::TranslateMatrix(this->View3d.LookAt);
|
||||
//T2(0,3) = view3d.lookAt[0];
|
||||
//T2(1,3) = view3d.lookAt[1];
|
||||
//T2(2,3) = view3d.lookAt[2];
|
||||
vtkm::Matrix<vtkm::Float32,4,4> T2 = MatrixHelpers::TranslateMatrix(this->View3d.LookAt);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> V1 = this->CreateViewMatrix();
|
||||
V1(0,3) = 0;
|
||||
@ -463,18 +310,6 @@ public:
|
||||
this->View3d.Position = MultVector(MM, this->View3d.Position);
|
||||
this->View3d.LookAt = MultVector(MM, this->View3d.LookAt);
|
||||
this->View3d.Up = MultVector(MM, this->View3d.Up);
|
||||
|
||||
/*
|
||||
printMtx("T1", T1);
|
||||
printMtx("T2", T2);
|
||||
printMtx("V1", V1);
|
||||
printMtx("V2", V2);
|
||||
printMtx("R1", R1);
|
||||
printMtx("MM", MM);
|
||||
printVec("position", this->View3d.Position);
|
||||
printVec("lookAt", this->View3d.LookAt);
|
||||
printVec("up", this->View3d.Up);
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <vtkm/rendering/AxisAnnotation2D.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/ColorBarAnnotation.h>
|
||||
#include <vtkm/rendering/TextAnnotation.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/SceneRenderer.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
@ -98,16 +99,16 @@ class Window3D : public Window<SceneRendererType, SurfaceType,WorldAnnotatorType
|
||||
{
|
||||
typedef Window<SceneRendererType, SurfaceType,WorldAnnotatorType> Superclass;
|
||||
public:
|
||||
vtkm::rendering::Scene3D Scene;
|
||||
vtkm::rendering::Scene Scene;
|
||||
// 3D-specific annotations
|
||||
vtkm::rendering::BoundingBoxAnnotation BoxAnnotation;
|
||||
vtkm::rendering::AxisAnnotation3D XAxisAnnotation;
|
||||
vtkm::rendering::AxisAnnotation3D YAxisAnnotation;
|
||||
vtkm::rendering::AxisAnnotation3D ZAxisAnnotation;
|
||||
ColorBarAnnotation ColorBarAnnotation;
|
||||
vtkm::rendering::ColorBarAnnotation ColorBarAnnotation;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
Window3D(const vtkm::rendering::Scene3D &scene,
|
||||
Window3D(const vtkm::rendering::Scene &scene,
|
||||
const SceneRendererType &sceneRenderer,
|
||||
const SurfaceType &surface,
|
||||
const vtkm::rendering::View &view,
|
||||
@ -138,7 +139,7 @@ public:
|
||||
{
|
||||
if (this->Scene.Plots.size() > 0)
|
||||
{
|
||||
//this->ColorBarAnnotation.SetAxisColor(eavlColor::white);
|
||||
//this->ColorBarAnnotation.SetAxisColor(vtkm::rendering::Color(1,1,1));
|
||||
this->ColorBarAnnotation.SetRange(this->Scene.Plots[0].ScalarRange, 5);
|
||||
this->ColorBarAnnotation.SetColorTable(this->Scene.Plots[0].ColorTable);
|
||||
this->ColorBarAnnotation.Render(this->View, this->WorldAnnotator, this->Surface);
|
||||
@ -151,7 +152,7 @@ public:
|
||||
vtkm::Bounds bounds = this->Scene.GetSpatialBounds();
|
||||
vtkm::Float64 xmin = bounds.X.Min, xmax = bounds.X.Max;
|
||||
vtkm::Float64 ymin = bounds.Y.Min, ymax = bounds.Y.Max;
|
||||
vtkm::Float64 zmin = bounds.Z.Min, zmax = bounds.Y.Max;
|
||||
vtkm::Float64 zmin = bounds.Z.Min, zmax = bounds.Z.Max;
|
||||
vtkm::Float64 dx = xmax-xmin, dy = ymax-ymin, dz = zmax-zmin;
|
||||
vtkm::Float64 size = vtkm::Sqrt(dx*dx + dy*dy + dz*dz);
|
||||
|
||||
@ -159,8 +160,16 @@ public:
|
||||
this->BoxAnnotation.SetExtents(this->Scene.GetSpatialBounds());
|
||||
this->BoxAnnotation.Render(this->View, this->WorldAnnotator);
|
||||
|
||||
///\todo: set x/y/ztest based on view
|
||||
bool xtest=true, ytest=false, ztest=false;
|
||||
bool xtest = this->View.View3d.LookAt[0] > this->View.View3d.Position[0];
|
||||
bool ytest = this->View.View3d.LookAt[1] > this->View.View3d.Position[1];
|
||||
bool ztest = this->View.View3d.LookAt[2] > this->View.View3d.Position[2];
|
||||
|
||||
const bool outsideedges = true; // if false, do closesttriad
|
||||
if (outsideedges)
|
||||
{
|
||||
xtest = !xtest;
|
||||
//ytest = !ytest;
|
||||
}
|
||||
|
||||
vtkm::Float64 xrel = vtkm::Abs(dx) / size;
|
||||
vtkm::Float64 yrel = vtkm::Abs(dy) / size;
|
||||
@ -178,11 +187,11 @@ public:
|
||||
this->XAxisAnnotation.SetRange(xmin, xmax);
|
||||
this->XAxisAnnotation.SetMajorTickSize(size / 40.f, 0);
|
||||
this->XAxisAnnotation.SetMinorTickSize(size / 80.f, 0);
|
||||
this->XAxisAnnotation.SetLabelFontScale(size / 30.);
|
||||
this->XAxisAnnotation.SetLabelFontOffset(vtkm::Float32(size / 15.f));
|
||||
this->XAxisAnnotation.SetMoreOrLessTickAdjustment(xrel < .3 ? -1 : 0);
|
||||
this->XAxisAnnotation.Render(this->View, this->WorldAnnotator);
|
||||
this->XAxisAnnotation.Render(this->View, this->WorldAnnotator, this->Surface);
|
||||
|
||||
this->YAxisAnnotation.SetAxis(0);
|
||||
this->YAxisAnnotation.SetAxis(1);
|
||||
this->YAxisAnnotation.SetColor(Color(1,1,1));
|
||||
this->YAxisAnnotation.SetTickInvert(xtest,ytest,ztest);
|
||||
this->YAxisAnnotation.SetWorldPosition(xtest ? xmin : xmax,
|
||||
@ -194,11 +203,11 @@ public:
|
||||
this->YAxisAnnotation.SetRange(ymin, ymax);
|
||||
this->YAxisAnnotation.SetMajorTickSize(size / 40.f, 0);
|
||||
this->YAxisAnnotation.SetMinorTickSize(size / 80.f, 0);
|
||||
this->YAxisAnnotation.SetLabelFontScale(size / 30.);
|
||||
this->YAxisAnnotation.SetLabelFontOffset(vtkm::Float32(size / 15.f));
|
||||
this->YAxisAnnotation.SetMoreOrLessTickAdjustment(yrel < .3 ? -1 : 0);
|
||||
this->YAxisAnnotation.Render(this->View, this->WorldAnnotator);
|
||||
this->YAxisAnnotation.Render(this->View, this->WorldAnnotator, this->Surface);
|
||||
|
||||
this->ZAxisAnnotation.SetAxis(0);
|
||||
this->ZAxisAnnotation.SetAxis(2);
|
||||
this->ZAxisAnnotation.SetColor(Color(1,1,1));
|
||||
this->ZAxisAnnotation.SetTickInvert(xtest,ytest,ztest);
|
||||
this->ZAxisAnnotation.SetWorldPosition(xtest ? xmin : xmax,
|
||||
@ -210,9 +219,9 @@ public:
|
||||
this->ZAxisAnnotation.SetRange(zmin, zmax);
|
||||
this->ZAxisAnnotation.SetMajorTickSize(size / 40.f, 0);
|
||||
this->ZAxisAnnotation.SetMinorTickSize(size / 80.f, 0);
|
||||
this->ZAxisAnnotation.SetLabelFontScale(size / 30.);
|
||||
this->ZAxisAnnotation.SetLabelFontOffset(vtkm::Float32(size / 15.f));
|
||||
this->ZAxisAnnotation.SetMoreOrLessTickAdjustment(zrel < .3 ? -1 : 0);
|
||||
this->ZAxisAnnotation.Render(this->View, this->WorldAnnotator);
|
||||
this->ZAxisAnnotation.Render(this->View, this->WorldAnnotator, this->Surface);
|
||||
}
|
||||
};
|
||||
|
||||
@ -223,14 +232,14 @@ class Window2D : public Window<SceneRendererType, SurfaceType,WorldAnnotatorType
|
||||
{
|
||||
typedef Window<SceneRendererType, SurfaceType,WorldAnnotatorType> Superclass;
|
||||
public:
|
||||
vtkm::rendering::Scene2D Scene;
|
||||
vtkm::rendering::Scene Scene;
|
||||
// 2D-specific annotations
|
||||
AxisAnnotation2D HorizontalAxisAnnotation;
|
||||
AxisAnnotation2D VerticalAxisAnnotation;
|
||||
ColorBarAnnotation ColorBarAnnotation;
|
||||
vtkm::rendering::AxisAnnotation2D HorizontalAxisAnnotation;
|
||||
vtkm::rendering::AxisAnnotation2D VerticalAxisAnnotation;
|
||||
vtkm::rendering::ColorBarAnnotation ColorBarAnnotation;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
Window2D(const vtkm::rendering::Scene2D &scene,
|
||||
Window2D(const vtkm::rendering::Scene &scene,
|
||||
const SceneRendererType &sceneRenderer,
|
||||
const SurfaceType &surface,
|
||||
const vtkm::rendering::View &view,
|
||||
@ -274,8 +283,8 @@ public:
|
||||
this->View.View2d.Right);
|
||||
this->HorizontalAxisAnnotation.SetMajorTickSize(0, .05, 1.0);
|
||||
this->HorizontalAxisAnnotation.SetMinorTickSize(0, .02, 1.0);
|
||||
//this->HorizontalAxisAnnotation.SetLabelAlignment(eavlTextAnnotation::HCenter,
|
||||
// eavlTextAnnotation::Top);
|
||||
this->HorizontalAxisAnnotation.SetLabelAlignment(TextAnnotation::HCenter,
|
||||
TextAnnotation::Top);
|
||||
this->HorizontalAxisAnnotation.Render(
|
||||
this->View, this->WorldAnnotator, this->Surface);
|
||||
|
||||
@ -289,16 +298,16 @@ public:
|
||||
this->View.View2d.Top);
|
||||
this->VerticalAxisAnnotation.SetMajorTickSize(.05 / windowaspect, 0, 1.0);
|
||||
this->VerticalAxisAnnotation.SetMinorTickSize(.02 / windowaspect, 0, 1.0);
|
||||
//this->VerticalAxisAnnotation.SetLabelAlignment(eavlTextAnnotation::Right,
|
||||
// eavlTextAnnotation::VCenter);
|
||||
this->VerticalAxisAnnotation.SetLabelAlignment(TextAnnotation::Right,
|
||||
TextAnnotation::VCenter);
|
||||
this->VerticalAxisAnnotation.Render(
|
||||
this->View, this->WorldAnnotator, this->Surface);
|
||||
|
||||
if (this->Scene.Plots.size() > 0)
|
||||
{
|
||||
//this->ColorBarAnnotation.SetAxisColor(eavlColor::white);
|
||||
this->ColorBarAnnotation.SetRange(this->Scene.Plots[0].ScalarRange[0],
|
||||
this->Scene.Plots[0].ScalarRange[1],
|
||||
//this->ColorBarAnnotation.SetAxisColor(vtkm::rendering::Color(1,1,1));
|
||||
this->ColorBarAnnotation.SetRange(this->Scene.Plots[0].ScalarRange.Min,
|
||||
this->Scene.Plots[0].ScalarRange.Max,
|
||||
5);
|
||||
this->ColorBarAnnotation.SetColorTable(this->Scene.Plots[0].ColorTable);
|
||||
this->ColorBarAnnotation.Render(
|
||||
|
@ -37,6 +37,13 @@ public:
|
||||
vtkm::Float32,
|
||||
const vtkm::rendering::Color &,
|
||||
bool=false) {}
|
||||
virtual void AddText(vtkm::Float32, vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32, vtkm::Float32,
|
||||
vtkm::Float32,
|
||||
vtkm::Float32, vtkm::Float32,
|
||||
Color,
|
||||
std::string) {}
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
@ -20,12 +20,17 @@
|
||||
#ifndef vtk_m_rendering_WorldAnnotatorGL_h
|
||||
#define vtk_m_rendering_WorldAnnotatorGL_h
|
||||
|
||||
#include <vtkm/Matrix.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/SceneRenderer.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
#include <vtkm/rendering/WorldAnnotator.h>
|
||||
#include <vtkm/rendering/BitmapFont.h>
|
||||
#include <vtkm/rendering/BitmapFontFactory.h>
|
||||
#include <vtkm/rendering/TextureGL.h>
|
||||
#include <vtkm/rendering/MatrixHelpers.h>
|
||||
|
||||
#include <vtkm/rendering/internal/OpenGLHeaders.h>
|
||||
|
||||
@ -60,6 +65,107 @@ public:
|
||||
glDepthRange(0,1);
|
||||
|
||||
}
|
||||
virtual void AddText(vtkm::Float32 ox, vtkm::Float32 oy, vtkm::Float32 oz,
|
||||
vtkm::Float32 rx, vtkm::Float32 ry, vtkm::Float32 rz,
|
||||
vtkm::Float32 ux, vtkm::Float32 uy, vtkm::Float32 uz,
|
||||
vtkm::Float32 scale,
|
||||
vtkm::Float32 anchorx, vtkm::Float32 anchory,
|
||||
Color color,
|
||||
std::string text)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32,3> o(ox,oy,oz);
|
||||
vtkm::Vec<vtkm::Float32,3> r(rx,ry,rz);
|
||||
vtkm::Vec<vtkm::Float32,3> u(ux,uy,uz);
|
||||
|
||||
vtkm::Vec<vtkm::Float32,3> n = vtkm::Cross(r,u);
|
||||
vtkm::Normalize(n);
|
||||
|
||||
vtkm::Matrix<vtkm::Float32,4,4> m;
|
||||
m = MatrixHelpers::WorldMatrix(o, r, u, n);
|
||||
|
||||
vtkm::Float32 ogl[16];
|
||||
MatrixHelpers::CreateOGLMatrix(m, ogl);
|
||||
glPushMatrix();
|
||||
glMultMatrixf(ogl);
|
||||
glColor3fv(color.Components);
|
||||
RenderText(scale, anchorx, anchory, text);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
private:
|
||||
BitmapFont Font;
|
||||
TextureGL FontTexture;
|
||||
|
||||
void RenderText(vtkm::Float32 scale,
|
||||
vtkm::Float32 anchorx, vtkm::Float32 anchory,
|
||||
std::string text)
|
||||
{
|
||||
if (this->FontTexture.ID == 0)
|
||||
{
|
||||
Font = BitmapFontFactory::CreateLiberation2Sans();
|
||||
std::vector<unsigned char> &rawpngdata = this->Font.GetRawImageData();
|
||||
|
||||
std::vector<unsigned char> rgba;
|
||||
unsigned long width, height;
|
||||
int error = decodePNG(rgba, width, height,
|
||||
&rawpngdata[0], rawpngdata.size());
|
||||
if (error != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->FontTexture.CreateAlphaFromRGBA(int(width),int(height),rgba);
|
||||
}
|
||||
|
||||
|
||||
this->FontTexture.Enable();
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glDisable(GL_LIGHTING);
|
||||
//glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -.5);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
vtkm::Float32 textwidth = this->Font.GetTextWidth(text);
|
||||
|
||||
vtkm::Float32 fx = -(.5f + .5f*anchorx) * textwidth;
|
||||
vtkm::Float32 fy = -(.5f + .5f*anchory);
|
||||
vtkm::Float32 fz = 0;
|
||||
for (unsigned int i=0; i<text.length(); ++i)
|
||||
{
|
||||
char c = text[i];
|
||||
char nextchar = (i < text.length()-1) ? text[i+1] : 0;
|
||||
|
||||
vtkm::Float32 vl,vr,vt,vb;
|
||||
vtkm::Float32 tl,tr,tt,tb;
|
||||
this->Font.GetCharPolygon(c, fx, fy,
|
||||
vl, vr, vt, vb,
|
||||
tl, tr, tt, tb, nextchar);
|
||||
|
||||
glTexCoord2f(tl, 1.f-tt);
|
||||
glVertex3f(scale*vl, scale*vt, fz);
|
||||
|
||||
glTexCoord2f(tl, 1.f-tb);
|
||||
glVertex3f(scale*vl, scale*vb, fz);
|
||||
|
||||
glTexCoord2f(tr, 1.f-tb);
|
||||
glVertex3f(scale*vr, scale*vb, fz);
|
||||
|
||||
glTexCoord2f(tr, 1.f-tt);
|
||||
glVertex3f(scale*vr, scale*vt, fz);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
this->FontTexture.Disable();
|
||||
|
||||
//glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
}
|
||||
};
|
||||
|
||||
}} //namespace vtkm::rendering
|
||||
|
@ -17,6 +17,7 @@
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#include <vtkm/Bounds.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/rendering/Window.h>
|
||||
#include <vtkm/rendering/RenderSurfaceOSMesa.h>
|
||||
@ -33,13 +34,12 @@ void Set3DView(vtkm::rendering::View &view,
|
||||
const vtkm::cont::CoordinateSystem &coords,
|
||||
vtkm::Int32 w, vtkm::Int32 h)
|
||||
{
|
||||
vtkm::Float64 coordsBounds[6]; // Xmin,Xmax,Ymin..
|
||||
coords.GetBounds(coordsBounds,VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
|
||||
vtkm::Bounds coordsBounds = coords.GetBounds(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
|
||||
//set up a default view
|
||||
vtkm::Vec<vtkm::Float32,3> totalExtent;
|
||||
totalExtent[0] = vtkm::Float32(coordsBounds[1] - coordsBounds[0]);
|
||||
totalExtent[1] = vtkm::Float32(coordsBounds[3] - coordsBounds[2]);
|
||||
totalExtent[2] = vtkm::Float32(coordsBounds[5] - coordsBounds[4]);
|
||||
totalExtent[0] = vtkm::Float32(coordsBounds.X.Max - coordsBounds.X.Min);
|
||||
totalExtent[1] = vtkm::Float32(coordsBounds.Y.Max - coordsBounds.Y.Min);
|
||||
totalExtent[2] = vtkm::Float32(coordsBounds.Z.Max - coordsBounds.Z.Min);
|
||||
vtkm::Float32 mag = vtkm::Magnitude(totalExtent);
|
||||
vtkm::Normalize(totalExtent);
|
||||
|
||||
@ -65,22 +65,14 @@ void Set2DView(vtkm::rendering::View &view,
|
||||
const vtkm::cont::CoordinateSystem &coords,
|
||||
vtkm::Int32 w, vtkm::Int32 h)
|
||||
{
|
||||
vtkm::Float64 coordsBounds[6]; // Xmin,Xmax,Ymin..
|
||||
coords.GetBounds(coordsBounds,VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
|
||||
vtkm::Bounds coordsBounds = coords.GetBounds(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
|
||||
//set up a default view
|
||||
// totalExtent does not seem to be used
|
||||
// vtkm::Vec<vtkm::Float32,3> totalExtent;
|
||||
// totalExtent[0] = vtkm::Float32(coordsBounds[1] - coordsBounds[0]);
|
||||
// totalExtent[1] = vtkm::Float32(coordsBounds[3] - coordsBounds[2]);
|
||||
// totalExtent[2] = vtkm::Float32(coordsBounds[5] - coordsBounds[4]);
|
||||
// vtkm::Float32 mag = vtkm::Magnitude(totalExtent);
|
||||
// vtkm::Normalize(totalExtent);
|
||||
|
||||
view = vtkm::rendering::View(vtkm::rendering::View::VIEW_2D);
|
||||
view.View2d.Left = static_cast<vtkm::Float32>(coordsBounds[0]);
|
||||
view.View2d.Right = static_cast<vtkm::Float32>(coordsBounds[1]);
|
||||
view.View2d.Bottom = static_cast<vtkm::Float32>(coordsBounds[2]);
|
||||
view.View2d.Top = static_cast<vtkm::Float32>(coordsBounds[3]);
|
||||
view.View2d.Left = static_cast<vtkm::Float32>(coordsBounds.X.Min);
|
||||
view.View2d.Right = static_cast<vtkm::Float32>(coordsBounds.X.Max);
|
||||
view.View2d.Bottom = static_cast<vtkm::Float32>(coordsBounds.Y.Min);
|
||||
view.View2d.Top = static_cast<vtkm::Float32>(coordsBounds.Y.Max);
|
||||
view.NearPlane = 1.f;
|
||||
view.FarPlane = 100.f;
|
||||
view.Width = w;
|
||||
@ -112,7 +104,7 @@ void Render3D(const vtkm::cont::DataSet &ds,
|
||||
vtkm::rendering::View view;
|
||||
Set3DView(view, coords, W, H);
|
||||
|
||||
vtkm::rendering::Scene3D scene;
|
||||
vtkm::rendering::Scene scene;
|
||||
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
vtkm::rendering::RenderSurfaceOSMesa surface(W,H,bg);
|
||||
|
||||
@ -144,7 +136,7 @@ void Render2D(const vtkm::cont::DataSet &ds,
|
||||
vtkm::rendering::View view;
|
||||
Set2DView(view, coords, W, H);
|
||||
|
||||
vtkm::rendering::Scene2D scene;
|
||||
vtkm::rendering::Scene scene;
|
||||
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
vtkm::rendering::RenderSurfaceOSMesa surface(W,H,bg);
|
||||
|
||||
|
@ -72,7 +72,7 @@ void Render(const vtkm::cont::DataSet &ds,
|
||||
vtkm::rendering::View view;
|
||||
Set3DView(view, coords, W, H);
|
||||
|
||||
vtkm::rendering::Scene3D scene;
|
||||
vtkm::rendering::Scene scene;
|
||||
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
vtkm::rendering::RenderSurfaceRayTracer surface(W,H,bg);
|
||||
scene.Plots.push_back(vtkm::rendering::Plot(ds.GetCellSet(),
|
||||
|
@ -77,7 +77,7 @@ void Render(const vtkm::cont::DataSet &ds,
|
||||
colorTable.AddAlphaControlPoint(0.0f, .01f);
|
||||
colorTable.AddAlphaControlPoint(1.0f, .01f);
|
||||
|
||||
vtkm::rendering::Scene3D scene;
|
||||
vtkm::rendering::Scene scene;
|
||||
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
vtkm::rendering::RenderSurfaceRayTracer surface(W,H,bg);
|
||||
scene.Plots.push_back(vtkm::rendering::Plot(ds.GetCellSet(),
|
||||
|
Loading…
Reference in New Issue
Block a user