bool GridMap::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name == "theme") { set_theme(p_value); } else if (name == "cell_size") { if (p_value.get_type() == Variant::INT || p_value.get_type() == Variant::REAL) { //compatibility float cs = p_value; set_cell_size(Vector3(cs, cs, cs)); } else { set_cell_size(p_value); } } else if (name == "cell_octant_size") { set_octant_size(p_value); } else if (name == "cell_center_x") { set_center_x(p_value); } else if (name == "cell_center_y") { set_center_y(p_value); } else if (name == "cell_center_z") { set_center_z(p_value); } else if (name == "cell_scale") { set_cell_scale(p_value); /* } else if (name=="cells") { PoolVector<int> cells = p_value; int amount=cells.size(); PoolVector<int>::Read r = cells.read(); ERR_FAIL_COND_V(amount&1,false); // not even cell_map.clear(); for(int i=0;i<amount/3;i++) { IndexKey ik; ik.key=decode_uint64(&r[i*3]); Cell cell; cell.cell=uint32_t(r[i*+1]); cell_map[ik]=cell; } _recreate_octant_data();*/ } else if (name == "data") { Dictionary d = p_value; if (d.has("cells")) { PoolVector<int> cells = d["cells"]; int amount = cells.size(); PoolVector<int>::Read r = cells.read(); ERR_FAIL_COND_V(amount % 3, false); // not even cell_map.clear(); for (int i = 0; i < amount / 3; i++) { IndexKey ik; ik.key = decode_uint64((const uint8_t *)&r[i * 3]); Cell cell; cell.cell = decode_uint32((const uint8_t *)&r[i * 3 + 2]); cell_map[ik] = cell; } } _recreate_octant_data(); } else return false; return true; }
Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) { Ref<Sample> smp =p_from; ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>()); int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size*=EDSCALE; PoolVector<uint8_t> img; int w = thumbnail_size; int h = thumbnail_size; img.resize(w*h*3); PoolVector<uint8_t>::Write imgdata = img.write(); uint8_t * imgw = imgdata.ptr(); PoolVector<uint8_t> data = smp->get_data(); PoolVector<uint8_t>::Read sampledata = data.read(); const uint8_t *sdata=sampledata.ptr(); bool stereo = smp->is_stereo(); bool _16=smp->get_format()==Sample::FORMAT_PCM16; int len = smp->get_length(); if (len<1) return Ref<Texture>(); if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) { struct IMA_ADPCM_State { int16_t step_index; int32_t predictor; /* values at loop point */ int16_t loop_step_index; int32_t loop_predictor; int32_t last_nibble; int32_t loop_pos; int32_t window_ofs; const uint8_t *ptr; } ima_adpcm; ima_adpcm.step_index=0; ima_adpcm.predictor=0; ima_adpcm.loop_step_index=0; ima_adpcm.loop_predictor=0; ima_adpcm.last_nibble=-1; ima_adpcm.loop_pos=0x7FFFFFFF; ima_adpcm.window_ofs=0; ima_adpcm.ptr=NULL; for(int i=0;i<w;i++) { float max[2]={-1e10,-1e10}; float min[2]={1e10,1e10}; int from = i*len/w; int to = (i+1)*len/w; if (to>=len) to=len-1; for(int j=from;j<to;j++) { while(j>ima_adpcm.last_nibble) { static const int16_t _ima_adpcm_step_table[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; static const int8_t _ima_adpcm_index_table[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; int16_t nibble,diff,step; ima_adpcm.last_nibble++; const uint8_t *src_ptr=sdata; int ofs = ima_adpcm.last_nibble>>1; if (stereo) ofs*=2; nibble = (ima_adpcm.last_nibble&1)? (src_ptr[ofs]>>4):(src_ptr[ofs]&0xF); step=_ima_adpcm_step_table[ima_adpcm.step_index]; ima_adpcm.step_index += _ima_adpcm_index_table[nibble]; if (ima_adpcm.step_index<0) ima_adpcm.step_index=0; if (ima_adpcm.step_index>88) ima_adpcm.step_index=88; diff = step >> 3 ; if (nibble & 1) diff += step >> 2 ; if (nibble & 2) diff += step >> 1 ; if (nibble & 4) diff += step ; if (nibble & 8) diff = -diff ; ima_adpcm.predictor+=diff; if (ima_adpcm.predictor<-0x8000) ima_adpcm.predictor=-0x8000; else if (ima_adpcm.predictor>0x7FFF) ima_adpcm.predictor=0x7FFF; /* store loop if there */ if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) { ima_adpcm.loop_step_index = ima_adpcm.step_index; ima_adpcm.loop_predictor = ima_adpcm.predictor; } } float v=ima_adpcm.predictor/32767.0; if (v>max[0]) max[0]=v; if (v<min[0]) min[0]=v; } max[0]*=0.8; min[0]*=0.8; for(int j=0;j<h;j++) { float v = (j/(float)h) * 2.0 - 1.0; uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3]; if (v>min[0] && v<max[0]) { imgofs[0]=255; imgofs[1]=150; imgofs[2]=80; } else { imgofs[0]=0; imgofs[1]=0; imgofs[2]=0; } } } } else { for(int i=0;i<w;i++) {
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { print_line("attempt to call " + String(p_method)); r_error.error = Variant::CallError::CALL_OK; Map<StringName, MethodData>::Element *E = method_map.find(p_method); if (!E) { print_line("no exists"); r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); } int ac = E->get().argtypes.size(); if (ac < p_argcount) { print_line("fewargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = ac; return Variant(); } if (ac > p_argcount) { print_line("manyargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument = ac; return Variant(); } for (int i = 0; i < p_argcount; i++) { if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = i; r_error.expected = E->get().argtypes[i]; } } jvalue *v = NULL; if (p_argcount) { v = (jvalue *)alloca(sizeof(jvalue) * p_argcount); } for (int i = 0; i < p_argcount; i++) { switch (E->get().argtypes[i]) { case Variant::BOOL: { v[i].z = *p_args[i]; } break; case Variant::INT: { v[i].i = *p_args[i]; } break; case Variant::REAL: { v[i].f = *p_args[i]; } break; case Variant::STRING: { String s = *p_args[i]; jstring jStr = env->NewStringUTF(s.utf8().get_data()); v[i].l = jStr; } break; case Variant::STRING_ARRAY: { PoolVector<String> sarray = *p_args[i]; jobjectArray arr = env->NewObjectArray(sarray.size(), env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int j = 0; j < sarray.size(); j++) { env->SetObjectArrayElement(arr, j, env->NewStringUTF(sarray[i].utf8().get_data())); } v[i].l = arr; } break; case Variant::INT_ARRAY: { PoolVector<int> array = *p_args[i]; jintArray arr = env->NewIntArray(array.size()); PoolVector<int>::Read r = array.read(); env->SetIntArrayRegion(arr, 0, array.size(), r.ptr()); v[i].l = arr; } break; case Variant::REAL_ARRAY: { PoolVector<float> array = *p_args[i]; jfloatArray arr = env->NewFloatArray(array.size()); PoolVector<float>::Read r = array.read(); env->SetFloatArrayRegion(arr, 0, array.size(), r.ptr()); v[i].l = arr; } break; default: { ERR_FAIL_V(Variant()); } break; } } print_line("calling method!!"); Variant ret; switch (E->get().ret_type) { case Variant::NIL: { print_line("call void"); env->CallVoidMethodA(instance, E->get().method, v); } break; case Variant::BOOL: { ret = env->CallBooleanMethodA(instance, E->get().method, v); print_line("call bool"); } break; case Variant::INT: { ret = env->CallIntMethodA(instance, E->get().method, v); print_line("call int"); } break; case Variant::REAL: { ret = env->CallFloatMethodA(instance, E->get().method, v); } break; case Variant::STRING: { jobject o = env->CallObjectMethodA(instance, E->get().method, v); String singname = env->GetStringUTFChars((jstring)o, NULL); } break; case Variant::STRING_ARRAY: { jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v); int stringCount = env->GetArrayLength(arr); PoolVector<String> sarr; for (int i = 0; i < stringCount; i++) { jstring string = (jstring)env->GetObjectArrayElement(arr, i); const char *rawString = env->GetStringUTFChars(string, 0); sarr.push_back(String(rawString)); } ret = sarr; } break; case Variant::INT_ARRAY: { jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v); int fCount = env->GetArrayLength(arr); PoolVector<int> sarr; sarr.resize(fCount); PoolVector<int>::Write w = sarr.write(); env->GetIntArrayRegion(arr, 0, fCount, w.ptr()); w = PoolVector<int>::Write(); ret = sarr; } break; case Variant::REAL_ARRAY: { jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v); int fCount = env->GetArrayLength(arr); PoolVector<float> sarr; sarr.resize(fCount); PoolVector<float>::Write w = sarr.write(); env->GetFloatArrayRegion(arr, 0, fCount, w.ptr()); w = PoolVector<float>::Write(); ret = sarr; } break; default: { print_line("failure.."); ERR_FAIL_V(Variant()); } break; } print_line("success"); return ret; }
void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { valid = false; int fc = p_faces.size(); ERR_FAIL_COND(!fc || ((fc % 3) != 0)); fc /= 3; triangles.resize(fc); bvh.resize(fc * 3); //will never be larger than this (todo make better) PoolVector<BVH>::Write bw = bvh.write(); { //create faces and indices and base bvh //except for the Set for repeated triangles, everything //goes in-place. PoolVector<Vector3>::Read r = p_faces.read(); PoolVector<Triangle>::Write w = triangles.write(); Map<Vector3, int> db; for (int i = 0; i < fc; i++) { Triangle &f = w[i]; const Vector3 *v = &r[i * 3]; for (int j = 0; j < 3; j++) { int vidx = -1; Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001)); Map<Vector3, int>::Element *E = db.find(vs); if (E) { vidx = E->get(); } else { vidx = db.size(); db[vs] = vidx; } f.indices[j] = vidx; if (j == 0) bw[i].aabb.position = vs; else bw[i].aabb.expand_to(vs); } f.normal = Face3(r[i * 3 + 0], r[i * 3 + 1], r[i * 3 + 2]).get_plane().get_normal(); bw[i].left = -1; bw[i].right = -1; bw[i].face_index = i; bw[i].center = bw[i].aabb.position + bw[i].aabb.size * 0.5; } vertices.resize(db.size()); PoolVector<Vector3>::Write vw = vertices.write(); for (Map<Vector3, int>::Element *E = db.front(); E; E = E->next()) { vw[E->get()] = E->key(); } } PoolVector<BVH *> bwptrs; bwptrs.resize(fc); PoolVector<BVH *>::Write bwp = bwptrs.write(); for (int i = 0; i < fc; i++) { bwp[i] = &bw[i]; } max_depth = 0; int max_alloc = fc; _create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc); bw = PoolVector<BVH>::Write(); //clearup bvh.resize(max_alloc); //resize back valid = true; }
Ref<Mesh> NavigationMesh::get_debug_mesh() { if (debug_mesh.is_valid()) return debug_mesh; PoolVector<Vector3> vertices = get_vertices(); PoolVector<Vector3>::Read vr = vertices.read(); List<Face3> faces; for (int i = 0; i < get_polygon_count(); i++) { Vector<int> p = get_polygon(i); for (int j = 2; j < p.size(); j++) { Face3 f; f.vertex[0] = vr[p[0]]; f.vertex[1] = vr[p[j - 1]]; f.vertex[2] = vr[p[j]]; faces.push_back(f); } } Map<_EdgeKey, bool> edge_map; PoolVector<Vector3> tmeshfaces; tmeshfaces.resize(faces.size() * 3); { PoolVector<Vector3>::Write tw = tmeshfaces.write(); int tidx = 0; for (List<Face3>::Element *E = faces.front(); E; E = E->next()) { const Face3 &f = E->get(); for (int j = 0; j < 3; j++) { tw[tidx++] = f.vertex[j]; _EdgeKey ek; ek.from = f.vertex[j].snapped(CMP_EPSILON); ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON); if (ek.from < ek.to) SWAP(ek.from, ek.to); Map<_EdgeKey, bool>::Element *E = edge_map.find(ek); if (E) { E->get() = false; } else { edge_map[ek] = true; } } } } List<Vector3> lines; for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) { if (E->get()) { lines.push_back(E->key().from); lines.push_back(E->key().to); } } PoolVector<Vector3> varr; varr.resize(lines.size()); { PoolVector<Vector3>::Write w = varr.write(); int idx = 0; for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) { w[idx++] = E->get(); } } debug_mesh = Ref<Mesh>(memnew(Mesh)); Array arr; arr.resize(Mesh::ARRAY_MAX); arr[Mesh::ARRAY_VERTEX] = varr; debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); return debug_mesh; }
void Navigation2D::_navpoly_link(int p_id) { ERR_FAIL_COND(!navpoly_map.has(p_id)); NavMesh &nm = navpoly_map[p_id]; ERR_FAIL_COND(nm.linked); PoolVector<Vector2> vertices = nm.navpoly->get_vertices(); int len = vertices.size(); if (len == 0) return; PoolVector<Vector2>::Read r = vertices.read(); for (int i = 0; i < nm.navpoly->get_polygon_count(); i++) { //build List<Polygon>::Element *P = nm.polygons.push_back(Polygon()); Polygon &p = P->get(); p.owner = &nm; Vector<int> poly = nm.navpoly->get_polygon(i); int plen = poly.size(); const int *indices = poly.ptr(); bool valid = true; p.edges.resize(plen); Vector2 center; float sum = 0; for (int j = 0; j < plen; j++) { int idx = indices[j]; if (idx < 0 || idx >= len) { valid = false; break; } Polygon::Edge e; Vector2 ep = nm.xform.xform(r[idx]); center += ep; e.point = _get_point(ep); p.edges[j] = e; int idxn = indices[(j + 1) % plen]; if (idxn < 0 || idxn >= len) { valid = false; break; } Vector2 epn = nm.xform.xform(r[idxn]); sum += (epn.x - ep.x) * (epn.y + ep.y); } p.clockwise = sum > 0; if (!valid) { nm.polygons.pop_back(); ERR_CONTINUE(!valid); continue; } p.center = center / plen; //connect for (int j = 0; j < plen; j++) { int next = (j + 1) % plen; EdgeKey ek(p.edges[j].point, p.edges[next].point); Map<EdgeKey, Connection>::Element *C = connections.find(ek); if (!C) { Connection c; c.A = &p; c.A_edge = j; c.B = NULL; c.B_edge = -1; connections[ek] = c; } else { if (C->get().B != NULL) { ConnectionPending pending; pending.polygon = &p; pending.edge = j; p.edges[j].P = C->get().pending.push_back(pending); continue; //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); } C->get().B = &p; C->get().B_edge = j; C->get().A->edges[C->get().A_edge].C = &p; C->get().A->edges[C->get().A_edge].C_edge = j; p.edges[j].C = C->get().A; p.edges[j].C_edge = C->get().A_edge; //connection successful. } } } nm.linked = true; }
void GIProbe::_plot_mesh(const Transform& p_xform, Ref<Mesh>& p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) { for(int i=0;i<p_mesh->get_surface_count();i++) { if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) continue; //only triangles Ref<Material> src_material; if (p_override_material.is_valid()) { src_material=p_override_material; } else if (i<p_materials.size() && p_materials[i].is_valid()) { src_material=p_materials[i]; } else { src_material=p_mesh->surface_get_material(i); } Baker::MaterialCache material = _get_material_cache(src_material,p_baker); Array a = p_mesh->surface_get_arrays(i); PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; PoolVector<Vector3>::Read vr=vertices.read(); PoolVector<Vector2> uv = a[Mesh::ARRAY_TEX_UV]; PoolVector<Vector2>::Read uvr; PoolVector<int> index = a[Mesh::ARRAY_INDEX]; bool read_uv=false; if (uv.size()) { uvr=uv.read(); read_uv=true; } if (index.size()) { int facecount = index.size()/3; PoolVector<int>::Read ir=index.read(); for(int j=0;j<facecount;j++) { Vector3 vtxs[3]; Vector2 uvs[3]; for(int k=0;k<3;k++) { vtxs[k]=p_xform.xform(vr[ir[j*3+k]]); } if (read_uv) { for(int k=0;k<3;k++) { uvs[k]=uvr[ir[j*3+k]]; } } //test against original bounds if (!fast_tri_box_overlap(-extents,extents*2,vtxs)) continue; //plot _plot_face(0,0,0,0,0,vtxs,uvs,material,p_baker->po2_bounds,p_baker); } } else { int facecount = vertices.size()/3; for(int j=0;j<facecount;j++) { Vector3 vtxs[3]; Vector2 uvs[3]; for(int k=0;k<3;k++) { vtxs[k]=p_xform.xform(vr[j*3+k]); } if (read_uv) { for(int k=0;k<3;k++) { uvs[k]=uvr[j*3+k]; } } //test against original bounds if (!fast_tri_box_overlap(-extents,extents*2,vtxs)) continue; //plot face _plot_face(0,0,0,0,0,vtxs,uvs,material,p_baker->po2_bounds,p_baker); } } } }
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n"; if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { // Don't append the standard ports request += "Host: " + conn_host + "\r\n"; } else { request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; } bool add_clen = p_body.size() > 0; bool add_uagent = true; bool add_accept = true; for (int i = 0; i < p_headers.size(); i++) { request += p_headers[i] + "\r\n"; if (add_clen && p_headers[i].findn("Content-Length:") == 0) { add_clen = false; } if (add_uagent && p_headers[i].findn("User-Agent:") == 0) { add_uagent = false; } if (add_accept && p_headers[i].findn("Accept:") == 0) { add_accept = false; } } if (add_clen) { request += "Content-Length: " + itos(p_body.size()) + "\r\n"; // Should it add utf8 encoding? } if (add_uagent) { request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n"; } if (add_accept) { request += "Accept: */*\r\n"; } request += "\r\n"; CharString cs = request.utf8(); PoolVector<uint8_t> data; data.resize(cs.length()); { PoolVector<uint8_t>::Write data_write = data.write(); for (int i = 0; i < cs.length(); i++) { data_write[i] = cs[i]; } } data.append_array(p_body); PoolVector<uint8_t>::Read r = data.read(); Error err = connection->put_data(&r[0], data.size()); if (err) { close(); status = STATUS_CONNECTION_ERROR; return err; } status = STATUS_REQUESTING; return OK; }
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.write[0] = barr[i * 4 + 0]; b.write[1] = barr[i * 4 + 1]; b.write[2] = barr[i * 4 + 2]; b.write[3] = barr[i * 4 + 3]; v.bones = b; } if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); w.write[0] = warr[i * 4 + 0]; w.write[1] = warr[i * 4 + 1]; w.write[2] = warr[i * 4 + 2]; w.write[3] = warr[i * 4 + 3]; v.weights = w; } ret.push_back(v); } return ret; }
PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_array) { PoolVector<PoolVector<Face3> > objects; int len = p_array.size(); PoolVector<Face3>::Read r = p_array.read(); const Face3 *arrayptr = r.ptr(); PoolVector<_FaceClassify> fc; fc.resize(len); PoolVector<_FaceClassify>::Write fcw = fc.write(); _FaceClassify *_fcptr = fcw.ptr(); for (int i = 0; i < len; i++) { _fcptr[i].face = arrayptr[i]; } bool error = _connect_faces(_fcptr, len, -1); if (error) { ERR_FAIL_COND_V(error, PoolVector<PoolVector<Face3> >()); // invalid geometry } /* group connected faces in separate objects */ int group = 0; for (int i = 0; i < len; i++) { if (!_fcptr[i].valid) continue; if (_group_face(_fcptr, len, i, group)) { group++; } } /* group connected faces in separate objects */ for (int i = 0; i < len; i++) { _fcptr[i].face = arrayptr[i]; } if (group >= 0) { objects.resize(group); PoolVector<PoolVector<Face3> >::Write obw = objects.write(); PoolVector<Face3> *group_faces = obw.ptr(); for (int i = 0; i < len; i++) { if (!_fcptr[i].valid) continue; if (_fcptr[i].group >= 0 && _fcptr[i].group < group) { group_faces[_fcptr[i].group].push_back(_fcptr[i].face); } } } return objects; }
PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_error) { #define _MIN_SIZE 1.0 #define _MAX_LENGTH 20 int face_count = p_array.size(); PoolVector<Face3>::Read facesr = p_array.read(); const Face3 *faces = facesr.ptr(); Rect3 global_aabb; for (int i = 0; i < face_count; i++) { if (i == 0) { global_aabb = faces[i].get_aabb(); } else { global_aabb.merge_with(faces[i].get_aabb()); } } global_aabb.grow_by(0.01); // avoid numerical error // determine amount of cells in grid axis int div_x, div_y, div_z; if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH) div_x = (int)(global_aabb.size.x / _MIN_SIZE) + 1; else div_x = _MAX_LENGTH; if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH) div_y = (int)(global_aabb.size.y / _MIN_SIZE) + 1; else div_y = _MAX_LENGTH; if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH) div_z = (int)(global_aabb.size.z / _MIN_SIZE) + 1; else div_z = _MAX_LENGTH; Vector3 voxelsize = global_aabb.size; voxelsize.x /= div_x; voxelsize.y /= div_y; voxelsize.z /= div_z; // create and initialize cells to zero //print_line("Wrapper: Initializing Cells"); uint8_t ***cell_status = memnew_arr(uint8_t **, div_x); for (int i = 0; i < div_x; i++) { cell_status[i] = memnew_arr(uint8_t *, div_y); for (int j = 0; j < div_y; j++) { cell_status[i][j] = memnew_arr(uint8_t, div_z); for (int k = 0; k < div_z; k++) { cell_status[i][j][k] = 0; } } } // plot faces into cells //print_line("Wrapper (1/6): Plotting Faces"); for (int i = 0; i < face_count; i++) { Face3 f = faces[i]; for (int j = 0; j < 3; j++) { f.vertex[j] -= global_aabb.pos; } _plot_face(cell_status, 0, 0, 0, div_x, div_y, div_z, voxelsize, f); } // determine which cells connect to the outside by traversing the outside and recursively flood-fill marking //print_line("Wrapper (2/6): Flood Filling"); for (int i = 0; i < div_x; i++) { for (int j = 0; j < div_y; j++) { _mark_outside(cell_status, i, j, 0, div_x, div_y, div_z); _mark_outside(cell_status, i, j, div_z - 1, div_x, div_y, div_z); } } for (int i = 0; i < div_z; i++) { for (int j = 0; j < div_y; j++) { _mark_outside(cell_status, 0, j, i, div_x, div_y, div_z); _mark_outside(cell_status, div_x - 1, j, i, div_x, div_y, div_z); } } for (int i = 0; i < div_x; i++) { for (int j = 0; j < div_z; j++) { _mark_outside(cell_status, i, 0, j, div_x, div_y, div_z); _mark_outside(cell_status, i, div_y - 1, j, div_x, div_y, div_z); } } // build faces for the inside-outside cell divisors //print_line("Wrapper (3/6): Building Faces"); PoolVector<Face3> wrapped_faces; for (int i = 0; i < div_x; i++) { for (int j = 0; j < div_y; j++) { for (int k = 0; k < div_z; k++) { _build_faces(cell_status, i, j, k, div_x, div_y, div_z, wrapped_faces); } } } //print_line("Wrapper (4/6): Transforming Back Vertices"); // transform face vertices to global coords int wrapped_faces_count = wrapped_faces.size(); PoolVector<Face3>::Write wrapped_facesw = wrapped_faces.write(); Face3 *wrapped_faces_ptr = wrapped_facesw.ptr(); for (int i = 0; i < wrapped_faces_count; i++) { for (int j = 0; j < 3; j++) { Vector3 &v = wrapped_faces_ptr[i].vertex[j]; v = v * voxelsize; v += global_aabb.pos; } } // clean up grid //print_line("Wrapper (5/6): Grid Cleanup"); for (int i = 0; i < div_x; i++) { for (int j = 0; j < div_y; j++) { memdelete_arr(cell_status[i][j]); } memdelete_arr(cell_status[i]); } memdelete_arr(cell_status); if (p_error) *p_error = voxelsize.length(); //print_line("Wrapper (6/6): Finished."); return wrapped_faces; }
Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &flags, Ref<Image> &image, int p_size_limit) { ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); uint8_t header[4]; f->get_buffer(header, 4); if (header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T') { memdelete(f); ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T', ERR_FILE_CORRUPT); } tw = f->get_32(); th = f->get_32(); flags = f->get_32(); //texture flags! uint32_t df = f->get_32(); //data format /* print_line("width: " + itos(tw)); print_line("height: " + itos(th)); print_line("flags: " + itos(flags)); print_line("df: " + itos(df)); */ #ifdef TOOLS_ENABLED if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) { //print_line("request detect 3D at " + p_path); VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); } else { //print_line("not requesting detect 3D at " + p_path); VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); } if (request_srgb_callback && df & FORMAT_BIT_DETECT_SRGB) { //print_line("request detect srgb at " + p_path); VS::get_singleton()->texture_set_detect_srgb_callback(texture, _requested_srgb, this); } else { //print_line("not requesting detect srgb at " + p_path); VS::get_singleton()->texture_set_detect_srgb_callback(texture, NULL, NULL); } if (request_srgb_callback && df & FORMAT_BIT_DETECT_NORMAL) { //print_line("request detect srgb at " + p_path); VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); } else { //print_line("not requesting detect normal at " + p_path); VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); } #endif if (!(df & FORMAT_BIT_STREAM)) { p_size_limit = 0; } if (df & FORMAT_BIT_LOSSLESS || df & FORMAT_BIT_LOSSY) { //look for a PNG or WEBP file inside int sw = tw; int sh = th; uint32_t mipmaps = f->get_32(); uint32_t size = f->get_32(); //print_line("mipmaps: " + itos(mipmaps)); while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { f->seek(f->get_position() + size); mipmaps = f->get_32(); size = f->get_32(); sw = MAX(sw >> 1, 1); sh = MAX(sh >> 1, 1); mipmaps--; } //mipmaps need to be read independently, they will be later combined Vector<Ref<Image> > mipmap_images; int total_size = 0; for (uint32_t i = 0; i < mipmaps; i++) { if (i) { size = f->get_32(); } PoolVector<uint8_t> pv; pv.resize(size); { PoolVector<uint8_t>::Write w = pv.write(); f->get_buffer(w.ptr(), size); } Ref<Image> img; if (df & FORMAT_BIT_LOSSLESS) { img = Image::lossless_unpacker(pv); } else { img = Image::lossy_unpacker(pv); } if (img.is_null() || img->empty()) { memdelete(f); ERR_FAIL_COND_V(img.is_null() || img->empty(), ERR_FILE_CORRUPT); } total_size += img->get_data().size(); mipmap_images.push_back(img); } //print_line("mipmap read total: " + itos(mipmap_images.size())); memdelete(f); //no longer needed if (mipmap_images.size() == 1) { image = mipmap_images[0]; return OK; } else { PoolVector<uint8_t> img_data; img_data.resize(total_size); { PoolVector<uint8_t>::Write w = img_data.write(); int ofs = 0; for (int i = 0; i < mipmap_images.size(); i++) { PoolVector<uint8_t> id = mipmap_images[i]->get_data(); int len = id.size(); PoolVector<uint8_t>::Read r = id.read(); copymem(&w[ofs], r.ptr(), len); ofs += len; } } image->create(sw, sh, true, mipmap_images[0]->get_format(), img_data); return OK; } } else {
bool GridMap::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name == "theme") { set_theme(p_value); } else if (name == "cell_size") { set_cell_size(p_value); } else if (name == "cell_octant_size") { set_octant_size(p_value); } else if (name == "cell_center_x") { set_center_x(p_value); } else if (name == "cell_center_y") { set_center_y(p_value); } else if (name == "cell_center_z") { set_center_z(p_value); } else if (name == "cell_scale") { set_cell_scale(p_value); /* } else if (name=="cells") { PoolVector<int> cells = p_value; int amount=cells.size(); PoolVector<int>::Read r = cells.read(); ERR_FAIL_COND_V(amount&1,false); // not even cell_map.clear(); for(int i=0;i<amount/3;i++) { IndexKey ik; ik.key=decode_uint64(&r[i*3]); Cell cell; cell.cell=uint32_t(r[i*+1]); cell_map[ik]=cell; } _recreate_octant_data();*/ } else if (name == "data") { Dictionary d = p_value; if (d.has("cells")) { PoolVector<int> cells = d["cells"]; int amount = cells.size(); PoolVector<int>::Read r = cells.read(); ERR_FAIL_COND_V(amount % 3, false); // not even cell_map.clear(); for (int i = 0; i < amount / 3; i++) { IndexKey ik; ik.key = decode_uint64((const uint8_t *)&r[i * 3]); Cell cell; cell.cell = decode_uint32((const uint8_t *)&r[i * 3 + 2]); cell_map[ik] = cell; } } _recreate_octant_data(); } else if (name.begins_with("areas/")) { int which = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); if (what == "bounds") { ERR_FAIL_COND_V(area_map.has(which), false); create_area(which, p_value); return true; } ERR_FAIL_COND_V(!area_map.has(which), false); if (what == "name") area_set_name(which, p_value); else if (what == "disable_distance") area_set_portal_disable_distance(which, p_value); else if (what == "exterior_portal") area_set_portal_disable_color(which, p_value); else return false; } else return false; return true; }
Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { AudioStreamSample::Format dst_format = format; bool stereo = true; //forcing mono is not implemented PoolVector<uint8_t> dst_data; if (dst_format == AudioStreamSample::FORMAT_8_BITS) { int data_size = current_instance->recording_data.size(); dst_data.resize(data_size); PoolVector<uint8_t>::Write w = dst_data.write(); for (int i = 0; i < data_size; i++) { int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127); w[i] = v; } } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) { int data_size = current_instance->recording_data.size(); dst_data.resize(data_size * 2); PoolVector<uint8_t>::Write w = dst_data.write(); for (int i = 0; i < data_size; i++) { int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767); encode_uint16(v, &w[i * 2]); } } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) { //byte interleave Vector<float> left; Vector<float> right; int tframes = current_instance->recording_data.size() / 2; left.resize(tframes); right.resize(tframes); for (int i = 0; i < tframes; i++) { left.set(i, current_instance->recording_data[i * 2 + 0]); right.set(i, current_instance->recording_data[i * 2 + 1]); } PoolVector<uint8_t> bleft; PoolVector<uint8_t> bright; ResourceImporterWAV::_compress_ima_adpcm(left, bleft); ResourceImporterWAV::_compress_ima_adpcm(right, bright); int dl = bleft.size(); dst_data.resize(dl * 2); PoolVector<uint8_t>::Write w = dst_data.write(); PoolVector<uint8_t>::Read rl = bleft.read(); PoolVector<uint8_t>::Read rr = bright.read(); for (int i = 0; i < dl; i++) { w[i * 2 + 0] = rl[i]; w[i * 2 + 1] = rr[i]; } } else { ERR_PRINT("Format not implemented."); } Ref<AudioStreamSample> sample; sample.instance(); sample->set_data(dst_data); sample->set_format(dst_format); sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate()); sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED); sample->set_loop_begin(0); sample->set_loop_end(0); sample->set_stereo(stereo); return sample; }
void NavigationPolygon::make_polygons_from_outlines() { List<TriangulatorPoly> in_poly, out_poly; Vector2 outside_point(-1e10, -1e10); for (int i = 0; i < outlines.size(); i++) { PoolVector<Vector2> ol = outlines[i]; int olsize = ol.size(); if (olsize < 3) continue; PoolVector<Vector2>::Read r = ol.read(); for (int j = 0; j < olsize; j++) { outside_point.x = MAX(r[j].x, outside_point.x); outside_point.y = MAX(r[j].y, outside_point.y); } } outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues for (int i = 0; i < outlines.size(); i++) { PoolVector<Vector2> ol = outlines[i]; int olsize = ol.size(); if (olsize < 3) continue; PoolVector<Vector2>::Read r = ol.read(); int interscount = 0; //test if this is an outer outline for (int k = 0; k < outlines.size(); k++) { if (i == k) continue; //no self intersect PoolVector<Vector2> ol2 = outlines[k]; int olsize2 = ol2.size(); if (olsize2 < 3) continue; PoolVector<Vector2>::Read r2 = ol2.read(); for (int l = 0; l < olsize2; l++) { if (Geometry::segment_intersects_segment_2d(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], NULL)) { interscount++; } } } bool outer = (interscount % 2) == 0; TriangulatorPoly tp; tp.Init(olsize); for (int j = 0; j < olsize; j++) { tp[j] = r[j]; } if (outer) tp.SetOrientation(TRIANGULATOR_CCW); else { tp.SetOrientation(TRIANGULATOR_CW); tp.SetHole(true); } in_poly.push_back(tp); } TriangulatorPartition tpart; if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed! print_line("convex partition failed!"); return; } polygons.clear(); vertices.resize(0); Map<Vector2, int> points; for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { TriangulatorPoly &tp = I->get(); struct Polygon p; for (int i = 0; i < tp.GetNumPoints(); i++) { Map<Vector2, int>::Element *E = points.find(tp[i]); if (!E) { E = points.insert(tp[i], vertices.size()); vertices.push_back(tp[i]); } p.indices.push_back(E->get()); } polygons.push_back(p); } emit_signal(CoreStringNames::get_singleton()->changed); }
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]; PoolVector<Vector3> narr = arr[VS::ARRAY_NORMAL]; PoolVector<float> tarr = arr[VS::ARRAY_TANGENT]; PoolVector<Color> carr = arr[VS::ARRAY_COLOR]; PoolVector<Vector2> uvarr = arr[VS::ARRAY_TEX_UV]; PoolVector<Vector2> uv2arr = arr[VS::ARRAY_TEX_UV2]; PoolVector<int> barr = arr[VS::ARRAY_BONES]; PoolVector<float> warr = arr[VS::ARRAY_WEIGHTS]; int vc = varr.size(); if (vc == 0) return; 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.write[0] = barr[i * 4 + 0]; b.write[1] = barr[i * 4 + 1]; b.write[2] = barr[i * 4 + 2]; b.write[3] = barr[i * 4 + 3]; v.bones = b; } if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); w.write[0] = warr[i * 4 + 0]; w.write[1] = warr[i * 4 + 1]; w.write[2] = warr[i * 4 + 2]; w.write[3] = warr[i * 4 + 3]; v.weights = w; } r_vertex->push_back(v); } //indices PoolVector<int> idx = arr[VS::ARRAY_INDEX]; int is = idx.size(); if (is) { lformat |= VS::ARRAY_FORMAT_INDEX; PoolVector<int>::Read iarr = idx.read(); for (int i = 0; i < is; i++) { r_index->push_back(iarr[i]); } } }
void NavigationPolygonInstance::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { Node2D *c = this; while (c) { navigation = Object::cast_to<Navigation2D>(c); if (navigation) { if (enabled && navpoly.is_valid()) { nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); } break; } c = Object::cast_to<Node2D>(c->get_parent()); } } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (navigation && nav_id != -1) { navigation->navpoly_set_transform(nav_id, get_relative_transform_to_parent(navigation)); } } break; case NOTIFICATION_EXIT_TREE: { if (navigation) { if (nav_id != -1) { navigation->navpoly_remove(nav_id); nav_id = -1; } } navigation = NULL; } break; case NOTIFICATION_DRAW: { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) { PoolVector<Vector2> verts = navpoly->get_vertices(); int vsize = verts.size(); if (vsize < 3) return; Color color; if (enabled) { color = get_tree()->get_debug_navigation_color(); } else { color = get_tree()->get_debug_navigation_disabled_color(); } Vector<Color> colors; Vector<Vector2> vertices; vertices.resize(vsize); colors.resize(vsize); { PoolVector<Vector2>::Read vr = verts.read(); for (int i = 0; i < vsize; i++) { vertices[i] = vr[i]; colors[i] = color; } } Vector<int> indices; for (int i = 0; i < navpoly->get_polygon_count(); i++) { Vector<int> polygon = navpoly->get_polygon(i); for (int j = 2; j < polygon.size(); j++) { int kofs[3] = { 0, j - 1, j }; for (int k = 0; k < 3; k++) { int idx = polygon[kofs[k]]; ERR_FAIL_INDEX(idx, vsize); indices.push_back(idx); } } } VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors); } } break; } }
void SpriteEditor::_create_uv_lines() { Ref<Mesh> sprite = node->get_sprite(); ERR_FAIL_COND(!sprite.is_valid()); Set<SpriteEditorEdgeSort> edges; uv_lines.clear(); for (int i = 0; i < sprite->get_surface_count(); i++) { if (sprite->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) continue; Array a = sprite->surface_get_arrays(i); PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2]; if (uv.size() == 0) { err_dialog->set_text(TTR("Model has no UV in this layer")); err_dialog->popup_centered_minsize(); return; } PoolVector<Vector2>::Read r = uv.read(); PoolVector<int> indices = a[Mesh::ARRAY_INDEX]; PoolVector<int>::Read ri; int ic; bool use_indices; if (indices.size()) { ic = indices.size(); ri = indices.read(); use_indices = true; } else { ic = uv.size(); use_indices = false; } for (int j = 0; j < ic; j += 3) { for (int k = 0; k < 3; k++) { SpriteEditorEdgeSort edge; if (use_indices) { edge.a = r[ri[j + k]]; edge.b = r[ri[j + ((k + 1) % 3)]]; } else { edge.a = r[j + k]; edge.b = r[j + ((k + 1) % 3)]; } if (edges.has(edge)) continue; uv_lines.push_back(edge.a); uv_lines.push_back(edge.b); edges.insert(edge); } } } debug_uv_dialog->popup_centered_minsize(); }
void CPUParticles2DEditorPlugin::_generate_emission_mask() { Ref<Image> img; img.instance(); Error err = ImageLoader::load_image(source_emission_file, img); ERR_EXPLAIN(TTR("Error loading image:") + " " + source_emission_file); ERR_FAIL_COND(err != OK); if (img->is_compressed()) { img->decompress(); } img->convert(Image::FORMAT_RGBA8); ERR_FAIL_COND(img->get_format() != Image::FORMAT_RGBA8); Size2i s = Size2(img->get_width(), img->get_height()); ERR_FAIL_COND(s.width == 0 || s.height == 0); Vector<Point2> valid_positions; Vector<Point2> valid_normals; Vector<uint8_t> valid_colors; valid_positions.resize(s.width * s.height); EmissionMode emode = (EmissionMode)emission_mask_mode->get_selected(); if (emode == EMISSION_MODE_BORDER_DIRECTED) { valid_normals.resize(s.width * s.height); } bool capture_colors = emission_colors->is_pressed(); if (capture_colors) { valid_colors.resize(s.width * s.height * 4); } int vpc = 0; { PoolVector<uint8_t> data = img->get_data(); PoolVector<uint8_t>::Read r = data.read(); for (int i = 0; i < s.width; i++) { for (int j = 0; j < s.height; j++) { uint8_t a = r[(j * s.width + i) * 4 + 3]; if (a > 128) { if (emode == EMISSION_MODE_SOLID) { if (capture_colors) { valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } valid_positions.write[vpc++] = Point2(i, j); } else { bool on_border = false; for (int x = i - 1; x <= i + 1; x++) { for (int y = j - 1; y <= j + 1; y++) { if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) { on_border = true; break; } } if (on_border) break; } if (on_border) { valid_positions.write[vpc] = Point2(i, j); if (emode == EMISSION_MODE_BORDER_DIRECTED) { Vector2 normal; for (int x = i - 2; x <= i + 2; x++) { for (int y = j - 2; y <= j + 2; y++) { if (x == i && y == j) continue; if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) { normal += Vector2(x - i, y - j).normalized(); } } } normal.normalize(); valid_normals.write[vpc] = normal; } if (capture_colors) { valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } vpc++; } } } } } } valid_positions.resize(vpc); if (valid_normals.size()) { valid_normals.resize(vpc); } ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image...")); ERR_FAIL_COND(valid_positions.size() == 0); if (capture_colors) { PoolColorArray pca; pca.resize(vpc); PoolColorArray::Write pcaw = pca.write(); for (int i = 0; i < vpc; i += 1) { Color color; color.r = valid_colors[i * 4 + 0] / 255.0f; color.g = valid_colors[i * 4 + 1] / 255.0f; color.b = valid_colors[i * 4 + 2] / 255.0f; color.a = valid_colors[i * 4 + 3] / 255.0f; pcaw[i] = color; } particles->set_emission_colors(pca); } if (valid_normals.size()) { particles->set_emission_shape(CPUParticles2D::EMISSION_SHAPE_DIRECTED_POINTS); PoolVector2Array norms; norms.resize(valid_normals.size()); PoolVector2Array::Write normsw = norms.write(); for (int i = 0; i < valid_normals.size(); i += 1) { normsw[i] = valid_normals[i]; } particles->set_emission_normals(norms); } else { particles->set_emission_shape(CPUParticles2D::EMISSION_SHAPE_POINTS); } { PoolVector2Array points; points.resize(valid_positions.size()); PoolVector2Array::Write pointsw = points.write(); for (int i = 0; i < valid_positions.size(); i += 1) { pointsw[i] = valid_positions[i]; } particles->set_emission_points(points); } }
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) { uint8_t *buf = r_buffer; r_len = 0; uint32_t flags = 0; switch (p_variant.get_type()) { case Variant::INT: { int64_t val = p_variant; if (val > 0x7FFFFFFF || val < -0x80000000) { flags |= ENCODE_FLAG_64; } } break; case Variant::REAL: { double d = p_variant; float f = d; if (double(f) != d) { flags |= ENCODE_FLAG_64; //always encode real as double } } break; } if (buf) { encode_uint32(p_variant.get_type() | flags, buf); buf += 4; } r_len += 4; switch (p_variant.get_type()) { case Variant::NIL: { //nothing to do } break; case Variant::BOOL: { if (buf) { encode_uint32(p_variant.operator bool(), buf); } r_len += 4; } break; case Variant::INT: { int64_t val = p_variant; if (val > 0x7FFFFFFF || val < -0x80000000) { //64 bits if (buf) { encode_uint64(val, buf); } r_len += 8; } else { if (buf) { encode_uint32(int32_t(val), buf); } r_len += 4; } } break; case Variant::REAL: { double d = p_variant; float f = d; if (double(f) != d) { if (buf) { encode_double(p_variant.operator double(), buf); } r_len += 8; } else { if (buf) { encode_float(p_variant.operator float(), buf); } r_len += 4; } } break; case Variant::NODE_PATH: { NodePath np = p_variant; if (buf) { encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format encode_uint32(np.get_subname_count(), buf + 4); uint32_t flags = 0; if (np.is_absolute()) flags |= 1; if (np.get_property() != StringName()) flags |= 2; encode_uint32(flags, buf + 8); buf += 12; } r_len += 12; int total = np.get_name_count() + np.get_subname_count(); if (np.get_property() != StringName()) total++; for (int i = 0; i < total; i++) { String str; if (i < np.get_name_count()) str = np.get_name(i); else if (i < np.get_name_count() + np.get_subname_count()) str = np.get_subname(i - np.get_subname_count()); else str = np.get_property(); CharString utf8 = str.utf8(); int pad = 0; if (utf8.length() % 4) pad = 4 - utf8.length() % 4; if (buf) { encode_uint32(utf8.length(), buf); buf += 4; copymem(buf, utf8.get_data(), utf8.length()); buf += pad + utf8.length(); } r_len += 4 + utf8.length() + pad; } } break; case Variant::STRING: { CharString utf8 = p_variant.operator String().utf8(); if (buf) { encode_uint32(utf8.length(), buf); buf += 4; copymem(buf, utf8.get_data(), utf8.length()); } r_len += 4 + utf8.length(); while (r_len % 4) r_len++; //pad } break; // math types case Variant::VECTOR2: { if (buf) { Vector2 v2 = p_variant; encode_float(v2.x, &buf[0]); encode_float(v2.y, &buf[4]); } r_len += 2 * 4; } break; // 5 case Variant::RECT2: { if (buf) { Rect2 r2 = p_variant; encode_float(r2.position.x, &buf[0]); encode_float(r2.position.y, &buf[4]); encode_float(r2.size.x, &buf[8]); encode_float(r2.size.y, &buf[12]); } r_len += 4 * 4; } break; case Variant::VECTOR3: { if (buf) { Vector3 v3 = p_variant; encode_float(v3.x, &buf[0]); encode_float(v3.y, &buf[4]); encode_float(v3.z, &buf[8]); } r_len += 3 * 4; } break; case Variant::TRANSFORM2D: { if (buf) { Transform2D val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { copymem(&buf[(i * 2 + j) * 4], &val.elements[i][j], sizeof(float)); } } } r_len += 6 * 4; } break; case Variant::PLANE: { if (buf) { Plane p = p_variant; encode_float(p.normal.x, &buf[0]); encode_float(p.normal.y, &buf[4]); encode_float(p.normal.z, &buf[8]); encode_float(p.d, &buf[12]); } r_len += 4 * 4; } break; case Variant::QUAT: { if (buf) { Quat q = p_variant; encode_float(q.x, &buf[0]); encode_float(q.y, &buf[4]); encode_float(q.z, &buf[8]); encode_float(q.w, &buf[12]); } r_len += 4 * 4; } break; case Variant::RECT3: { if (buf) { Rect3 aabb = p_variant; encode_float(aabb.position.x, &buf[0]); encode_float(aabb.position.y, &buf[4]); encode_float(aabb.position.z, &buf[8]); encode_float(aabb.size.x, &buf[12]); encode_float(aabb.size.y, &buf[16]); encode_float(aabb.size.z, &buf[20]); } r_len += 6 * 4; } break; case Variant::BASIS: { if (buf) { Basis val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { copymem(&buf[(i * 3 + j) * 4], &val.elements[i][j], sizeof(float)); } } } r_len += 9 * 4; } break; case Variant::TRANSFORM: { if (buf) { Transform val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { copymem(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float)); } } encode_float(val.origin.x, &buf[36]); encode_float(val.origin.y, &buf[40]); encode_float(val.origin.z, &buf[44]); } r_len += 12 * 4; } break; // misc types case Variant::COLOR: { if (buf) { Color c = p_variant; encode_float(c.r, &buf[0]); encode_float(c.g, &buf[4]); encode_float(c.b, &buf[8]); encode_float(c.a, &buf[12]); } r_len += 4 * 4; } break; /*case Variant::RESOURCE: { ERR_EXPLAIN("Can't marshallize resources"); ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go } break;*/ case Variant::_RID: case Variant::OBJECT: { } break; case Variant::DICTIONARY: { Dictionary d = p_variant; if (buf) { encode_uint32(uint32_t(d.size()), buf); buf += 4; } r_len += 4; List<Variant> keys; d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { /* CharString utf8 = E->->utf8(); if (buf) { encode_uint32(utf8.length()+1,buf); buf+=4; copymem(buf,utf8.get_data(),utf8.length()+1); } r_len+=4+utf8.length()+1; while (r_len%4) r_len++; //pad */ int len; encode_variant(E->get(), buf, len); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) buf += len; encode_variant(d[E->get()], buf, len); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) buf += len; } } break; case Variant::ARRAY: { Array v = p_variant; if (buf) { encode_uint32(uint32_t(v.size()), buf); buf += 4; } r_len += 4; for (int i = 0; i < v.size(); i++) { int len; encode_variant(v.get(i), buf, len); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) buf += len; } } break; // arrays case Variant::POOL_BYTE_ARRAY: { PoolVector<uint8_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(uint8_t); if (buf) { encode_uint32(datalen, buf); buf += 4; PoolVector<uint8_t>::Read r = data.read(); copymem(buf, &r[0], datalen * datasize); } r_len += 4 + datalen * datasize; while (r_len % 4) r_len++; } break; case Variant::POOL_INT_ARRAY: { PoolVector<int> data = p_variant; int datalen = data.size(); int datasize = sizeof(int32_t); if (buf) { encode_uint32(datalen, buf); buf += 4; PoolVector<int>::Read r = data.read(); for (int i = 0; i < datalen; i++) encode_uint32(r[i], &buf[i * datasize]); } r_len += 4 + datalen * datasize; } break; case Variant::POOL_REAL_ARRAY: { PoolVector<real_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(real_t); if (buf) { encode_uint32(datalen, buf); buf += 4; PoolVector<real_t>::Read r = data.read(); for (int i = 0; i < datalen; i++) encode_float(r[i], &buf[i * datasize]); } r_len += 4 + datalen * datasize; } break; case Variant::POOL_STRING_ARRAY: { PoolVector<String> data = p_variant; int len = data.size(); if (buf) { encode_uint32(len, buf); buf += 4; } r_len += 4; for (int i = 0; i < len; i++) { CharString utf8 = data.get(i).utf8(); if (buf) { encode_uint32(utf8.length() + 1, buf); buf += 4; copymem(buf, utf8.get_data(), utf8.length() + 1); buf += utf8.length() + 1; } r_len += 4 + utf8.length() + 1; while (r_len % 4) { r_len++; //pad if (buf) buf++; } } } break; case Variant::POOL_VECTOR2_ARRAY: { PoolVector<Vector2> data = p_variant; int len = data.size(); if (buf) { encode_uint32(len, buf); buf += 4; } r_len += 4; if (buf) { for (int i = 0; i < len; i++) { Vector2 v = data.get(i); encode_float(v.x, &buf[0]); encode_float(v.y, &buf[4]); buf += 4 * 2; } } r_len += 4 * 2 * len; } break; case Variant::POOL_VECTOR3_ARRAY: { PoolVector<Vector3> data = p_variant; int len = data.size(); if (buf) { encode_uint32(len, buf); buf += 4; } r_len += 4; if (buf) { for (int i = 0; i < len; i++) { Vector3 v = data.get(i); encode_float(v.x, &buf[0]); encode_float(v.y, &buf[4]); encode_float(v.z, &buf[8]); buf += 4 * 3; } } r_len += 4 * 3 * len; } break; case Variant::POOL_COLOR_ARRAY: { PoolVector<Color> data = p_variant; int len = data.size(); if (buf) { encode_uint32(len, buf); buf += 4; } r_len += 4; if (buf) { for (int i = 0; i < len; i++) { Color c = data.get(i); encode_float(c.r, &buf[0]); encode_float(c.g, &buf[4]); encode_float(c.b, &buf[8]); encode_float(c.a, &buf[12]); buf += 4 * 4; } } r_len += 4 * 4 * len; } break; default: { ERR_FAIL_V(ERR_BUG); } } return OK; }
void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal) { print_line("saving: " + p_to_path); FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); f->store_8('G'); f->store_8('D'); f->store_8('S'); f->store_8('T'); //godot streamable texture f->store_32(p_image->get_width()); f->store_32(p_image->get_height()); f->store_32(p_texture_flags); uint32_t format = 0; if (p_streamable) format |= StreamTexture::FORMAT_BIT_STREAM; if (p_mipmaps || p_compress_mode == COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps format |= StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit if (p_detect_3d) format |= StreamTexture::FORMAT_BIT_DETECT_3D; if (p_detect_srgb) format |= StreamTexture::FORMAT_BIT_DETECT_SRGB; if (p_detect_normal) format |= StreamTexture::FORMAT_BIT_DETECT_NORMAL; if ((p_compress_mode == COMPRESS_LOSSLESS || p_compress_mode == COMPRESS_LOSSY) && p_image->get_format() > Image::FORMAT_RGBA8) { p_compress_mode == COMPRESS_UNCOMPRESSED; //these can't go as lossy } switch (p_compress_mode) { case COMPRESS_LOSSLESS: { Ref<Image> image = p_image->duplicate(); if (p_mipmaps) { image->generate_mipmaps(); } else { image->clear_mipmaps(); } int mmc = image->get_mipmap_count() + 1; format |= StreamTexture::FORMAT_BIT_LOSSLESS; f->store_32(format); f->store_32(mmc); for (int i = 0; i < mmc; i++) { if (i > 0) { image->shrink_x2(); } PoolVector<uint8_t> data = Image::lossless_packer(image); int data_len = data.size(); f->store_32(data_len); PoolVector<uint8_t>::Read r = data.read(); f->store_buffer(r.ptr(), data_len); } } break; case COMPRESS_LOSSY: { Ref<Image> image = p_image->duplicate(); if (p_mipmaps) { image->generate_mipmaps(); } else { image->clear_mipmaps(); } int mmc = image->get_mipmap_count() + 1; format |= StreamTexture::FORMAT_BIT_LOSSY; f->store_32(format); f->store_32(mmc); for (int i = 0; i < mmc; i++) { if (i > 0) { image->shrink_x2(); } PoolVector<uint8_t> data = Image::lossy_packer(image, p_lossy_quality); int data_len = data.size(); f->store_32(data_len); PoolVector<uint8_t>::Read r = data.read(); f->store_buffer(r.ptr(), data_len); } } break; case COMPRESS_VIDEO_RAM: { Ref<Image> image = p_image->duplicate(); image->generate_mipmaps(); if (p_force_rgbe && image->get_format() >= Image::FORMAT_R8 && image->get_format() <= Image::FORMAT_RGBE9995) { image->convert(Image::FORMAT_RGBE9995); } else { Image::CompressSource csource = Image::COMPRESS_SOURCE_GENERIC; if (p_force_normal) { csource = Image::COMPRESS_SOURCE_NORMAL; } else if (p_texture_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { csource = Image::COMPRESS_SOURCE_SRGB; } image->compress(p_vram_compression, csource, p_lossy_quality); } format |= image->get_format(); f->store_32(format); PoolVector<uint8_t> data = image->get_data(); int dl = data.size(); PoolVector<uint8_t>::Read r = data.read(); f->store_buffer(r.ptr(), dl); } break; case COMPRESS_UNCOMPRESSED: { Ref<Image> image = p_image->duplicate(); if (p_mipmaps) { image->generate_mipmaps(); } else { image->clear_mipmaps(); } format |= image->get_format(); f->store_32(format); PoolVector<uint8_t> data = image->get_data(); int dl = data.size(); PoolVector<uint8_t>::Read r = data.read(); f->store_buffer(r.ptr(), dl); } break; } memdelete(f); }
void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) { if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) return; //do not compress, already compressed int w = p_image->get_width(); int h = p_image->get_height(); bool is_ldr = (p_image->get_format() <= Image::FORMAT_RGBA8); bool is_hdr = (p_image->get_format() == Image::FORMAT_RGBH); if (!is_ldr && !is_hdr) { return; // Not a usable source format } cvtt::Options options; uint32_t flags = cvtt::Flags::Fastest; if (p_lossy_quality > 0.85) flags = cvtt::Flags::Ultra; else if (p_lossy_quality > 0.75) flags = cvtt::Flags::Better; else if (p_lossy_quality > 0.55) flags = cvtt::Flags::Default; else if (p_lossy_quality > 0.35) flags = cvtt::Flags::Fast; else if (p_lossy_quality > 0.15) flags = cvtt::Flags::Faster; flags |= cvtt::Flags::BC7_RespectPunchThrough; if (p_source == Image::COMPRESS_SOURCE_NORMAL) { flags |= cvtt::Flags::Uniform; } Image::Format target_format = Image::FORMAT_BPTC_RGBA; bool is_signed = false; if (is_hdr) { PoolVector<uint8_t>::Read rb = p_image->get_data().read(); const uint16_t *source_data = reinterpret_cast<const uint16_t *>(&rb[0]); int pixel_element_count = w * h * 3; for (int i = 0; i < pixel_element_count; i++) { if ((source_data[i] & 0x8000) != 0 && (source_data[i] & 0x7fff) != 0) { is_signed = true; break; } } target_format = is_signed ? Image::FORMAT_BPTC_RGBF : Image::FORMAT_BPTC_RGBFU; } else { p_image->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert } PoolVector<uint8_t>::Read rb = p_image->get_data().read(); PoolVector<uint8_t> data; int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps()); int mm_count = p_image->has_mipmaps() ? Image::get_image_required_mipmaps(w, h, target_format) : 0; data.resize(target_size); int shift = Image::get_format_pixel_rshift(target_format); PoolVector<uint8_t>::Write wb = data.write(); int dst_ofs = 0; CVTTCompressionJobQueue job_queue; job_queue.job_params.is_hdr = is_hdr; job_queue.job_params.is_signed = is_signed; job_queue.job_params.options = options; job_queue.job_params.bytes_per_pixel = is_hdr ? 6 : 4; #ifdef NO_THREADS int num_job_threads = 0; #else int num_job_threads = OS::get_singleton()->can_use_threads() ? (OS::get_singleton()->get_processor_count() - 1) : 0; #endif PoolVector<CVTTCompressionRowTask> tasks; for (int i = 0; i <= mm_count; i++) { int bw = w % 4 != 0 ? w + (4 - w % 4) : w; int bh = h % 4 != 0 ? h + (4 - h % 4) : h; int src_ofs = p_image->get_mipmap_offset(i); const uint8_t *in_bytes = &rb[src_ofs]; uint8_t *out_bytes = &wb[dst_ofs]; for (int y_start = 0; y_start < h; y_start += 4) { int y_end = y_start + 4; CVTTCompressionRowTask row_task; row_task.width = w; row_task.height = h; row_task.y_start = y_start; row_task.in_mm_bytes = in_bytes; row_task.out_mm_bytes = out_bytes; if (num_job_threads > 0) { tasks.push_back(row_task); } else { _digest_row_task(job_queue.job_params, row_task); } out_bytes += 16 * (bw / 4); } dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift; w = MAX(w / 2, 1); h = MAX(h / 2, 1); } if (num_job_threads > 0) { PoolVector<Thread *> threads; threads.resize(num_job_threads); PoolVector<Thread *>::Write threads_wb = threads.write(); PoolVector<CVTTCompressionRowTask>::Read tasks_rb = tasks.read(); job_queue.job_tasks = &tasks_rb[0]; job_queue.current_task = 0; job_queue.num_tasks = static_cast<uint32_t>(tasks.size()); for (int i = 0; i < num_job_threads; i++) { threads_wb[i] = Thread::create(_digest_job_queue, &job_queue); } _digest_job_queue(&job_queue); for (int i = 0; i < num_job_threads; i++) { Thread::wait_to_finish(threads_wb[i]); memdelete(threads_wb[i]); } } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); }
RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) { #define _RETURN(m_err)\ {\ if (r_error)\ *r_error=m_err;\ ERR_FAIL_V(RES());\ } FileAccessRef f=FileAccess::open(p_path,FileAccess::READ); uint8_t saved=0; if (!f) _RETURN(ERR_CANT_OPEN); PoolVector<uint8_t> token; if (!_get_token(f,saved,token)) { _RETURN(ERR_PARSE_ERROR); } if (token.size()!=2) { _RETURN(ERR_FILE_CORRUPT); } if (token[0]!='P') { _RETURN(ERR_FILE_CORRUPT); } if (token[1]!='1' && token[1]!='4') { _RETURN(ERR_FILE_CORRUPT); } bool bits = token[1]=='4'; if (!_get_token(f,saved,token)) { _RETURN(ERR_PARSE_ERROR); } int width = _get_number_from_token(token); if (width<=0) { _RETURN(ERR_FILE_CORRUPT); } if (!_get_token(f,saved,token)) { _RETURN(ERR_PARSE_ERROR); } int height = _get_number_from_token(token); if (height<=0) { _RETURN(ERR_FILE_CORRUPT); } Ref<BitMap> bm; bm.instance(); bm->create(Size2i(width,height)); if (!bits) { int required_bytes = width*height; if (!_get_token(f,saved,token,false,true)) { _RETURN(ERR_PARSE_ERROR); } if (token.size()<required_bytes) { _RETURN(ERR_FILE_CORRUPT); } PoolVector<uint8_t>::Read r=token.read(); for(int i=0;i<height;i++) { for(int j=0;j<width;j++) { char num = r[i*width+j]; bm->set_bit(Point2i(j,i),num=='0'); } } } else { //a single, entire token of bits! if (!_get_token(f,saved,token,true)) { _RETURN(ERR_PARSE_ERROR); } int required_bytes = Math::ceil((width*height)/8.0); if (token.size()<required_bytes) { _RETURN(ERR_FILE_CORRUPT); } PoolVector<uint8_t>::Read r=token.read(); int bitwidth = width; if (bitwidth % 8) bitwidth+=8-(bitwidth%8); for(int i=0;i<height;i++) { for(int j=0;j<width;j++) { int ofs = bitwidth*i+j; uint8_t byte = r[ofs/8]; bool bit = (byte>>(7-(ofs%8)))&1; bm->set_bit(Point2i(j,i),!bit); } } } return bm; }
void Particles2DEditorPlugin::_generate_emission_mask() { Ref<ParticlesMaterial> pm = particles->get_process_material(); if (!pm.is_valid()) { EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticlesMaterial process material")); return; } Ref<Image> img; img.instance(); Error err = ImageLoader::load_image(source_emission_file, img); ERR_EXPLAIN(TTR("Error loading image:") + " " + source_emission_file); ERR_FAIL_COND(err != OK); if (img->is_compressed()) { img->decompress(); } img->convert(Image::FORMAT_RGBA8); ERR_FAIL_COND(img->get_format() != Image::FORMAT_RGBA8); Size2i s = Size2(img->get_width(), img->get_height()); ERR_FAIL_COND(s.width == 0 || s.height == 0); Vector<Point2> valid_positions; Vector<Point2> valid_normals; Vector<uint8_t> valid_colors; valid_positions.resize(s.width * s.height); EmissionMode emode = (EmissionMode)emission_mask_mode->get_selected(); if (emode == EMISSION_MODE_BORDER_DIRECTED) { valid_normals.resize(s.width * s.height); } bool capture_colors = emission_colors->is_pressed(); if (capture_colors) { valid_colors.resize(s.width * s.height * 4); } int vpc = 0; { PoolVector<uint8_t> data = img->get_data(); PoolVector<uint8_t>::Read r = data.read(); for (int i = 0; i < s.width; i++) { for (int j = 0; j < s.height; j++) { uint8_t a = r[(j * s.width + i) * 4 + 3]; if (a > 128) { if (emode == EMISSION_MODE_SOLID) { if (capture_colors) { valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } valid_positions.write[vpc++] = Point2(i, j); } else { bool on_border = false; for (int x = i - 1; x <= i + 1; x++) { for (int y = j - 1; y <= j + 1; y++) { if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) { on_border = true; break; } } if (on_border) break; } if (on_border) { valid_positions.write[vpc] = Point2(i, j); if (emode == EMISSION_MODE_BORDER_DIRECTED) { Vector2 normal; for (int x = i - 2; x <= i + 2; x++) { for (int y = j - 2; y <= j + 2; y++) { if (x == i && y == j) continue; if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) { normal += Vector2(x - i, y - j).normalized(); } } } normal.normalize(); valid_normals.write[vpc] = normal; } if (capture_colors) { valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } vpc++; } } } } } } valid_positions.resize(vpc); if (valid_normals.size()) { valid_normals.resize(vpc); } ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image...")); ERR_FAIL_COND(valid_positions.size() == 0); PoolVector<uint8_t> texdata; int w = 2048; int h = (vpc / 2048) + 1; texdata.resize(w * h * 2 * sizeof(float)); { PoolVector<uint8_t>::Write tw = texdata.write(); float *twf = (float *)tw.ptr(); for (int i = 0; i < vpc; i++) { twf[i * 2 + 0] = valid_positions[i].x; twf[i * 2 + 1] = valid_positions[i].y; } } img.instance(); img->create(w, h, false, Image::FORMAT_RGF, texdata); Ref<ImageTexture> imgt; imgt.instance(); imgt->create_from_image(img, 0); pm->set_emission_point_texture(imgt); pm->set_emission_point_count(vpc); if (capture_colors) { PoolVector<uint8_t> colordata; colordata.resize(w * h * 4); //use RG texture { PoolVector<uint8_t>::Write tw = colordata.write(); for (int i = 0; i < vpc * 4; i++) { tw[i] = valid_colors[i]; } } img.instance(); img->create(w, h, false, Image::FORMAT_RGBA8, colordata); imgt.instance(); imgt->create_from_image(img, 0); pm->set_emission_color_texture(imgt); } if (valid_normals.size()) { pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); PoolVector<uint8_t> normdata; normdata.resize(w * h * 2 * sizeof(float)); //use RG texture { PoolVector<uint8_t>::Write tw = normdata.write(); float *twf = (float *)tw.ptr(); for (int i = 0; i < vpc; i++) { twf[i * 2 + 0] = valid_normals[i].x; twf[i * 2 + 1] = valid_normals[i].y; } } img.instance(); img->create(w, h, false, Image::FORMAT_RGF, normdata); imgt.instance(); imgt->create_from_image(img, 0); pm->set_emission_normal_texture(imgt); } else { pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); } }
void SoftBodyBullet::set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices) { /// Assert the current soft body is destroyed destroy_soft_body(); /// Parse visual server indices to physical indices. /// Merge all overlapping vertices and create a map of physical vertices to visual server { /// This is the map of visual server indices to physics indices (So it's the inverse of idices_map), Thanks to it I don't need make a heavy search in the indices_map Vector<int> vs_indices_to_physics_table; { // Map vertices indices_table.resize(0); int index = 0; Map<Vector3, int> unique_vertices; const int vs_vertices_size(p_vertices.size()); PoolVector<Vector3>::Read p_vertices_read = p_vertices.read(); for (int vs_vertex_index = 0; vs_vertex_index < vs_vertices_size; ++vs_vertex_index) { Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]); int vertex_id; if (e) { // Already rxisting vertex_id = e->value(); } else { // Create new one unique_vertices[p_vertices_read[vs_vertex_index]] = vertex_id = index++; indices_table.push_back(Vector<int>()); } indices_table.write[vertex_id].push_back(vs_vertex_index); vs_indices_to_physics_table.push_back(vertex_id); } } const int indices_map_size(indices_table.size()); Vector<btScalar> bt_vertices; { // Parse vertices to bullet bt_vertices.resize(indices_map_size * 3); PoolVector<Vector3>::Read p_vertices_read = p_vertices.read(); for (int i = 0; i < indices_map_size; ++i) { bt_vertices.write[3 * i + 0] = p_vertices_read[indices_table[i][0]].x; bt_vertices.write[3 * i + 1] = p_vertices_read[indices_table[i][0]].y; bt_vertices.write[3 * i + 2] = p_vertices_read[indices_table[i][0]].z; } } Vector<int> bt_triangles; const int triangles_size(p_indices.size() / 3); { // Parse indices bt_triangles.resize(triangles_size * 3); PoolVector<int>::Read p_indices_read = p_indices.read(); for (int i = 0; i < triangles_size; ++i) { bt_triangles.write[3 * i + 0] = vs_indices_to_physics_table[p_indices_read[3 * i + 2]]; bt_triangles.write[3 * i + 1] = vs_indices_to_physics_table[p_indices_read[3 * i + 1]]; bt_triangles.write[3 * i + 2] = vs_indices_to_physics_table[p_indices_read[3 * i + 0]]; } } btSoftBodyWorldInfo fake_world_info; bt_soft_body = btSoftBodyHelpers::CreateFromTriMesh(fake_world_info, &bt_vertices[0], &bt_triangles[0], triangles_size, false); setup_soft_body(); } }
void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); p_gizmo->clear(); Ref<Material> material = get_material("shape_material", p_gizmo); Ref<Material> handles_material = get_material("handles"); PoolVector<Vector3> faces = cs->get_brush_faces(); Vector<Vector3> lines; lines.resize(faces.size() * 2); { PoolVector<Vector3>::Read r = faces.read(); for (int i = 0; i < lines.size(); i += 6) { int f = i / 6; for (int j = 0; j < 3; j++) { int j_n = (j + 1) % 3; lines.write[i + j * 2 + 0] = r[f * 3 + j]; lines.write[i + j * 2 + 1] = r[f * 3 + j_n]; } } } p_gizmo->add_lines(lines, material); p_gizmo->add_collision_segments(lines); if (Object::cast_to<CSGSphere>(cs)) { CSGSphere *s = Object::cast_to<CSGSphere>(cs); float r = s->get_radius(); Vector<Vector3> handles; handles.push_back(Vector3(r, 0, 0)); p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CSGBox>(cs)) { CSGBox *s = Object::cast_to<CSGBox>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_width(), 0, 0)); handles.push_back(Vector3(0, s->get_height(), 0)); handles.push_back(Vector3(0, 0, s->get_depth())); p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CSGCylinder>(cs)) { CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_radius(), 0, 0)); handles.push_back(Vector3(0, s->get_height() * 0.5, 0)); p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CSGTorus>(cs)) { CSGTorus *s = Object::cast_to<CSGTorus>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_inner_radius(), 0, 0)); handles.push_back(Vector3(s->get_outer_radius(), 0, 0)); p_gizmo->add_handles(handles, handles_material); } }