Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support tangent space handedness #8871

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion editor/src/clj/editor/graphics.clj
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,12 @@
:semantic-type :semantic-type-normal
:coordinate-space :coordinate-space-world
:data-type :type-float
:element-count 3}]))
:element-count 3}
{:name "tangent"
:semantic-type :semantic-type-tangent
:coordinate-space :coordinate-space-world
:data-type :type-float
:element-count 4}]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using world-space meshes, the tangents in :tangent-data will be transformed by the renderable-data->world-direction-v4 function. Currently, this writes a zero for the W component when it calls the geom/transf-n4 function. I think we need to update geom/transf-n4 to pass along the unaltered W component.

It seems to me, we would need to do something similar on the engine side since we presumably transform the tangents using the normal matrix somewhere there as well, but I'm not seeing it in this PR? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The engine preserves the handedness in Rig.cpp in the "GenerateNormalData" function.


(defn shader-bound-attributes [^GL2 gl shader material-attribute-infos manufactured-attribute-keys default-coordinate-space]
{:pre [(#{:coordinate-space-local :coordinate-space-world} default-coordinate-space)]}
Expand Down
4 changes: 2 additions & 2 deletions editor/src/clj/editor/model_scene.clj
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
(defn mesh->renderable-data [mesh]
(let [positions (flat->vectors 3 (:positions mesh))
normals (flat->vectors 3 (:normals mesh))
tangents (flat->vectors 3 (:tangents mesh))
tangents (flat->vectors 4 (:tangents mesh))
colors (flat->vectors 4 (:colors mesh))
texcoord0s (flat->vectors (:num-texcoord0-components mesh 0) (:texcoord0 mesh))
texcoord1s (flat->vectors (:num-texcoord1-components mesh 0) (:texcoord1 mesh))
Expand Down Expand Up @@ -193,7 +193,7 @@
:vertex-space-local :coordinate-space-local
:vertex-space-world :coordinate-space-world)
vertex-description (or override-vertex-description
(let [manufactured-attribute-keys [:position :texcoord0 :normal]
(let [manufactured-attribute-keys [:position :texcoord0 :normal :tangent]
shader-bound-attributes (graphics/shader-bound-attributes gl shader material-attribute-infos manufactured-attribute-keys default-coordinate-space)]
(graphics/make-vertex-description shader-bound-attributes)))
coordinate-space-info (graphics/coordinate-space-info (:attributes vertex-description))
Expand Down
5 changes: 3 additions & 2 deletions engine/gamesys/src/gamesys/components/comp_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,14 @@ namespace dmGameSystem

world->m_Components.SetCapacity(comp_count);
world->m_RenderObjects.SetCapacity(comp_count);
DM_STATIC_ASSERT( sizeof(dmRig::RigModelVertex) == ((3+3+3+4+2+2)*4), Invalid_Struct_Size);
// position, normal, tangent, color, texcoord0, texcoord1 * sizeof(float)
DM_STATIC_ASSERT( sizeof(dmRig::RigModelVertex) == ((3+3+4+4+2+2)*4), Invalid_Struct_Size);

dmGraphics::HContext graphics_context = dmRender::GetGraphicsContext(render_context);
dmGraphics::HVertexStreamDeclaration stream_declaration = dmGraphics::NewVertexStreamDeclaration(graphics_context);
dmGraphics::AddVertexStream(stream_declaration, "position", 3, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "normal", 3, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "tangent", 3, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "tangent", 4, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "color", 4, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "texcoord0", 2, dmGraphics::TYPE_FLOAT, false);
dmGraphics::AddVertexStream(stream_declaration, "texcoord1", 2, dmGraphics::TYPE_FLOAT, false);
Expand Down
2 changes: 1 addition & 1 deletion engine/gamesys/src/gamesys/resources/res_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ namespace dmGameSystem
{
out_write_ptr->pos[c] = *positions++;
out_write_ptr->normal[c] = normals ? *normals++ : 0.0f;
out_write_ptr->tangent[c] = tangents ? *tangents++ : 0.0f;
}

for (int c = 0; c < 4; ++c)
{
out_write_ptr->color[c] = colors ? *colors++ : 1.0f;
out_write_ptr->tangent[c] = tangents ? *tangents++ : 0.0f;
}

for (int c = 0; c < 2; ++c)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public static class Mesh {

public float[] positions; // float3
public float[] normals; // float3
public float[] tangents; // float3
public float[] tangents; // float4
public float[] colors; // float4
public float[] weights; // float4
public int[] bones; // uint4
Expand Down Expand Up @@ -368,7 +368,7 @@ private static void DebugPrintMesh(Mesh mesh, int indent) {
max_count = mesh.vertexCount;
DebugPrintFloatArray(indent+1, "positions", mesh.positions, max_count, 3);
DebugPrintFloatArray(indent+1, "normals", mesh.normals, max_count, 3);
DebugPrintFloatArray(indent+1, "tangents", mesh.tangents, max_count, 3);
DebugPrintFloatArray(indent+1, "tangents", mesh.tangents, max_count, 4);
DebugPrintFloatArray(indent+1, "colors", mesh.colors, max_count, 4);
DebugPrintFloatArray(indent+1, "weights", mesh.weights, max_count, 4);
DebugPrintIntArray(indent+1, "bones", mesh.bones, max_count, 4);
Expand Down Expand Up @@ -481,7 +481,8 @@ public byte[] getData(String path, String uri) {
};

// Used for testing the importer. Usage:
// ./src/com/dynamo/bob/pipeline/test_model_importer.sh <model path>
// cd engine/modelc
// ./scripts/test_model_importer.sh <model path>
public static void main(String[] args) throws IOException {
System.setProperty("java.awt.headless", "true");

Expand Down
2 changes: 1 addition & 1 deletion engine/modelc/src/modelimporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace dmModelImporter
// loop using m_VertexCount * stride
float* m_Positions; // 3 floats per vertex
float* m_Normals; // 3 floats per vertex
float* m_Tangents; // 3 floats per vertex
float* m_Tangents; // 4 floats per vertex
float* m_Color; // 4 floats per vertex
float* m_Weights; // 4 weights per vertex
uint32_t* m_Bones; // 4 bones per vertex
Expand Down
2 changes: 1 addition & 1 deletion engine/modelc/src/modelimporter_gltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ static void LoadPrimitives(Scene* scene, Model* model, cgltf_data* gltf_data, cg
float default_value_f = 0.0f;
if (attribute->type == cgltf_attribute_type_tangent)
{
desired_num_components = 3; // for some reason it give 4 elements
desired_num_components = 4; // xyz + handedness
}
else if (attribute->type == cgltf_attribute_type_color)
{
Expand Down
2 changes: 1 addition & 1 deletion engine/modelc/src/modelimporter_jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ static jobject CreateMesh(JNIEnv* env, const TypeInfos* types, const dmArray<job
uint32_t icount = mesh->m_IndexCount;
SET_FARRAY(obj, positions, vcount * 3, mesh->m_Positions);
SET_FARRAY(obj, normals, vcount * 3, mesh->m_Normals);
SET_FARRAY(obj, tangents, vcount * 3, mesh->m_Tangents);
SET_FARRAY(obj, tangents, vcount * 4, mesh->m_Tangents);
SET_FARRAY(obj, colors, vcount * 4, mesh->m_Color);
SET_FARRAY(obj, weights, vcount * 4, mesh->m_Weights);
SET_FARRAY(obj, texCoords0, vcount * mesh->m_TexCoord0NumComponents, mesh->m_TexCoord0);
Expand Down
2 changes: 1 addition & 1 deletion engine/rig/src/dmsdk/rig/rig.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ namespace dmRig
{
float pos[3];
float normal[3];
float tangent[3];
float tangent[4];
float color[4];
float uv0[2];
float uv1[2];
Expand Down
23 changes: 14 additions & 9 deletions engine/rig/src/rig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace dmRig
// used to creating primitives from indices.
dmArray<dmVMath::Vector3> m_ScratchPositionBuffer;
dmArray<dmVMath::Vector3> m_ScratchNormalBuffer;
dmArray<dmVMath::Vector3> m_ScratchTangentBuffer;
dmArray<dmVMath::Vector4> m_ScratchTangentBuffer;
};


Expand Down Expand Up @@ -801,14 +801,16 @@ namespace dmRig

if (has_tangents)
{
Vector3 tangent_in(tangents_in[i*3+0], tangents_in[i*3+1], tangents_in[i*3+2]);
Vector3 tangent_in(tangents_in[i*4+0], tangents_in[i*4+1], tangents_in[i*4+2]);
float tangent_handedness = tangents_in[i*4+3];
tangent = normal_matrix * tangent_in;
if (lengthSqr(tangent) > 0.0f) {
normalize(tangent);
}
*tangents_buffer++ = tangent[0];
*tangents_buffer++ = tangent[1];
*tangents_buffer++ = tangent[2];
*tangents_buffer++ = tangent_handedness;
}
}
return;
Expand All @@ -822,7 +824,8 @@ namespace dmRig
const Vector3 normal_in(normals_in[i*3+0], normals_in[i*3+1], normals_in[i*3+2]);
Vector4 normal_out(0.0f, 0.0f, 0.0f, 0.0f);

const Vector3 tangent_in = has_tangents ? Vector3(tangents_in[i*3+0], tangents_in[i*3+1], tangents_in[i*3+2]) : Vector3(0,0,0);
const Vector3 tangent_in = has_tangents ? Vector3(tangents_in[i*4+0], tangents_in[i*4+1], tangents_in[i*4+2]) : Vector3(0,0,0);
const float tangent_handedness = tangents_in[i*4+3];
Vector4 tangent_out(0.0f, 0.0f, 0.0f, 0.0f);

const uint32_t bi_offset = i * 4;
Expand Down Expand Up @@ -867,6 +870,7 @@ namespace dmRig
*tangents_buffer++ = tangent[0];
*tangents_buffer++ = tangent[1];
*tangents_buffer++ = tangent[2];
*tangents_buffer++ = tangent_handedness;
}
}
}
Expand Down Expand Up @@ -974,7 +978,7 @@ namespace dmRig
} break;
case dmGraphics::VertexAttribute::SEMANTIC_TYPE_TANGENT:
{
memcpy(write_ptr, &tangents[idx*3], dmMath::Min(3 * sizeof(float), data_size));
memcpy(write_ptr, &tangents[idx*4], dmMath::Min(4 * sizeof(float), data_size));
} break;
default:
{
Expand Down Expand Up @@ -1035,12 +1039,12 @@ namespace dmRig
{
out_write_ptr->pos[c] = *positions++;
out_write_ptr->normal[c] = *normals++;
out_write_ptr->tangent[c] = *tangents++;
}

for (int c = 0; c < 4; ++c)
{
out_write_ptr->color[c] = colors ? *colors++ : 1.0f;
out_write_ptr->tangent[c] = *tangents++;
}

for (int c = 0; c < 2; ++c)
Expand Down Expand Up @@ -1075,12 +1079,12 @@ namespace dmRig
{
out_write_ptr->pos[c] = positions[idx*3+c];
out_write_ptr->normal[c] = normals[idx*3+c];
out_write_ptr->tangent[c] = tangents[idx*3+c];
}

for (int c = 0; c < 4; ++c)
{
out_write_ptr->color[c] = colors ? colors[idx*4+c] : 1.0f;
out_write_ptr->tangent[c] = tangents[idx*4+c];
}

for (int c = 0; c < 2; ++c)
Expand All @@ -1096,7 +1100,8 @@ namespace dmRig
return out_write_ptr;
}

static void EnsureSize(dmArray<Vector3>& array, uint32_t size)
template <typename T>
static void EnsureSize(T& array, uint32_t size)
{
if (array.Capacity() < size) {
array.OffsetCapacity(size - array.Capacity());
Expand All @@ -1116,7 +1121,7 @@ namespace dmRig
dmArray<Matrix4>& pose_matrices = context->m_ScratchPoseMatrixBuffer;
dmArray<Vector3>& positions = context->m_ScratchPositionBuffer;
dmArray<Vector3>& normals = context->m_ScratchNormalBuffer;
dmArray<Vector3>& tangents = context->m_ScratchTangentBuffer;
dmArray<Vector4>& tangents = context->m_ScratchTangentBuffer;

uint32_t bone_count = GetBoneCount(instance);
uint32_t vertex_count = mesh->m_Positions.m_Count / 3;
Expand Down Expand Up @@ -1193,7 +1198,7 @@ namespace dmRig
dmArray<Matrix4>& pose_matrices = context->m_ScratchPoseMatrixBuffer;
dmArray<Vector3>& positions = context->m_ScratchPositionBuffer;
dmArray<Vector3>& normals = context->m_ScratchNormalBuffer;
dmArray<Vector3>& tangents = context->m_ScratchTangentBuffer;
dmArray<Vector4>& tangents = context->m_ScratchTangentBuffer;

// If the rig has bones, update the pose to be local-to-model
uint32_t bone_count = GetBoneCount(instance);
Expand Down
18 changes: 11 additions & 7 deletions engine/rig/src/test/test_rig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,24 @@ static void CreateTestMesh(dmRigDDF::MeshSet* mesh_set, int model_index, int mes
mesh.m_Normals[10] = 1.0;
mesh.m_Normals[11] = 0.0;

mesh.m_Tangents.m_Count = vert_count*3;
mesh.m_Tangents.m_Count = vert_count*4;
mesh.m_Tangents.m_Data = new float[mesh.m_Tangents.m_Count];
mesh.m_Tangents[0] = 0.0;
mesh.m_Tangents[1] = 0.0;
mesh.m_Tangents[2] = 1.0;
mesh.m_Tangents[3] = 0.0;
mesh.m_Tangents[3] = 1.0;
mesh.m_Tangents[4] = 0.0;
mesh.m_Tangents[5] = 1.0;
mesh.m_Tangents[6] = 0.0;
mesh.m_Tangents[7] = 0.0;
mesh.m_Tangents[8] = 1.0;
mesh.m_Tangents[5] = 0.0;
mesh.m_Tangents[6] = 1.0;
mesh.m_Tangents[7] = 1.0;
mesh.m_Tangents[8] = 0.0;
mesh.m_Tangents[9] = 0.0;
mesh.m_Tangents[10] = 0.0;
mesh.m_Tangents[10] = 1.0;
mesh.m_Tangents[11] = 1.0;
mesh.m_Tangents[12] = 0.0;
mesh.m_Tangents[13] = 0.0;
mesh.m_Tangents[14] = 1.0;
mesh.m_Tangents[15] = 1.0;

mesh.m_Colors.m_Count = vert_count*4;
mesh.m_Colors.m_Data = new float[mesh.m_Colors.m_Count];
Expand Down