Browse Source

-Fixes to how collada generates tangents (use SurfaceTool), closes #9562
-Fix to gridmap cell size (wrong property type)

Juan Linietsky 8 years ago
parent
commit
a2027cfa49

+ 48 - 202
editor/import/editor_import_collada.cpp

@@ -41,6 +41,7 @@
 #include "scene/animation/animation_player.h"
 #include "scene/resources/animation.h"
 #include "scene/resources/packed_scene.h"
+#include "scene/resources/surface_tool.h"
 
 #include <iostream>
 
@@ -868,7 +869,6 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
 					int normal_pos = (normal_src->stride ? normal_src->stride : 3) * p.indices[src + normal_ofs];
 					ERR_FAIL_INDEX_V(normal_pos, normal_src->array.size(), ERR_INVALID_DATA);
 					vertex.normal = Vector3(normal_src->array[normal_pos + 0], normal_src->array[normal_pos + 1], normal_src->array[normal_pos + 2]);
-					vertex.normal.snap(Vector3(0.001, 0.001, 0.001));
 
 					if (tangent_src && binormal_src) {
 
@@ -991,18 +991,6 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
 			}
 		}
 
-		PoolVector<int> index_array;
-		index_array.resize(indices_list.size());
-		PoolVector<int>::Write index_arrayw = index_array.write();
-
-		int iidx = 0;
-		for (List<int>::Element *F = indices_list.front(); F; F = F->next()) {
-
-			index_arrayw[iidx++] = F->get();
-		}
-
-		index_arrayw = PoolVector<int>::Write();
-
 		/*****************/
 		/* MAKE SURFACES  */
 		/*****************/
@@ -1011,9 +999,6 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
 
 			Ref<SpatialMaterial> material;
 
-			//find material
-			Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
-
 			{
 
 				if (p_material_map.has(p.material)) {
@@ -1031,212 +1016,73 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
 				}
 			}
 
-			PoolVector<Vector3> final_vertex_array;
-			PoolVector<Vector3> final_normal_array;
-			PoolVector<float> final_tangent_array;
-			PoolVector<Color> final_color_array;
-			PoolVector<Vector3> final_uv_array;
-			PoolVector<Vector3> final_uv2_array;
-			PoolVector<int> final_bone_array;
-			PoolVector<float> final_weight_array;
-
-			uint32_t final_format = 0;
+			Ref<SurfaceTool> surftool;
+			surftool.instance();
+			surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
 
