summaryrefslogtreecommitdiffstats
path: root/scene/resources/mesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/mesh.cpp')
-rw-r--r--scene/resources/mesh.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 3aeccdc551..f4bb3088c3 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -743,6 +743,225 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
}
+Ref<Mesh> Mesh::create_outline(float p_margin) const {
+
+
+ Array arrays;
+ int index_accum=0;
+ for(int i=0;i<get_surface_count();i++) {
+
+ if (surface_get_primitive_type(i)!=PRIMITIVE_TRIANGLES)
+ continue;
+
+ Array a = surface_get_arrays(i);
+ int vcount=0;
+
+ if (i==0) {
+ arrays=a;
+ DVector<Vector3> v=a[ARRAY_VERTEX];
+ index_accum+=v.size();
+ } else {
+
+ for(int j=0;j<arrays.size();j++) {
+
+ if (arrays[j].get_type()==Variant::NIL || a[j].get_type()==Variant::NIL) {
+ //mismatch, do not use
+ arrays[j]=Variant();
+ continue;
+ }
+
+ switch(j) {
+
+ case ARRAY_VERTEX:
+ case ARRAY_NORMAL: {
+
+ DVector<Vector3> dst = arrays[j];
+ DVector<Vector3> src = a[j];
+ if (j==ARRAY_VERTEX)
+ vcount=src.size();
+ if (dst.size()==0 || src.size()==0) {
+ arrays[j]=Variant();
+ continue;
+ }
+ dst.append_array(src);
+ arrays[j]=dst;
+ } break;
+ case ARRAY_TANGENT:
+ case ARRAY_BONES:
+ case ARRAY_WEIGHTS: {
+
+ DVector<real_t> dst = arrays[j];
+ DVector<real_t> src = a[j];
+ if (dst.size()==0 || src.size()==0) {
+ arrays[j]=Variant();
+ continue;
+ }
+ dst.append_array(src);
+ arrays[j]=dst;
+
+ } break;
+ case ARRAY_COLOR: {
+ DVector<Color> dst = arrays[j];
+ DVector<Color> src = a[j];
+ if (dst.size()==0 || src.size()==0) {
+ arrays[j]=Variant();
+ continue;
+ }
+ dst.append_array(src);
+ arrays[j]=dst;
+
+ } break;
+ case ARRAY_TEX_UV:
+ case ARRAY_TEX_UV2: {
+ DVector<Vector2> dst = arrays[j];
+ DVector<Vector2> src = a[j];
+ if (dst.size()==0 || src.size()==0) {
+ arrays[j]=Variant();
+ continue;
+ }
+ dst.append_array(src);
+ arrays[j]=dst;
+
+ } break;
+ case ARRAY_INDEX: {
+ DVector<int> dst = arrays[j];
+ DVector<int> src = a[j];
+ if (dst.size()==0 || src.size()==0) {
+ arrays[j]=Variant();
+ continue;
+ }
+ {
+ int ss = src.size();
+ DVector<int>::Write w = src.write();
+ for(int k=0;k<ss;k++) {
+ w[k]+=index_accum;
+ }
+
+ }
+ dst.append_array(src);
+ arrays[j]=dst;
+ index_accum+=vcount;
+
+ } break;
+
+ }
+ }
+ }
+ }
+
+ {
+ int tc=0;
+ DVector<int>::Write ir;
+ DVector<int> indices =arrays[ARRAY_INDEX];
+ bool has_indices=false;
+ DVector<Vector3> vertices =arrays[ARRAY_VERTEX];
+ int vc = vertices.size();
+ ERR_FAIL_COND_V(!vc,Ref<Mesh>());
+ DVector<Vector3>::Write r=vertices.write();
+
+
+ if (indices.size()) {
+ vc=indices.size();
+ ir=indices.write();
+ has_indices=true;
+ }
+
+ Map<Vector3,Vector3> normal_accum;
+
+ //fill normals with triangle normals
+ for(int i=0;i<vc;i+=3) {
+
+
+ Vector3 t[3];
+
+ if (has_indices) {
+ t[0]=r[ir[i+0]];
+ t[1]=r[ir[i+1]];
+ t[2]=r[ir[i+2]];
+ } else {
+ t[0]=r[i+0];
+ t[1]=r[i+1];
+ t[2]=r[i+2];
+ }
+
+ Vector3 n = Plane(t[0],t[1],t[2]).normal;
+
+ for(int j=0;j<3;j++) {
+
+ Map<Vector3,Vector3>::Element *E=normal_accum.find(t[j]);
+ if (!E) {
+ normal_accum[t[j]]=n;
+ } else {
+ float d = n.dot(E->get());
+ if (d<1.0)
+ E->get()+=n*(1.0-d);
+ //E->get()+=n;
+ }
+ }
+ }
+
+ //normalize
+
+ for (Map<Vector3,Vector3>::Element *E=normal_accum.front();E;E=E->next()) {
+ E->get().normalize();
+ }
+
+
+ //displace normals
+ int vc2 = vertices.size();
+
+ for(int i=0;i<vc2;i++) {
+
+
+ Vector3 t=r[i];
+
+ Map<Vector3,Vector3>::Element *E=normal_accum.find(t);
+ ERR_CONTINUE(!E);
+
+ t+=E->get()*p_margin;
+ r[i]=t;
+ }
+
+ r = DVector<Vector3>::Write();
+ arrays[ARRAY_VERTEX]=vertices;
+
+ if (!has_indices) {
+
+ DVector<int> new_indices;
+ new_indices.resize(vertices.size());
+ DVector<int>::Write iw = new_indices.write();
+
+ for(int j=0;j<vc2;j+=3) {
+
+ iw[j]=j;
+ iw[j+1]=j+2;
+ iw[j+2]=j+1;
+ }
+
+ iw=DVector<int>::Write();
+ arrays[ARRAY_INDEX]=new_indices;
+
+ } else {
+
+ for(int j=0;j<vc;j+=3) {
+
+ SWAP(ir[j+1],ir[j+2]);
+ }
+ ir=DVector<int>::Write();
+ arrays[ARRAY_INDEX]=indices;
+
+ }
+ }
+
+
+
+
+ Ref<Mesh> newmesh = memnew( Mesh );
+ newmesh->add_surface(PRIMITIVE_TRIANGLES,arrays);
+ return newmesh;
+}
+
+
void Mesh::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_morph_target","name"),&Mesh::add_morph_target);