summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp25
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/resources/mesh.cpp209
-rw-r--r--scene/resources/mesh.h7
-rw-r--r--scene/resources/surface_tool.cpp114
-rw-r--r--scene/resources/surface_tool.h3
6 files changed, 355 insertions, 5 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 768d5185d7..82123d12ac 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -623,6 +623,29 @@ void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vect
VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
+
+void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ Vector<Color> colors;
+ colors.push_back(p_color);
+ VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
+}
+
+void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
+}
+
void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
if (!drawing) {
@@ -979,6 +1002,8 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index ccbb528d6f..2384c0f370 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -268,6 +268,8 @@ public:
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>());
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 0a886c25b1..842af20ac8 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "mesh.h"
+#include "pair.h"
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "surface_tool.h"
-
void Mesh::_clear_triangle_mesh() const {
triangle_mesh.unref();
@@ -413,8 +413,21 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
return newmesh;
}
+void Mesh::set_lightmap_size_hint(const Vector2 &p_size) {
+ lightmap_size_hint = p_size;
+}
+
+Size2 Mesh::get_lightmap_size_hint() const {
+ return lightmap_size_hint;
+}
+
void Mesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint);
+ ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint);
+
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint");
+
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
@@ -1035,6 +1048,200 @@ void ArrayMesh::regen_normalmaps() {
}
}
+//dirty hack
+bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = NULL;
+
+struct ArrayMeshLightmapSurface {
+
+ Ref<Material> material;
+ Vector<SurfaceTool::Vertex> vertices;
+ Mesh::PrimitiveType primitive;
+ uint32_t format;
+};
+
+Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
+
+ ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
+ ERR_EXPLAIN("Can't unwrap mesh with blend shapes");
+ ERR_FAIL_COND_V(blend_shapes.size() != 0, ERR_UNAVAILABLE);
+
+ Vector<float> vertices;
+ Vector<float> normals;
+ Vector<int> indices;
+ Vector<int> face_materials;
+ Vector<float> uv;
+ Vector<Pair<int, int> > uv_index;
+
+ Vector<ArrayMeshLightmapSurface> surfaces;
+ for (int i = 0; i < get_surface_count(); i++) {
+ ArrayMeshLightmapSurface s;
+ s.primitive = surface_get_primitive_type(i);
+
+ if (s.primitive != Mesh::PRIMITIVE_TRIANGLES) {
+ ERR_EXPLAIN("Only triangles are supported for lightmap unwrap");
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+ s.format = surface_get_format(i);
+ if (!(s.format & ARRAY_FORMAT_NORMAL)) {
+ ERR_EXPLAIN("Normals are required for lightmap unwrap");
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+
+ Array arrays = surface_get_arrays(i);
+ s.material = surface_get_material(i);
+ s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays);
+
+ PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
+ int vc = rvertices.size();
+ PoolVector<Vector3>::Read r = rvertices.read();
+
+ PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
+ PoolVector<Vector3>::Read rn = rnormals.read();
+
+ int vertex_ofs = vertices.size() / 3;
+
+ vertices.resize((vertex_ofs + vc) * 3);
+ normals.resize((vertex_ofs + vc) * 3);
+ uv_index.resize(vertex_ofs + vc);
+
+ for (int j = 0; j < vc; j++) {
+
+ Vector3 v = p_base_transform.xform(r[j]);
+
+ vertices[(j + vertex_ofs) * 3 + 0] = v.x;
+ vertices[(j + vertex_ofs) * 3 + 1] = v.y;
+ vertices[(j + vertex_ofs) * 3 + 2] = v.z;
+ normals[(j + vertex_ofs) * 3 + 0] = rn[j].x;
+ normals[(j + vertex_ofs) * 3 + 1] = rn[j].y;
+ normals[(j + vertex_ofs) * 3 + 2] = rn[j].z;
+ uv_index[j + vertex_ofs] = Pair<int, int>(i, j);
+ }
+
+ PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX];
+ int ic = rindices.size();
+ int index_ofs = indices.size();
+
+ if (ic == 0) {
+ indices.resize(index_ofs + vc);
+ face_materials.resize((index_ofs + vc) / 3);
+ for (int j = 0; j < vc; j++) {
+ indices[index_ofs + j] = vertex_ofs + j;
+ }
+ for (int j = 0; j < vc / 3; j++) {
+ face_materials[(index_ofs / 3) + j] = i;
+ }
+
+ } else {
+ PoolVector<int>::Read ri = rindices.read();
+ indices.resize(index_ofs + ic);
+ face_materials.resize((index_ofs + ic) / 3);
+ for (int j = 0; j < ic; j++) {
+ indices[index_ofs + j] = vertex_ofs + ri[j];
+ }
+ for (int j = 0; j < ic / 3; j++) {
+ face_materials[(index_ofs / 3) + j] = i;
+ }
+ }
+
+ surfaces.push_back(s);
+ }
+
+ //unwrap
+
+ float *gen_uvs;
+ int *gen_vertices;
+ int *gen_indices;
+ int gen_vertex_count;
+ int gen_index_count;
+ int size_x;
+ int size_y;
+
+ bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y);
+
+ if (!ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ //remove surfaces
+ while (get_surface_count()) {
+ surface_remove(0);
+ }
+
+ //create surfacetools for each surface..
+ Vector<Ref<SurfaceTool> > surfaces_tools;
+
+ for (int i = 0; i < surfaces.size(); i++) {
+ Ref<SurfaceTool> st;
+ st.instance();
+ st->begin(Mesh::PRIMITIVE_TRIANGLES);
+ st->set_material(surfaces[i].material);
+ surfaces_tools.push_back(st); //stay there
+ }
+
+ print_line("gen indices: " + itos(gen_index_count));
+ //go through all indices
+ for (int i = 0; i < gen_index_count; i += 3) {
+
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG);
+
+ ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);
+
+ int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first;
+
+ for (int j = 0; j < 3; j++) {
+
+ int vertex_idx = gen_vertices[gen_indices[i + j]];
+
+ SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second];
+
+ if (surfaces[surface].format & ARRAY_FORMAT_COLOR) {
+ surfaces_tools[surface]->add_color(v.color);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
+ surfaces_tools[surface]->add_uv(v.uv);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
+ surfaces_tools[surface]->add_normal(v.normal);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
+ Plane t;
+ t.normal = v.tangent;
+ t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
+ surfaces_tools[surface]->add_tangent(t);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_BONES) {
+ surfaces_tools[surface]->add_bones(v.bones);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
+ surfaces_tools[surface]->add_weights(v.weights);
+ }
+
+ Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
+ surfaces_tools[surface]->add_uv2(uv2);
+
+ surfaces_tools[surface]->add_vertex(v.vertex);
+ }
+ }
+
+ //free stuff
+ ::free(gen_vertices);
+ ::free(gen_indices);
+ ::free(gen_uvs);
+
+ //generate surfaces
+
+ for (int i = 0; i < surfaces_tools.size(); i++) {
+ surfaces_tools[i]->index();
+ surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format);
+ }
+
+ set_lightmap_size_hint(Size2(size_x, size_y));
+
+ return OK;
+}
+
void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index b85a6a84af..ea38ebf2ff 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -43,6 +43,8 @@ class Mesh : public Resource {
GDCLASS(Mesh, Resource);
mutable Ref<TriangleMesh> triangle_mesh; //cached
+ Size2 lightmap_size_hint;
+
protected:
void _clear_triangle_mesh() const;
@@ -138,6 +140,9 @@ public:
virtual AABB get_aabb() const = 0;
+ void set_lightmap_size_hint(const Vector2 &p_size);
+ Size2 get_lightmap_size_hint() const;
+
Mesh();
};
@@ -216,6 +221,8 @@ public:
void center_geometry();
void regen_normalmaps();
+ Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
+
virtual void reload_from_file();
ArrayMesh();
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index bf89e704bc..352418e65c 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -101,6 +101,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
vtx.color = last_color;
vtx.normal = last_normal;
vtx.uv = last_uv;
+ vtx.uv2 = last_uv2;
vtx.weights = last_weights;
vtx.bones = last_bones;
vtx.tangent = last_tangent.normal;
@@ -401,7 +402,7 @@ Array SurfaceTool::commit_to_arrays() {
return a;
}
-Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) {
+Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_flags) {
Ref<ArrayMesh> mesh;
if (p_existing.is_valid())
@@ -418,7 +419,7 @@ Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) {
Array a = commit_to_arrays();
- mesh->add_surface_from_arrays(primitive, a);
+ mesh->add_surface_from_arrays(primitive, a, Array(), p_flags);
if (material.is_valid())
mesh->surface_set_material(surface, material);
@@ -482,6 +483,113 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
}
+Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) {
+
+ Vector<SurfaceTool::Vertex> ret;
+
+ PoolVector<Vector3> varr = p_arrays[VS::ARRAY_VERTEX];
+ PoolVector<Vector3> narr = p_arrays[VS::ARRAY_NORMAL];
+ PoolVector<float> tarr = p_arrays[VS::ARRAY_TANGENT];
+ PoolVector<Color> carr = p_arrays[VS::ARRAY_COLOR];
+ PoolVector<Vector2> uvarr = p_arrays[VS::ARRAY_TEX_UV];
+ PoolVector<Vector2> uv2arr = p_arrays[VS::ARRAY_TEX_UV2];
+ PoolVector<int> barr = p_arrays[VS::ARRAY_BONES];
+ PoolVector<float> warr = p_arrays[VS::ARRAY_WEIGHTS];
+
+ int vc = varr.size();
+
+ if (vc == 0)
+ return ret;
+ int lformat = 0;
+
+ PoolVector<Vector3>::Read rv;
+ if (varr.size()) {
+ lformat |= VS::ARRAY_FORMAT_VERTEX;
+ rv = varr.read();
+ }
+ PoolVector<Vector3>::Read rn;
+ if (narr.size()) {
+ lformat |= VS::ARRAY_FORMAT_NORMAL;
+ rn = narr.read();
+ }
+ PoolVector<float>::Read rt;
+ if (tarr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TANGENT;
+ rt = tarr.read();
+ }
+ PoolVector<Color>::Read rc;
+ if (carr.size()) {
+ lformat |= VS::ARRAY_FORMAT_COLOR;
+ rc = carr.read();
+ }
+
+ PoolVector<Vector2>::Read ruv;
+ if (uvarr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TEX_UV;
+ ruv = uvarr.read();
+ }
+
+ PoolVector<Vector2>::Read ruv2;
+ if (uv2arr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TEX_UV2;
+ ruv2 = uv2arr.read();
+ }
+
+ PoolVector<int>::Read rb;
+ if (barr.size()) {
+ lformat |= VS::ARRAY_FORMAT_BONES;
+ rb = barr.read();
+ }
+
+ PoolVector<float>::Read rw;
+ if (warr.size()) {
+ lformat |= VS::ARRAY_FORMAT_WEIGHTS;
+ rw = warr.read();
+ }
+
+ for (int i = 0; i < vc; i++) {
+
+ Vertex v;
+ if (lformat & VS::ARRAY_FORMAT_VERTEX)
+ v.vertex = varr[i];
+ if (lformat & VS::ARRAY_FORMAT_NORMAL)
+ v.normal = narr[i];
+ if (lformat & VS::ARRAY_FORMAT_TANGENT) {
+ Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
+ v.tangent = p.normal;
+ v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
+ }
+ if (lformat & VS::ARRAY_FORMAT_COLOR)
+ v.color = carr[i];
+ if (lformat & VS::ARRAY_FORMAT_TEX_UV)
+ v.uv = uvarr[i];
+ if (lformat & VS::ARRAY_FORMAT_TEX_UV2)
+ v.uv2 = uv2arr[i];
+ if (lformat & VS::ARRAY_FORMAT_BONES) {
+ Vector<int> b;
+ b.resize(4);
+ b[0] = barr[i * 4 + 0];
+ b[1] = barr[i * 4 + 1];
+ b[2] = barr[i * 4 + 2];
+ b[3] = barr[i * 4 + 3];
+ v.bones = b;
+ }
+ if (lformat & VS::ARRAY_FORMAT_WEIGHTS) {
+ Vector<float> w;
+ w.resize(4);
+ w[0] = warr[i * 4 + 0];
+ w[1] = warr[i * 4 + 1];
+ w[2] = warr[i * 4 + 2];
+ w[3] = warr[i * 4 + 3];
+ v.weights = w;
+ }
+
+ ret.push_back(v);
+ }
+
+ return ret;
+}
+
void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX];
@@ -882,7 +990,7 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from);
ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from);
- ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT));
}
SurfaceTool::SurfaceTool() {
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index cdaac643de..b180ffe260 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -127,10 +127,11 @@ public:
List<Vertex> &get_vertex_array() { return vertex_array; }
void create_from_triangle_arrays(const Array &p_arrays);
+ static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays);
Array commit_to_arrays();
void create_from(const Ref<Mesh> &p_existing, int p_surface);
void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform);
- Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>());
+ Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = Mesh::ARRAY_COMPRESS_DEFAULT);
SurfaceTool();
};