-			//create format
-			final_format = Mesh::ARRAY_FORMAT_VERTEX | Mesh::ARRAY_FORMAT_INDEX;
-
-			if (normal_src) {
-				final_format |= Mesh::ARRAY_FORMAT_NORMAL;
-				if (uv_src && binormal_src && tangent_src) {
-					final_format |= Mesh::ARRAY_FORMAT_TANGENT;
+			for (int k = 0; k < vertex_array.size(); k++) {
+				if (normal_src) {
+					surftool->add_normal(vertex_array[k].normal);
+					if (binormal_src && tangent_src) {
+						surftool->add_tangent(vertex_array[k].tangent);
+					}
 				}
-			}
-
-			if (color_src)
-				final_format |= Mesh::ARRAY_FORMAT_COLOR;
-			if (uv_src)
-				final_format |= Mesh::ARRAY_FORMAT_TEX_UV;
-			if (uv2_src)
-				final_format |= Mesh::ARRAY_FORMAT_TEX_UV2;
-
-			if (has_weights) {
-				final_format |= Mesh::ARRAY_FORMAT_WEIGHTS;
-				final_format |= Mesh::ARRAY_FORMAT_BONES;
-			}
-
-			//set arrays
-
-			int vlen = vertex_array.size();
-			{ //vertices
-
-				PoolVector<Vector3> varray;
-				varray.resize(vertex_array.size());
-
-				PoolVector<Vector3>::Write varrayw = varray.write();
-
-				for (int k = 0; k < vlen; k++)
-					varrayw[k] = vertex_array[k].vertex;
-
-				varrayw = PoolVector<Vector3>::Write();
-				final_vertex_array = varray;
-			}
-
-			if (uv_src) { //compute uv first, may be needed for computing tangent/bionrmal
-				PoolVector<Vector3> uvarray;
-				uvarray.resize(vertex_array.size());
-				PoolVector<Vector3>::Write uvarrayw = uvarray.write();
-
-				for (int k = 0; k < vlen; k++) {
-					uvarrayw[k] = vertex_array[k].uv;
+				if (uv_src) {
+					surftool->add_uv(Vector2(vertex_array[k].uv.x, vertex_array[k].uv.y));
 				}
-
-				uvarrayw = PoolVector<Vector3>::Write();
-				final_uv_array = uvarray;
-			}
-
-			if (uv2_src) { //compute uv first, may be needed for computing tangent/bionrmal
-				PoolVector<Vector3> uv2array;
-				uv2array.resize(vertex_array.size());
-				PoolVector<Vector3>::Write uv2arrayw = uv2array.write();
-
-				for (int k = 0; k < vlen; k++) {
-					uv2arrayw[k] = vertex_array[k].uv2;
+				if (uv2_src) {
+					surftool->add_uv2(Vector2(vertex_array[k].uv2.x, vertex_array[k].uv2.y));
 				}
-
-				uv2arrayw = PoolVector<Vector3>::Write();
-				final_uv2_array = uv2array;
-			}
-
-			if (normal_src) {
-				PoolVector<Vector3> narray;
-				narray.resize(vertex_array.size());
-				PoolVector<Vector3>::Write narrayw = narray.write();
-
-				for (int k = 0; k < vlen; k++) {
-					narrayw[k] = vertex_array[k].normal;
+				if (color_src) {
+					surftool->add_color(vertex_array[k].color);
 				}
 
-				narrayw = PoolVector<Vector3>::Write();
-				final_normal_array = narray;
-
-				/*
-				PoolVector<Vector3> altnaray;
-				_generate_normals(index_array,final_vertex_array,altnaray);
-
-				for(int i=0;i<altnaray.size();i++)
-					print_line(rtos(altnaray[i].dot(final_normal_array[i])));
-				*/
-
-			} else if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
-				//generate normals (even if unused later)
-
-				_generate_normals(index_array, final_vertex_array, final_normal_array);
-				if (OS::get_singleton()->is_stdout_verbose())
-					print_line("Collada: Triangle mesh lacks normals, so normals were generated.");
-				final_format |= Mesh::ARRAY_FORMAT_NORMAL;
-			}
-
-			if (final_normal_array.size() && uv_src && binormal_src && tangent_src && !force_make_tangents) {
+				if (has_weights) {
+					Vector<float> weights;
+					Vector<int> bones;
+					weights.resize(VS::ARRAY_WEIGHTS_SIZE);
+					bones.resize(VS::ARRAY_WEIGHTS_SIZE);
+					//float sum=0.0;
+					for (int l = 0; l < VS::ARRAY_WEIGHTS_SIZE; l++) {
+						if (l < vertex_array[k].weights.size()) {
+							weights[l] = vertex_array[k].weights[l].weight;
+							bones[l] = vertex_array[k].weights[l].bone_idx;
+							//sum += vertex_array[k].weights[l].weight;
+						} else {
 
-				PoolVector<real_t> tarray;
-				tarray.resize(vertex_array.size() * 4);
-				PoolVector<real_t>::Write tarrayw = tarray.write();
+							weights[l] = 0;
+							bones[l] = 0;
+						}
+					}
 
-				for (int k = 0; k < vlen; k++) {
-					tarrayw[k * 4 + 0] = vertex_array[k].tangent.normal.x;
-					tarrayw[k * 4 + 1] = vertex_array[k].tangent.normal.y;
-					tarrayw[k * 4 + 2] = vertex_array[k].tangent.normal.z;
-					tarrayw[k * 4 + 3] = vertex_array[k].tangent.d;
+					surftool->add_bones(bones);
+					surftool->add_weights(weights);
 				}
 
-				tarrayw = PoolVector<real_t>::Write();
-
-				final_tangent_array = tarray;
-			} else if (final_normal_array.size() && primitive == Mesh::PRIMITIVE_TRIANGLES && final_uv_array.size() && (force_make_tangents || (material.is_valid()))) {
-				//if this uses triangles, there are uvs and the material is using a normalmap, generate tangents and binormals, because they WILL be needed
-				//generate binormals/tangents
-				_generate_tangents_and_binormals(index_array, final_vertex_array, final_uv_array, final_normal_array, final_tangent_array);
-				final_format |= Mesh::ARRAY_FORMAT_TANGENT;
-				if (OS::get_singleton()->is_stdout_verbose())
-					print_line("Collada: Triangle mesh lacks tangents (And normalmap was used), so tangents were generated.");
+				surftool->add_vertex(vertex_array[k].vertex);
 			}
 
-			if (color_src) {
-				PoolVector<Color> colorarray;
-				colorarray.resize(vertex_array.size());
-				PoolVector<Color>::Write colorarrayw = colorarray.write();
-
-				for (int k = 0; k < vlen; k++) {
-					colorarrayw[k] = vertex_array[k].color;
-				}
-
-				colorarrayw = PoolVector<Color>::Write();
-
-				final_color_array = colorarray;
+			for (List<int>::Element *E = indices_list.front(); E; E = E->next()) {
+				surftool->add_index(E->get());
 			}
 
-			if (has_weights) {
-				PoolVector<float> weightarray;
-				PoolVector<int> bonearray;
-
-				weightarray.resize(vertex_array.size() * 4);
-				PoolVector<float>::Write weightarrayw = weightarray.write();
-				bonearray.resize(vertex_array.size() * 4);
-				PoolVector<int>::Write bonearrayw = bonearray.write();
-
-				for (int k = 0; k < vlen; k++) {
-					float sum = 0;
-
-					for (int l = 0; l < VS::ARRAY_WEIGHTS_SIZE; l++) {
-						if (l < vertex_array[k].weights.size()) {
-							weightarrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = vertex_array[k].weights[l].weight;
-							sum += weightarrayw[k * VS::ARRAY_WEIGHTS_SIZE + l];
-							bonearrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = int(vertex_array[k].weights[l].bone_idx);
-							//COLLADA_PRINT(itos(k)+": "+rtos(bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l])+":"+rtos(weightarray[k*VS::ARRAY_WEIGHTS_SIZE+l]));
-						} else {
-
-							weightarrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = 0;
-							bonearrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = 0;
-						}
-					}
-					/*
-					if (sum<0.8)
-						COLLADA_PRINT("ERROR SUMMING INDEX "+itos(k)+" had weights: "+itos(vertex_array[k].weights.size()));
-					*/
-				}
+			if (!normal_src) {
+				//should always be normals
+				surftool->generate_normals();
+			}
 
-				weightarrayw = PoolVector<float>::Write();
-				bonearrayw = PoolVector<int>::Write();
+			if ((!binormal_src || !tangent_src) && normal_src && uv_src && force_make_tangents) {
 
-				final_weight_array = weightarray;
-				final_bone_array = bonearray;
+				surftool->generate_tangents();
 			}
 
 			////////////////////////////
 			// FINALLY CREATE SUFRACE //
 			////////////////////////////
 
-			Array d;
+			Array d = surftool->commit_to_arrays();
 			d.resize(VS::ARRAY_MAX);
 
-			d[Mesh::ARRAY_INDEX] = index_array;
-			d[Mesh::ARRAY_VERTEX] = final_vertex_array;
-
-			if (final_normal_array.size())
-				d[Mesh::ARRAY_NORMAL] = final_normal_array;
-			if (final_tangent_array.size())
-				d[Mesh::ARRAY_TANGENT] = final_tangent_array;
-			if (final_uv_array.size())
-				d[Mesh::ARRAY_TEX_UV] = final_uv_array;
-			if (final_uv2_array.size())
-				d[Mesh::ARRAY_TEX_UV2] = final_uv2_array;
-			if (final_color_array.size())
-				d[Mesh::ARRAY_COLOR] = final_color_array;
-			if (final_weight_array.size())
-				d[Mesh::ARRAY_WEIGHTS] = final_weight_array;
-			if (final_bone_array.size())
-				d[Mesh::ARRAY_BONES] = final_bone_array;
-
 			Array mr;
 
 			////////////////////////////
@@ -1249,10 +1095,10 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
 				Array a = p_morph_meshes[mi]->surface_get_arrays(surface);
 				//add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not)
 
-				if (final_weight_array.size())
-					a[Mesh::ARRAY_WEIGHTS] = final_weight_array;
-				if (final_bone_array.size())
-					a[Mesh::ARRAY_BONES] = final_bone_array;
+				if (has_weights) {
+					a[Mesh::ARRAY_WEIGHTS] = d[Mesh::ARRAY_WEIGHTS];
+					a[Mesh::ARRAY_BONES] = d[Mesh::ARRAY_BONES];
+				}
 
 				a[Mesh::ARRAY_INDEX] = Variant();
 				//a.resize(Mesh::ARRAY_MAX); //no need for index

+ 2 - 1
modules/gridmap/grid_map.cpp

@@ -155,7 +155,7 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const {
 
 	p_list->push_back(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"));
 	p_list->push_back(PropertyInfo(Variant::NIL, "Cell", PROPERTY_HINT_NONE, "cell_", PROPERTY_USAGE_GROUP));
-	p_list->push_back(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_RANGE, "0.01,16384,0.01"));
+	p_list->push_back(PropertyInfo(Variant::VECTOR3, "cell_size"));
 	p_list->push_back(PropertyInfo(Variant::INT, "cell_octant_size", PROPERTY_HINT_RANGE, "1,1024,1"));
 	p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_x"));
 	p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_y"));
@@ -184,6 +184,7 @@ Ref<MeshLibrary> GridMap::get_theme() const {
 
 void GridMap::set_cell_size(const Vector3 &p_size) {
 
+	ERR_FAIL_COND(p_size.x < 0.001 || p_size.y < 0.001 || p_size.z < 0.001);
 	cell_size = p_size;
 	_recreate_octant_data();
 }

+ 13 - 2
scene/resources/surface_tool.cpp

@@ -691,6 +691,17 @@ void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvT
 	fvTexcOut[1] = v.y;
 	//fvTexcOut[1]=1.0-v.y;
 }
+
+void SurfaceTool::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+		const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
+
+	Vector<List<Vertex>::Element *> &varr = *((Vector<List<Vertex>::Element *> *)pContext->m_pUserData);
+	Vertex *vtx = &varr[iFace * 3 + iVert]->get();
+
+	vtx->tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
+	vtx->binormal = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+}
+
 void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) {
 
 	Vector<List<Vertex>::Element *> &varr = *((Vector<List<Vertex>::Element *> *)pContext->m_pUserData);
@@ -715,8 +726,8 @@ void SurfaceTool::generate_tangents() {
 	mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace;
 	mkif.m_getPosition = mikktGetPosition;
 	mkif.m_getTexCoord = mikktGetTexCoord;
-	mkif.m_setTSpaceBasic = mikktSetTSpaceBasic;
-	mkif.m_setTSpace = NULL;
+	mkif.m_setTSpace = mikktSetTSpaceDefault;
+	mkif.m_setTSpaceBasic = NULL;
 
 	SMikkTSpaceContext msc;
 	msc.m_pInterface = &mkif;

+ 2 - 0
scene/resources/surface_tool.h

@@ -90,6 +90,8 @@ private:
 	static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
 	static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
 	static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
+	static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+			const tbool bIsOrientationPreserving, const int iFace, const int iVert);
 
 protected:
 	static void _bind_methods();