|
|
93cbac |
/*
|
|
|
93cbac |
......... 2015 Ivan Mahonin
|
|
|
93cbac |
|
|
|
93cbac |
This program is free software: you can redistribute it and/or modify
|
|
|
93cbac |
it under the terms of the GNU General Public License as published by
|
|
|
93cbac |
the Free Software Foundation, either version 3 of the License, or
|
|
|
93cbac |
(at your option) any later version.
|
|
|
93cbac |
|
|
|
93cbac |
This program is distributed in the hope that it will be useful,
|
|
|
93cbac |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
93cbac |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
93cbac |
GNU General Public License for more details.
|
|
|
93cbac |
|
|
|
93cbac |
You should have received a copy of the GNU General Public License
|
|
|
93cbac |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
93cbac |
*/
|
|
|
93cbac |
|
|
|
93cbac |
#include <fstream></fstream>
|
|
|
93cbac |
#include <iostream></iostream>
|
|
|
c7fa36 |
#include <iomanip></iomanip>
|
|
|
93cbac |
|
|
|
93cbac |
#include "test.h"
|
|
|
93cbac |
#include "contourbuilder.h"
|
|
|
8cd87e |
#include "triangulator.h"
|
|
|
49e693 |
#include "measure.h"
|
|
|
49e693 |
#include "utils.h"
|
|
|
d989ab |
#include "clrender.h"
|
|
|
93cbac |
|
|
|
93cbac |
|
|
|
93cbac |
using namespace std;
|
|
|
93cbac |
|
|
|
93cbac |
|
|
|
d9c2d9 |
void Test::draw_contour(
|
|
|
d9c2d9 |
Environment &e,
|
|
|
d9c2d9 |
int start,
|
|
|
d9c2d9 |
int count,
|
|
|
d9c2d9 |
const rect<int> bounds,</int>
|
|
|
d9c2d9 |
bool even_odd,
|
|
|
d9c2d9 |
bool invert,
|
|
|
d9c2d9 |
const Color &color
|
|
|
d9c2d9 |
) {
|
|
|
d9c2d9 |
glScissor(bounds.p0.x, bounds.p0.y, bounds.p1.x-bounds.p0.x, bounds.p1.y-bounds.p0.y);
|
|
|
d9c2d9 |
glEnable(GL_SCISSOR_TEST);
|
|
|
49e693 |
glEnable(GL_STENCIL_TEST);
|
|
|
93cbac |
|
|
|
49e693 |
// render mask
|
|
|
a04770 |
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
49e693 |
glClear(GL_STENCIL_BUFFER_BIT);
|
|
|
49e693 |
glStencilFunc(GL_ALWAYS, 0, 0);
|
|
|
49e693 |
if (even_odd) {
|
|
|
49e693 |
glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);
|
|
|
93cbac |
} else {
|
|
|
49e693 |
glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);
|
|
|
49e693 |
glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP);
|
|
|
49e693 |
}
|
|
|
49e693 |
e.shaders.simple();
|
|
|
d9c2d9 |
glDrawArrays(GL_TRIANGLE_FAN, start, count);
|
|
|
a04770 |
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
49e693 |
|
|
|
49e693 |
// fill mask
|
|
|
49e693 |
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
|
|
49e693 |
if (!even_odd && !invert)
|
|
|
49e693 |
glStencilFunc(GL_NOTEQUAL, 0, -1);
|
|
|
49e693 |
if (!even_odd && invert)
|
|
|
49e693 |
glStencilFunc(GL_EQUAL, 0, -1);
|
|
|
49e693 |
if ( even_odd && !invert)
|
|
|
49e693 |
glStencilFunc(GL_EQUAL, 1, 1);
|
|
|
49e693 |
if ( even_odd && invert)
|
|
|
49e693 |
glStencilFunc(GL_EQUAL, 0, 1);
|
|
|
49e693 |
|
|
|
49e693 |
e.shaders.color(color);
|
|
|
49e693 |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
49e693 |
|
|
|
49e693 |
glDisable(GL_STENCIL_TEST);
|
|
|
d9c2d9 |
glDisable(GL_SCISSOR_TEST);
|
|
|
7c6b57 |
}
|
|
|
7c6b57 |
|
|
|
f29469 |
void Test::load(Data &contours, const std::string &filename) {
|
|
|
9edf2e |
vector<vector> groups;</vector>
|
|
|
9edf2e |
groups.push_back(Vector());
|
|
|
9edf2e |
|
|
|
f29469 |
ifstream f(("data/" + filename).c_str());
|
|
|
9edf2e |
int vertices_count = 0;
|
|
|
9edf2e |
while(f) {
|
|
|
9edf2e |
string s;
|
|
|
9edf2e |
f >> s;
|
|
|
9edf2e |
if (s == "g") {
|
|
|
9edf2e |
Vector t;
|
|
|
9edf2e |
f >> t.x >> t.y;
|
|
|
9edf2e |
groups.push_back(groups.back() + t);
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s == "end") {
|
|
|
9edf2e |
groups.pop_back();
|
|
|
9edf2e |
if ((int)groups.size() == 1)
|
|
|
9edf2e |
break;
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s == "path") {
|
|
|
9edf2e |
contours.push_back(ContourInfo());
|
|
|
9edf2e |
ContourInfo &ci = contours.back();
|
|
|
9edf2e |
f >> ci.invert
|
|
|
9edf2e |
>> ci.antialias
|
|
|
9edf2e |
>> ci.evenodd
|
|
|
9edf2e |
>> ci.color.r
|
|
|
9edf2e |
>> ci.color.g
|
|
|
9edf2e |
>> ci.color.b
|
|
|
9edf2e |
>> ci.color.a;
|
|
|
9edf2e |
bool closed = true;
|
|
|
9edf2e |
while(true) {
|
|
|
9edf2e |
f >> s;
|
|
|
9edf2e |
Vector p1;
|
|
|
9edf2e |
if (s == "M") {
|
|
|
9edf2e |
f >> p1.x >> p1.y;
|
|
|
9edf2e |
ci.contour.move_to(p1 + groups.back());
|
|
|
9edf2e |
closed = false;
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s == "L") {
|
|
|
9edf2e |
f >> p1.x >> p1.y;
|
|
|
9edf2e |
if (closed) {
|
|
|
9edf2e |
ci.contour.move_to(p1 + groups.back());
|
|
|
9edf2e |
closed = false;
|
|
|
9edf2e |
}
|
|
|
9edf2e |
ci.contour.line_to(p1 + groups.back());
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s == "Z") {
|
|
|
9edf2e |
ci.contour.close();
|
|
|
9edf2e |
closed = true;
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s == "end") {
|
|
|
9edf2e |
break;
|
|
|
9edf2e |
} else {
|
|
|
9edf2e |
cout << "bug " << s << endl;
|
|
|
9edf2e |
if (!f) break;
|
|
|
9edf2e |
}
|
|
|
9edf2e |
}
|
|
|
9edf2e |
if (!closed)
|
|
|
9edf2e |
ci.contour.close();
|
|
|
9edf2e |
if (ci.color.a < 0.9999)
|
|
|
9edf2e |
contours.pop_back();
|
|
|
9edf2e |
else
|
|
|
9edf2e |
vertices_count += ci.contour.get_chunks().size();
|
|
|
9edf2e |
} else
|
|
|
9edf2e |
if (s != "") {
|
|
|
9edf2e |
cout << "bug " << s << endl;
|
|
|
9edf2e |
}
|
|
|
9edf2e |
}
|
|
|
9edf2e |
if ((int)groups.size() != 1)
|
|
|
9edf2e |
cout << "bug groups " << groups.size() << endl;
|
|
|
9edf2e |
|
|
|
9edf2e |
cout << contours.size() << " contours" << endl;
|
|
|
9edf2e |
cout << vertices_count << " vertices" << endl;
|
|
|
9edf2e |
}
|
|
|
9edf2e |
|
|
|
f29469 |
void Test::transform(Data &data, const Rect &from, const Rect &to) {
|
|
|
f29469 |
for(Data::iterator i = data.begin(); i != data.end(); ++i)
|
|
|
f29469 |
i->contour.transform(from, to);
|
|
|
f29469 |
}
|
|
|
9edf2e |
|
|
|
f29469 |
void Test::downgrade(Data &from, Data &to) {
|
|
|
f29469 |
to = from;
|
|
|
f29469 |
Measure t("downgrade");
|
|
|
f29469 |
for(Data::iterator i = from.begin(); i != from.end(); ++i)
|
|
|
d9c2d9 |
i->contour.downgrade(to[i - from.begin()].contour, Vector(1.f, 1.f));
|
|
|
f29469 |
}
|
|
|
93cbac |
|
|
|
f29469 |
void Test::split(Data &from, Data &to) {
|
|
|
f29469 |
to = from;
|
|
|
f29469 |
Measure t("split");
|
|
|
f29469 |
for(Data::iterator i = from.begin(); i != from.end(); ++i)
|
|
|
f29469 |
i->contour.split(to[i - from.begin()].contour, Rect(0.f, 0.f, 100000.f, 100000.f), Vector(1.f, 1.f));
|
|
|
f29469 |
}
|
|
|
93cbac |
|
|
|
f29469 |
void Test::test_gl_stencil(Environment &e, Data &data) {
|
|
|
d9c2d9 |
Vector size = Utils::get_frame_size();
|
|
|
7c6b57 |
GLuint buffer_id = 0;
|
|
|
7c6b57 |
GLuint array_id = 0;
|
|
|
a04770 |
vector<vec2f> vertices;</vec2f>
|
|
|
f29469 |
vector<int> starts(data.size());</int>
|
|
|
f29469 |
vector<int> counts(data.size());</int>
|
|
|
d9c2d9 |
vector< rect<int> > bounds(data.size());</int>
|
|
|
f29469 |
|
|
|
f29469 |
vertices.push_back(vec2f(-1.f, -1.f));
|
|
|
f29469 |
vertices.push_back(vec2f( 1.f, -1.f));
|
|
|
f29469 |
vertices.push_back(vec2f(-1.f, 1.f));
|
|
|
f29469 |
vertices.push_back(vec2f( 1.f, 1.f));
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i) {
|
|
|
f29469 |
starts[i] = (int)vertices.size();
|
|
|
f29469 |
const Contour::ChunkList &chunks = data[i].contour.get_chunks();
|
|
|
d9c2d9 |
Rect r(chunks.front().p1, chunks.front().p1);
|
|
|
f29469 |
for(Contour::ChunkList::const_iterator j = chunks.begin(); j != chunks.end(); ++j) {
|
|
|
d9c2d9 |
vertices.push_back(vec2f(j->p1));
|
|
|
d9c2d9 |
r = r.expand(j->p1);
|
|
|
8de121 |
}
|
|
|
f29469 |
counts[i] = (int)vertices.size() - starts[i];
|
|
|
d9c2d9 |
bounds[i].p0.x = (int)floor((r.p0.x + 1.0)*0.5*size.x);
|
|
|
d9c2d9 |
bounds[i].p0.y = (int)floor((r.p0.y + 1.0)*0.5*size.y);
|
|
|
d9c2d9 |
bounds[i].p1.x = (int)ceil ((r.p1.x + 1.0)*0.5*size.x) + 1;
|
|
|
d9c2d9 |
bounds[i].p1.y = (int)ceil ((r.p1.y + 1.0)*0.5*size.y) + 1;
|
|
|
8de121 |
}
|
|
|
8de121 |
|
|
|
f29469 |
glGenBuffers(1, &buffer_id);
|
|
|
f29469 |
glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
|
|
|
f29469 |
glBufferData( GL_ARRAY_BUFFER,
|
|
|
f29469 |
vertices.size()*sizeof(vec2f),
|
|
|
f29469 |
&vertices.front(),
|
|
|
f29469 |
GL_DYNAMIC_DRAW );
|
|
|
8de121 |
|
|
|
f29469 |
glGenVertexArrays(1, &array_id);
|
|
|
f29469 |
glBindVertexArray(array_id);
|
|
|
93cbac |
|
|
|
f29469 |
glEnableVertexAttribArray(0);
|
|
|
f29469 |
glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
|
|
|
6e407d |
|
|
|
f29469 |
e.shaders.color(Color(0.f, 0.f, 1.f, 1.f));
|
|
|
f29469 |
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
|
|
|
f29469 |
glFinish();
|
|
|
f29469 |
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
f29469 |
glFinish();
|
|
|
93cbac |
|
|
|
93cbac |
{
|
|
|
f29469 |
Measure t("render");
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i) {
|
|
|
f29469 |
draw_contour(
|
|
|
f29469 |
e,
|
|
|
f29469 |
starts[i],
|
|
|
f29469 |
counts[i],
|
|
|
d9c2d9 |
bounds[i],
|
|
|
f29469 |
data[i].invert,
|
|
|
f29469 |
data[i].evenodd,
|
|
|
f29469 |
data[i].color );
|
|
|
f29469 |
}
|
|
|
d9c2d9 |
glFinish();
|
|
|
93cbac |
}
|
|
|
93cbac |
}
|
|
|
93cbac |
|
|
|
f29469 |
void Test::test_sw(Environment &e, Data &data, Surface &surface) {
|
|
|
f29469 |
vector<polyspan> polyspans(data.size());</polyspan>
|
|
|
93cbac |
{
|
|
|
f29469 |
Measure t("polyspans");
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i) {
|
|
|
f29469 |
polyspans[i].init(0, 0, surface.width, surface.height);
|
|
|
f29469 |
data[i].contour.to_polyspan(polyspans[i]);
|
|
|
f29469 |
polyspans[i].sort_marks();
|
|
|
f29469 |
}
|
|
|
93cbac |
}
|
|
|
93cbac |
|
|
|
93cbac |
{
|
|
|
f29469 |
Measure t("render");
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i)
|
|
|
f29469 |
SwRender::polyspan(surface, polyspans[i], data[i].color, data[i].evenodd, data[i].invert);
|
|
|
93cbac |
}
|
|
|
93cbac |
}
|
|
|
93cbac |
|
|
|
f29469 |
void Test::test_cl(Environment &e, Data &data, Surface &surface) {
|
|
|
f29469 |
vector<vec2f> paths;</vec2f>
|
|
|
f29469 |
vector<int> starts(data.size());</int>
|
|
|
f29469 |
vector<int> counts(data.size());</int>
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i) {
|
|
|
f29469 |
starts[i] = paths.size();
|
|
|
f29469 |
for(Contour::ChunkList::const_iterator j = data[i].contour.get_chunks().begin(); j != data[i].contour.get_chunks().end(); ++j)
|
|
|
f29469 |
paths.push_back(vec2f(j->p1));
|
|
|
f29469 |
paths.push_back(paths[starts[i]]);
|
|
|
f29469 |
counts[i] = paths.size() - starts[i];
|
|
|
9edf2e |
}
|
|
|
9edf2e |
|
|
|
f29469 |
ClRender clr(e.cl);
|
|
|
f29469 |
clr.send_surface(&surface);
|
|
|
f29469 |
clr.send_path(&paths.front(), paths.size());
|
|
|
d989ab |
|
|
|
d989ab |
{
|
|
|
f29469 |
Measure t("render");
|
|
|
f29469 |
for(int i = 0; i < (int)data.size(); ++i)
|
|
|
f29469 |
clr.path(starts[i], counts[i], data[i].color, data[i].invert, data[i].evenodd);
|
|
|
f29469 |
clr.wait();
|
|
|
c7fa36 |
}
|
|
|
c7fa36 |
|
|
|
f29469 |
clr.receive_surface();
|
|
|
9edf2e |
}
|