|
|
3c2463 |
/* === S Y N F I G ========================================================= */
|
|
|
248685 |
/*! \file synfig/rendering/primitive/mesh.cpp
|
|
|
3c2463 |
** \brief Mesh
|
|
|
3c2463 |
**
|
|
|
3c2463 |
** $Id$
|
|
|
3c2463 |
**
|
|
|
3c2463 |
** \legal
|
|
|
3c2463 |
** ......... ... 2015 Ivan Mahonin
|
|
|
3c2463 |
**
|
|
|
3c2463 |
** This package is free software; you can redistribute it and/or
|
|
|
3c2463 |
** modify it under the terms of the GNU General Public License as
|
|
|
3c2463 |
** published by the Free Software Foundation; either version 2 of
|
|
|
3c2463 |
** the License, or (at your option) any later version.
|
|
|
3c2463 |
**
|
|
|
3c2463 |
** This package is distributed in the hope that it will be useful,
|
|
|
3c2463 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
3c2463 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
3c2463 |
** General Public License for more details.
|
|
|
3c2463 |
** \endlegal
|
|
|
3c2463 |
*/
|
|
|
3c2463 |
/* ========================================================================= */
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === H E A D E R S ======================================================= */
|
|
|
3c2463 |
|
|
|
3c2463 |
#ifdef USING_PCH
|
|
|
3c2463 |
# include "pch.h"
|
|
|
3c2463 |
#else
|
|
|
3c2463 |
#ifdef HAVE_CONFIG_H
|
|
|
3c2463 |
# include <config.h></config.h>
|
|
|
3c2463 |
#endif
|
|
|
3c2463 |
|
|
|
3c2463 |
#include "mesh.h"
|
|
|
3c2463 |
|
|
|
3c2463 |
#endif
|
|
|
3c2463 |
|
|
|
3c2463 |
using namespace synfig;
|
|
|
248685 |
using namespace rendering;
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === M A C R O S ========================================================= */
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === G L O B A L S ======================================================= */
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === P R O C E D U R E S ================================================= */
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === M E T H O D S ======================================================= */
|
|
|
3c2463 |
|
|
|
8c834e |
Mesh::Mesh():
|
|
|
8c834e |
resolution_transfrom_calculated(false) { }
|
|
|
8c834e |
|
|
|
8c834e |
void
|
|
|
8c834e |
Mesh::assign(const Mesh &other) {
|
|
|
8c834e |
vertices = other.vertices;
|
|
|
8c834e |
triangles = other.triangles;
|
|
|
8c834e |
|
|
|
8c834e |
// other mesh is constant, so we need to lock mutexes for read the relolution data
|
|
|
8c834e |
// see comment for calculate_resolution_transfrom() declaration
|
|
|
8c834e |
{
|
|
Rodolfo Ribeiro Gomes |
d18249 |
std::lock_guard<std::mutex> lock(other.resolution_transfrom_read_mutex);</std::mutex>
|
|
|
8c834e |
resolution_transfrom_calculated = other.resolution_transfrom_calculated;
|
|
|
8c834e |
target_rectangle = other.target_rectangle;
|
|
|
8c834e |
source_rectangle = other.source_rectangle;
|
|
|
8c834e |
resolution_transfrom = other.resolution_transfrom;
|
|
|
8c834e |
}
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
248685 |
void
|
|
|
8c834e |
Mesh::clear()
|
|
|
e93eb5 |
{
|
|
|
8c834e |
vertices.clear();
|
|
|
8c834e |
triangles.clear();
|
|
|
8c834e |
reset_resolution_transfrom();
|
|
|
8c834e |
}
|
|
|
9af60c |
|
|
|
8c834e |
void
|
|
|
8c834e |
Mesh::reset_resolution_transfrom()
|
|
|
8c834e |
{ resolution_transfrom_calculated = false; }
|
|
|
8c834e |
|
|
|
2c1524 |
Rect
|
|
|
2c1524 |
Mesh::calc_target_rectangle() const
|
|
|
2c1524 |
{
|
|
|
2c1524 |
if (vertices.empty()) return Rect::zero();
|
|
|
2c1524 |
Rect target_rectangle = Rect(vertices[0].position);
|
|
|
2c1524 |
for(std::vector<vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)</vertex>
|
|
|
2c1524 |
target_rectangle.expand(i->position);
|
|
|
2c1524 |
return target_rectangle;
|
|
|
2c1524 |
}
|
|
|
2c1524 |
|
|
|
2c1524 |
Rect
|
|
|
2c1524 |
Mesh::calc_target_rectangle(const Matrix &transform_matrix) const
|
|
|
2c1524 |
{
|
|
|
2c1524 |
if (vertices.empty()) return Rect::zero();
|
|
|
2c1524 |
Rect target_rectangle = Rect(transform_matrix.get_transformed(vertices[0].position));
|
|
|
2c1524 |
for(std::vector<vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)</vertex>
|
|
|
2c1524 |
target_rectangle.expand( transform_matrix.get_transformed(i->position) );
|
|
|
2c1524 |
return target_rectangle;
|
|
|
2c1524 |
}
|
|
|
2c1524 |
|
|
|
2c1524 |
|
|
|
2c1524 |
Rect
|
|
|
2c1524 |
Mesh::calc_source_rectangle() const
|
|
|
2c1524 |
{
|
|
|
2c1524 |
if (vertices.empty()) return Rect::zero();
|
|
|
2c1524 |
Rect source_rectangle = Rect(vertices[0].position);
|
|
|
2c1524 |
for(std::vector<vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)</vertex>
|
|
|
2c1524 |
source_rectangle.expand(i->position);
|
|
|
2c1524 |
return source_rectangle;
|
|
|
2c1524 |
}
|
|
|
2c1524 |
Rect
|
|
|
2c1524 |
Mesh::calc_source_rectangle(const Matrix &transform_matrix) const
|
|
|
2c1524 |
{
|
|
|
2c1524 |
if (vertices.empty()) return Rect::zero();
|
|
|
2c1524 |
Rect source_rectangle = Rect(transform_matrix.get_transformed(vertices[0].tex_coords));
|
|
|
2c1524 |
for(std::vector<vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)</vertex>
|
|
|
2c1524 |
source_rectangle.expand( transform_matrix.get_transformed(i->tex_coords) );
|
|
|
2c1524 |
return source_rectangle;
|
|
|
2c1524 |
}
|
|
|
2c1524 |
|
|
|
8c834e |
void
|
|
|
8c834e |
Mesh::calculate_resolution_transfrom_no_lock(bool force) const
|
|
|
8c834e |
{
|
|
|
8c834e |
if (resolution_transfrom_calculated && !force)
|
|
|
8c834e |
return;
|
|
|
e48a26 |
// TODO:
|
|
|
9af60c |
resolution_transfrom.set_identity();
|
|
|
2c1524 |
target_rectangle = calc_target_rectangle();
|
|
|
2c1524 |
source_rectangle = calc_source_rectangle();
|
|
|
8c834e |
resolution_transfrom_calculated = true;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
void
|
|
|
8c834e |
Mesh::calculate_resolution_transfrom(bool force) const
|
|
|
8c834e |
{
|
|
Rodolfo Ribeiro Gomes |
d18249 |
std::lock_guard<std::mutex> lock(resolution_transfrom_read_mutex);</std::mutex>
|
|
|
8c834e |
calculate_resolution_transfrom_no_lock(force);
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
Matrix2
|
|
|
8c834e |
Mesh::get_resolution_transfrom() const
|
|
|
8c834e |
{
|
|
Rodolfo Ribeiro Gomes |
d18249 |
std::lock_guard<std::mutex> lock(resolution_transfrom_read_mutex);</std::mutex>
|
|
|
8c834e |
calculate_resolution_transfrom_no_lock();
|
|
|
8c834e |
return resolution_transfrom;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
Rect
|
|
|
8c834e |
Mesh::get_target_rectangle() const
|
|
|
8c834e |
{
|
|
Rodolfo Ribeiro Gomes |
d18249 |
std::lock_guard<std::mutex> lock(resolution_transfrom_read_mutex);</std::mutex>
|
|
|
8c834e |
calculate_resolution_transfrom_no_lock();
|
|
|
8c834e |
return target_rectangle;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
Rect
|
|
|
8c834e |
Mesh::get_source_rectangle() const
|
|
|
8c834e |
{
|
|
Rodolfo Ribeiro Gomes |
d18249 |
std::lock_guard<std::mutex> lock(resolution_transfrom_read_mutex);</std::mutex>
|
|
|
8c834e |
calculate_resolution_transfrom_no_lock();
|
|
|
8c834e |
return source_rectangle;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
bool
|
|
|
8c834e |
Mesh::transform_coord_world_to_texture(
|
|
|
8c834e |
const Vector &src,
|
|
|
8c834e |
Vector &dest,
|
|
|
8c834e |
const Vector &p0,
|
|
|
8c834e |
const Vector &t0,
|
|
|
8c834e |
const Vector &p1,
|
|
|
8c834e |
const Vector &t1,
|
|
|
8c834e |
const Vector &p2,
|
|
|
8c834e |
const Vector &t2 )
|
|
|
8c834e |
{
|
|
|
8c834e |
// is point inside triangle?
|
|
|
8c834e |
Matrix matrix_of_base_triangle(
|
|
|
8c834e |
p1[0]-p0[0], p1[1]-p0[1], 0.0,
|
|
|
8c834e |
p2[0]-p0[0], p2[1]-p0[1], 0.0,
|
|
|
8c834e |
p0[0], p0[1], 1.0 );
|
|
|
8c834e |
if (!matrix_of_base_triangle.is_invertible()) return false;
|
|
|
8c834e |
|
|
|
8c834e |
matrix_of_base_triangle.invert();
|
|
|
8c834e |
Vector v = matrix_of_base_triangle.get_transformed(src);
|
|
|
8c834e |
if (v[0] < 0.0 || v[0] > 1.0
|
|
|
8c834e |
|| v[1] < 0.0 || v[1] > 1.0
|
|
|
8c834e |
|| v[0] + v[1] > 1.0) return false;
|
|
|
8c834e |
|
|
|
8c834e |
// get coords at texture
|
|
|
8c834e |
Matrix matrix_of_texture_triangle(
|
|
|
8c834e |
t1[0]-t0[0], t1[1]-t0[1], 0.0,
|
|
|
8c834e |
t2[0]-t0[0], t2[1]-t0[1], 0.0,
|
|
|
8c834e |
t0[0], t0[1], 1.0 );
|
|
|
8c834e |
dest = matrix_of_texture_triangle.get_transformed(v);
|
|
|
8c834e |
return true;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
bool
|
|
|
8c834e |
Mesh::transform_coord_world_to_texture(const Vector &src, Vector &dest) const
|
|
|
8c834e |
{
|
|
|
8c834e |
// process triangles backward
|
|
|
8c834e |
for(TriangleList::const_reverse_iterator ri = triangles.rbegin(); ri != triangles.rend(); ++ri)
|
|
|
8c834e |
if (transform_coord_world_to_texture(
|
|
|
8c834e |
src,
|
|
|
8c834e |
dest,
|
|
|
8c834e |
vertices[ri->vertices[0]].position,
|
|
|
8c834e |
vertices[ri->vertices[0]].tex_coords,
|
|
|
8c834e |
vertices[ri->vertices[1]].position,
|
|
|
8c834e |
vertices[ri->vertices[1]].tex_coords,
|
|
|
8c834e |
vertices[ri->vertices[2]].position,
|
|
|
8c834e |
vertices[ri->vertices[2]].tex_coords
|
|
|
8c834e |
))
|
|
|
8c834e |
return true;
|
|
|
8c834e |
return false;
|
|
|
8c834e |
}
|
|
|
8c834e |
|
|
|
8c834e |
bool
|
|
|
8c834e |
Mesh::transform_coord_texture_to_world(const Vector &src, Vector &dest) const
|
|
|
8c834e |
{
|
|
|
8c834e |
// process triangles backward
|
|
|
8c834e |
for(TriangleList::const_reverse_iterator ri = triangles.rbegin(); ri != triangles.rend(); ++ri)
|
|
|
8c834e |
if (transform_coord_texture_to_world(
|
|
|
8c834e |
src,
|
|
|
8c834e |
dest,
|
|
|
8c834e |
vertices[ri->vertices[0]].position,
|
|
|
8c834e |
vertices[ri->vertices[0]].tex_coords,
|
|
|
8c834e |
vertices[ri->vertices[1]].position,
|
|
|
8c834e |
vertices[ri->vertices[1]].tex_coords,
|
|
|
8c834e |
vertices[ri->vertices[2]].position,
|
|
|
8c834e |
vertices[ri->vertices[2]].tex_coords
|
|
|
8c834e |
))
|
|
|
8c834e |
return true;
|
|
|
8c834e |
return false;
|
|
|
3c2463 |
}
|
|
|
3c2463 |
|
|
|
3c2463 |
/* === E N T R Y P O I N T ================================================= */
|