#include "morpher.h" #include #include DNA_::DNA_(String &path) { } DNA_::DNA_() { } DNA_::~DNA_() { } void DNA_::_bind_methods() { ClassDB::bind_method(D_METHOD("add_mesh", "part", "mesh", "same_verts"), &DNA_::add_mesh); ClassDB::bind_method(D_METHOD("add_cloth_mesh", "cloth_name", "cloth_helper", "mesh"), &DNA_::add_cloth_mesh); ClassDB::bind_method(D_METHOD("add_body_mesh", "body_mesh", "same_verts"), &DNA_::add_body_mesh); ClassDB::bind_method(D_METHOD("_prepare_cloth", "body_mesh", "cloth_mesh"), &DNA_::_prepare_cloth); ClassDB::bind_method(D_METHOD("find_body_points", "body_mesh", "cloth_mesh"), &DNA_::find_body_points); ClassDB::bind_method(D_METHOD("get_modifier_list"), &DNA_::get_modifier_list); ClassDB::bind_method(D_METHOD("triangulate_uv", "v0", "vs", "uvs"), &DNA_::triangulate_uv); ClassDB::bind_method(D_METHOD("get_replace_point_id", "point_pool", "vc", "vb_id", "selected_points"), &DNA_::get_replace_point_id); ClassDB::bind_method(D_METHOD("triangulate_uv_arrays", "point", "uv_index", "arrays", "points"), &DNA_::triangulate_uv_arrays); ClassDB::bind_method(D_METHOD("ensure_uv2", "arrays"), &DNA_::ensure_uv2); ClassDB::bind_method(D_METHOD("get_closest_points", "point", "pool_vertices", "indices", "count"), &DNA_::get_closest_points); ClassDB::bind_method(D_METHOD("load", "path"), &DNA_::load); ClassDB::bind_method(D_METHOD("modify_mesh", "orig_mesh", "same_verts"), &DNA_::modify_mesh); ClassDB::bind_method(D_METHOD("modify_part", "part"), &DNA_::modify_part); ClassDB::bind_method(D_METHOD("set_modifier_value", "mod_name", "value"), &DNA_::set_modifier_value); } Dictionary DNA_::find_body_points(const Ref &body_mesh, const Ref &cloth_mesh) { Dictionary tmp; Array arrays_cloth = cloth_mesh->surface_get_arrays(0); Array arrays_body = body_mesh->surface_get_arrays(0); const PoolVector &cloth_vertices = arrays_cloth[Mesh::ARRAY_VERTEX]; const PoolVector &body_vertices = arrays_body[Mesh::ARRAY_VERTEX]; for (int vcloth = 0; vcloth < cloth_vertices.size(); vcloth++) { for (int vbody = 0; vbody < body_vertices.size(); vbody++) { Vector3 vc = cloth_vertices[vcloth]; Vector3 vb = body_vertices[vbody]; if (vc.distance_to(vb) < 0.02f) { if (tmp.has(vcloth)) { PoolVector data = tmp[vcloth]; data.push_back(vbody); tmp[vcloth] = data; } else { PoolVector data; data.push_back(vbody); tmp[vcloth] = data; } } } } return tmp; } Ref DNA_::_prepare_cloth(const Ref &body_mesh, const Ref &cloth_mesh) { Array arrays_cloth = cloth_mesh->surface_get_arrays(0); ensure_uv2(arrays_cloth); Array arrays_body = body_mesh->surface_get_arrays(0); const PoolVector &cloth_vertices = arrays_cloth[Mesh::ARRAY_VERTEX]; const PoolVector &body_vertices = arrays_body[Mesh::ARRAY_VERTEX]; const PoolVector &body_uvs = arrays_body[Mesh::ARRAY_TEX_UV]; Dictionary tmp = find_body_points(body_mesh, cloth_mesh); PoolVector cloth_uv2 = arrays_cloth[Mesh::ARRAY_TEX_UV2]; Array tmp_keys = tmp.keys(); for (int i = 0; i < tmp_keys.size(); i++) { int k = tmp_keys[i]; Vector3 vc = cloth_vertices[k]; PoolVector data = tmp[k]; PoolVector res = get_closest_points(vc, body_vertices, data, 3); if (res.size() == 3) { Vector2 uv = triangulate_uv_arrays(vc, Mesh::ARRAY_TEX_UV, arrays_body, res); cloth_uv2.write()[k] = uv; } } arrays_cloth[Mesh::ARRAY_TEX_UV2] = cloth_uv2; for (int s = 0; s < cloth_uv2.size(); s++) { PoolVector uv1 = arrays_cloth[Mesh::ARRAY_TEX_UV]; PoolVector uv2 = arrays_cloth[Mesh::ARRAY_TEX_UV2]; } Ref new_mesh = memnew(ArrayMesh); new_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays_cloth); return new_mesh; } Ref DNA_::modify_mesh(const Ref orig_mesh, const Dictionary same_verts) { Ref ret = memnew(ArrayMesh); PoolVector modifier_list = get_modifier_list(); lock_all_images(); Rect2 rect = collect_rects(); modify_mesh_mutex.lock(); int surface_count = orig_mesh->get_surface_count(); for (int surface = 0; surface < surface_count; surface++) { Array arrays = orig_mesh->surface_get_arrays(surface); int uv_index = Mesh::ARRAY_TEX_UV; if (arrays[Mesh::ARRAY_TEX_UV2].get_type() != Variant::NIL) uv_index = Mesh::ARRAY_TEX_UV2; PoolVector vertices = arrays[Mesh::ARRAY_VERTEX]; PoolVector normals = arrays[Mesh::ARRAY_NORMAL]; PoolVector uvs = arrays[uv_index]; mod_cache.resize(vertices.size()); Vector3 n, v, diff, diffn; Vector2 uv; for (int index = 0; index < vertices.size(); index++) { // printf("init index: %d v: %ls n: %ls\n", index, String(v).c_str(), String(n).c_str()); uv = uvs[index]; if (!rect.has_point(uv)) continue; v = vertices[index]; n = normals[index]; if (mod_cache[index].get_type() == Variant::NIL) { Dictionary data; mod_cache[index] = data; } for (int ki = 0; ki < modifier_list.size(); ki++) { String key = modifier_list[ki]; Rect2 mrect = map_rect[key]; float value = mod_value[key]; if (!mrect.has_point(uv) || value < 0.0001) continue; Dictionary cache = mod_cache[index]; if (cache.has(key)) { Array data = cache[key]; diff = data[0]; diffn = data[1]; } else { diff = Vector3(); diffn = Vector3(); Vector2 pos(uv.x * (float)image_sizes[key].x, uv.y * (float)image_sizes[key].y); Color offset = map_vertices[key]->get_pixelv(pos); Color offsetn = map_normals[key]->get_pixelv(pos); Vector3 pdiff(offset.r, offset.g, offset.b); Vector3 ndiff(offsetn.r, offsetn.g, offsetn.b); for (int u = 0; u < 3; u++) { diff[u] = Math::range_lerp(pdiff[u], 0.0f, 1.0f, min_point[u], max_point[u]); diffn[u] = Math::range_lerp(ndiff[u], 0.0f, 1.0f, min_normal[u], max_normal[u]); if (fabs(diff[u]) < 0.0001f) diff[u] = 0.0f; if (fabs(diffn[u]) < 0.0001f) diffn[u] = 0.0f; } Array cache_data; cache_data.push_back(diff); cache_data.push_back(diffn); cache[key] = cache_data; // printf("diff: %ls diffn: %ls\n", String(diff).c_str(), String(diffn).c_str()); } v -= diff * value; n -= diffn * value; } vertices.write()[index] = v; normals.write()[index] = n; } Array idx_keys = same_verts.keys(); for (int vxk = 0; vxk < idx_keys.size(); vxk++) { int xv = idx_keys[vxk]; Array data = same_verts[xv]; if (data.size() <= 1) continue; Vector3 vx = vertices[data[0]]; for (int idx = 1; idx < data.size(); idx++) vx.linear_interpolate(vertices[data[idx]], 0.5f); for (int idx = 0; idx < data.size(); idx++) vertices.write()[data[idx]] = vx; } arrays[Mesh::ARRAY_VERTEX] = vertices; arrays[Mesh::ARRAY_NORMAL] = normals; ret->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays); Ref mat = orig_mesh->surface_get_material(surface); if (mat != NULL) ret->surface_set_material(surface, mat); } modify_mesh_mutex.unlock(); unlock_all_images(); return ret; } Variant DNA_::get_var(FileAccess *f) const { uint32_t len = f->get_32(); PoolVector buff; buff.resize(len); PoolVector::Write w = buff.write(); f->get_buffer(&w[0], len); w.release(); PoolVector::Read r = buff.read(); Variant v; decode_variant(v, &r[0], len, NULL, false); return v; } bool DNA_::load(const String &path) { Error err; FileAccess *f = FileAccess::open(path, FileAccess::READ, &err); if (!f || err != OK) return false; min_point = get_var(f); max_point = get_var(f); min_normal = get_var(f); max_normal = get_var(f); maps = get_var(f); vert_indices = get_var(f); printf("min: %ls max: %ls\n", String(min_point).c_str(), String(max_point).c_str()); if (f) f->close(); Array map_keys = maps.keys(); for (int i = 0; i < map_keys.size(); i++) { String key = map_keys[i]; Dictionary map = maps[key]; Rect2 rect = map["rect"]; map_rect[key] = rect; PoolVector compressed_data = map["image_data"]; PoolVector compressed_normal_data = map["image_normal_data"]; printf("%ls: %ls\n / points: %d normals: %d\n", key.c_str(), String(rect).c_str(), compressed_data.size(), compressed_normal_data.size()); int width, height, size, normal_size, format; size = map["image_size"]; normal_size = map["image_normal_size"]; width = map["width"]; height = map["height"]; format = map["format"]; printf("size: %d normal size: %d\n", size, normal_size); image_sizes[key] = Vector2i(width, height); PoolVector decompressed_data, decompressed_normal_data; decompressed_data.resize(size); decompressed_normal_data.resize(normal_size); Compression::decompress(decompressed_data.write().ptr(), size, compressed_data.read().ptr(), compressed_data.size(), Compression::MODE_FASTLZ); Compression::decompress(decompressed_normal_data.write().ptr(), normal_size, compressed_normal_data.read().ptr(), compressed_normal_data.size(), Compression::MODE_FASTLZ); Ref vertex_image = memnew(Image); Ref normal_image = memnew(Image); vertex_image->create(width, height, false, (enum Image::Format)format, decompressed_data); normal_image->create(width, height, false, (enum Image::Format)format, decompressed_normal_data); map_vertices[key] = vertex_image; map_normals[key] = vertex_image; } return true; }