-Fixes to how collada generates tangents (use SurfaceTool), closes #9562

-Fix to gridmap cell size (wrong property type)
This commit is contained in:
Juan Linietsky 2017-08-29 08:47:29 -03:00
parent b2d53257ed
commit a2027cfa49
4 changed files with 68 additions and 208 deletions

View file

@ -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;
Ref<SurfaceTool> surftool;
surftool.instance();
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
uint32_t final_format = 0;
//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));
}
if (uv2_src) {
surftool->add_uv2(Vector2(vertex_array[k].uv2.x, vertex_array[k].uv2.y));
}
if (color_src) {
surftool->add_color(vertex_array[k].color);
}
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;
}
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;
}
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) {
PoolVector<real_t> tarray;
tarray.resize(vertex_array.size() * 4);
PoolVector<real_t>::Write tarrayw = tarray.write();
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;
}
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.");
}
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;
}
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;
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()) {
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]));
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 {
weightarrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = 0;
bonearrayw[k * VS::ARRAY_WEIGHTS_SIZE + l] = 0;
weights[l] = 0;
bones[l] = 0;
}
}
/*
if (sum<0.8)
COLLADA_PRINT("ERROR SUMMING INDEX "+itos(k)+" had weights: "+itos(vertex_array[k].weights.size()));
*/
surftool->add_bones(bones);
surftool->add_weights(weights);
}
weightarrayw = PoolVector<float>::Write();
bonearrayw = PoolVector<int>::Write();
surftool->add_vertex(vertex_array[k].vertex);
}
final_weight_array = weightarray;
final_bone_array = bonearray;
for (List<int>::Element *E = indices_list.front(); E; E = E->next()) {
surftool->add_index(E->get());
}
if (!normal_src) {
//should always be normals
surftool->generate_normals();
}
if ((!binormal_src || !tangent_src) && normal_src && uv_src && force_make_tangents) {
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

View file

@ -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();
}

View file

@ -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;

View file

@ -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();