This saves one vertex attribute.
st.append(Token("TEXCOORD"+size))
else:
st.append(Token("TEXCOORD{}_{}".format(size, u.unit)))
- if mesh.tbn_vecs:
+ if mesh.tangent_vecs:
st.append(Token("TANGENT3"))
- st.append(Token("BINORMAL3"))
if mesh.vertex_groups:
st.append(Token("GROUP{}".format(mesh.max_groups_per_vertex)))
st.append(Token("WEIGHT{}".format(mesh.max_groups_per_vertex)))
color = None
uvs = [None]*len(mesh.uv_layers)
tan = None
- bino = None
group = None
weight = None
for v in mesh.vertices:
else:
st.sub.append(Statement("multitexcoord", u.unit, *v.uvs[i]))
uvs[i] = v.uvs[i]
- if mesh.tbn_vecs:
+ if mesh.tangent_vecs:
if v.tan!=tan:
st.sub.append(Statement("tangent", *v.tan))
tan = v.tan
- if v.bino!=bino:
- st.sub.append(Statement("binormal", *v.bino))
- bino = v.bino
if mesh.vertex_groups:
v_group = [g.group for g in v.groups]
v_weight = [g.weight for g in v.groups]
if vertex.__class__==Vertex:
self.uvs = vertex.uvs[:]
self.tan = vertex.tan
- self.bino = vertex.bino
else:
self.uvs = []
self.tan = None
- self.bino = None
self.index = vertex.index
self.co = mathutils.Vector(vertex.co)
self.normal = mathutils.Vector(vertex.normal)
self.winding_test = mesh.winding_test
self.smoothing = mesh.smoothing
self.use_uv = mesh.use_uv
- self.tbn_vecs = mesh.tbn_vecs
- self.tbn_uvtex = mesh.tbn_uvtex
+ self.tangent_vecs = mesh.tangent_vecs
+ self.tangent_uvtex = mesh.tangent_uvtex
self.vertex_groups = mesh.vertex_groups
# Clone basic data
prog_count = len(self.uv_layers)
prog_step = 0
- # Split by the UV layer used for TBN vectors first so connectivity
- # remains intact for TBN vector computation
- tbn_layer_index = -1
- if self.tbn_vecs:
- if self.tbn_uvtex:
+ # Split by the UV layer used for tangent vectors first so connectivity
+ # remains intact for tangent vector computation
+ tangent_layer_index = -1
+ if self.tangent_vecs:
+ if self.tangent_uvtex:
uv_names = [u.name for u in self.uv_layers]
- if self.tbn_uvtex in uv_names:
- tbn_layer_index = uv_names.index(self.tbn_uvtex)
+ if self.tangent_uvtex in uv_names:
+ tangent_layer_index = uv_names.index(self.tangent_uvtex)
elif self.uv_layers[0].unit==0:
- tbn_layer_index = 0
+ tangent_layer_index = 0
- if tbn_layer_index>=0:
+ if tangent_layer_index>=0:
prog_count += 1
- progress.push_task_slice("Computing TBN", 0, prog_count)
- self.split_vertices(self.find_uv_group, progress, tbn_layer_index)
- progress.set_task_slice(self.tbn_uvtex, 1, prog_count)
- self.compute_tbn(tbn_layer_index, progress)
+ progress.push_task_slice("Computing tangents", 0, prog_count)
+ self.split_vertices(self.find_uv_group, progress, tangent_layer_index)
+ progress.set_task_slice(self.tangent_uvtex, 1, prog_count)
+ self.compute_tangents(tangent_layer_index, progress)
progress.pop_task()
prog_step = 2
else:
- raise Exception("TBN UV layer not found")
+ raise Exception("Tangent UV layer not found")
# Split by the remaining UV layers
for i, u in enumerate(self.uv_layers):
- if i==tbn_layer_index:
+ if i==tangent_layer_index:
continue
progress.push_task_slice(u.name, prog_step, prog_count)
progress.set_progress(i/len(self.vertices))
- def compute_tbn(self, index, progress):
- # This function is called at an early stage during UV preparation when
- # face UVs are not available yet
+ def compute_tangents(self, index, progress):
layer_uvs = self.uv_layers[index].uvs
for i, v in enumerate(self.vertices):
v.tan = mathutils.Vector()
- v.bino = mathutils.Vector()
for f in v.faces:
vi = f.pivot_vertex(v)
uv0 = layer_uvs[f.loop_indices[vi[0]]]
if div:
mul = edge1.angle(edge2)/div
v.tan += (edge1*dv2-edge2*dv1)*mul
- v.bino += (edge2*du1-edge1*du2)*mul
if v.tan.length:
v.tan.normalize()
- if v.bino.length:
- v.bino.normalize()
progress.set_progress(i/len(self.vertices))
bmesh.vertex_groups = o.data.vertex_groups
bmesh.max_groups_per_vertex = o.data.max_groups_per_vertex
bmesh.use_uv = o.data.use_uv
- bmesh.tbn_vecs = o.data.tbn_vecs
- bmesh.tbn_uvtex = o.data.tbn_uvtex
+ bmesh.tangent_vecs = o.data.tangent_vecs
+ bmesh.tangent_uvtex = o.data.tangent_uvtex
me = Mesh(bmesh)
me.transform(m)
col = self.layout.column()
col.label(text="Texturing")
col.prop(mesh, "use_uv")
- col.prop(mesh, "tbn_vecs")
- col.prop(mesh, "tbn_uvtex")
+ col.prop(mesh, "tangent_vecs")
+ col.prop(mesh, "tangent_uvtex")
class MspGLObjectProperties(bpy.types.Panel):
bl_idname = "OBJECT_PT_mspgl_properties"
items=(("NONE", "None", "Ignore all UV coordinates"),
("UNIT0", "Unit 0", "Use UV coordinates for unit 0"),
("ALL", "All", "Use all UV coordinates")))
- bpy.types.Mesh.tbn_vecs = bpy.props.BoolProperty(name="TBN vectors", description="Compute tangent and binormal vectors for vertices", default=False)
- bpy.types.Mesh.tbn_uvtex = bpy.props.StringProperty(name="TBN UV layer", description="UV layer to use as basis for TBN vectors", default="")
+ bpy.types.Mesh.tangent_vecs = bpy.props.BoolProperty(name="Tangent vectors", description="Compute tangent vectors for vertices", default=False)
+ bpy.types.Mesh.tangent_uvtex = bpy.props.StringProperty(name="Tangent UV layer", description="UV layer to use as basis for tangent vectors", default="")
bpy.types.Object.compound = bpy.props.BoolProperty(name="Compound with parent", description="Join this object to its parent when exporting")
bpy.types.Object.lod_for_parent = bpy.props.BoolProperty(name="LoD for parent", description="This object is a level of detail for its parent")
out vec3 eye_normal = normal_tf*get_vertex_normal();
vec3 eye_tangent = normal_tf*tangent;
- vec3 eye_binormal = normal_tf*binormal;
+ vec3 eye_binormal = cross(eye_normal, eye_tangent);
out mat3 eye_tbn_matrix = mat3(eye_tangent, eye_binormal, eye_normal);
out vec3 eye_look_dir = normalize(eye_vertex.xyz);
layout(location=1) in vec4 color;
layout(location=2) in vec3 normal;
layout(location=3) in vec3 tangent;
-layout(location=4) in vec3 binormal;
-layout(location=7) in vec4 texcoord;
-layout(location=8) in vec4 texcoord1;
-layout(location=9) in vec4 texcoord2;
-layout(location=10) in vec4 texcoord3;
+layout(location=6) in vec4 texcoord;
+layout(location=7) in vec4 texcoord1;
+layout(location=8) in vec4 texcoord2;
+layout(location=9) in vec4 texcoord3;
layout(location=13) in vec4 instance_transform[3];
#pragma MSP stage(fragment)
void BoxBuilder::build_face(PrimitiveBuilder &builder, const Vector3 &o, const Vector3 &s1, const Vector3 &s2) const
{
float l1 = 1, l2 = 1;
- if(generate_tbn || tex_fit!=STRETCH)
+ if(generate_tan || tex_fit!=STRETCH)
{
l1 = s1.norm();
l2 = s2.norm();
}
- if(generate_tbn)
- {
+ if(generate_tan)
builder.tangent(s1/l1);
- builder.binormal(s2/l2);
- }
float u_size = 1;
float v_size = 1;
float sc = cos(sa);
float ss = sin(sa);
builder.normal(rs*sc, rs*ss, -rc);
- if(generate_tbn)
- {
+ if(generate_tan)
builder.tangent(-ss, sc, 0);
- builder.binormal(rc*sc, rc*ss, rs);
- }
builder.texcoord(j*u_scale, v);
builder.vertex(rs*sc*radius, rs*ss*radius, cz-rc*radius);
}
void CylinderBuilder::build(PrimitiveBuilder &builder) const
{
- if(generate_tbn)
- builder.binormal(0, 1, 0);
for(unsigned i=0; i<2; ++i)
{
float z = (i-0.5)*length;
builder.normal(0, 0, i*2.0-1.0);
builder.texcoord(0.5, 0.5);
- if(generate_tbn)
+ if(generate_tan)
builder.tangent((i ? 1 : -1), 0, 0);
builder.vertex(0, 0, z);
for(unsigned j=0; j<segments; ++j)
float v_scale = 1;
adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, length);
- if(generate_tbn)
- builder.binormal(0, 0, 1);
for(unsigned i=0; i<2; ++i)
{
float z = (i-0.5)*length;
float s = sin(a);
builder.normal(c, s, 0);
builder.texcoord(j*u_scale, i*v_scale);
- if(generate_tbn)
+ if(generate_tan)
builder.tangent(-s, c, 0);
builder.vertex(radius*c, radius*s, z);
}
namespace GL {
GeometryBuilder::GeometryBuilder():
- generate_tbn(false),
+ generate_tan(false),
tex_fit(STRETCH)
{ }
-GeometryBuilder &GeometryBuilder::tbn(bool t)
+GeometryBuilder &GeometryBuilder::tangents(bool t)
{
- generate_tbn = t;
+ generate_tan = t;
return *this;
}
#ifndef MSP_GL_GEOMETRYBUILDER_H_
#define MSP_GL_GEOMETRYBUILDER_H_
+#include <msp/core/attributes.h>
+
namespace Msp {
namespace GL {
};
protected:
- bool generate_tbn;
+ bool generate_tan;
TextureFit tex_fit;
GeometryBuilder();
public:
- GeometryBuilder &tbn(bool = true);
+ DEPRECATED GeometryBuilder &tbn(bool t = true) { return tangents(t); }
+ GeometryBuilder &tangents(bool = true);
GeometryBuilder &texture_fit(TextureFit);
protected:
void adjust_texture_scale(float &, float &, float, float) const;
adjust_texture_scale(u_scale, v_scale, sqrt(l1_sq), l2);
builder.normal(norm.x, norm.y, norm.z);
- if(generate_tbn)
- {
+ if(generate_tan)
builder.tangent(side1);
- builder.binormal(binorm);
- }
for(unsigned j=0; j<=v_div; ++j)
{
builder.normal(cv*cu, cv*su, sv);
builder.texcoord(j*u_scale, i*v_scale);
- if(generate_tbn)
- {
+ if(generate_tan)
builder.tangent(-su, cu, 0);
- builder.binormal(-sv*cu, -sv*su, cv);
- }
builder.vertex(cv*cu*radius, cv*su*radius, sv*radius);
}
}
void tangent(const Vector3 &t)
{ attrib(get_attribute_semantic(TANGENT3), mtx*Vector4(t.x, t.y, t.z, 0)); }
- void binormal(float x, float y, float z)
- { binormal(Vector3(x, y, z)); }
+ DEPRECATED void binormal(float, float, float)
+ { }
- void binormal(const Vector3 &b)
- { attrib(get_attribute_semantic(BINORMAL3), mtx*Vector4(b.x, b.y, b.z, 0)); }
+ DEPRECATED void binormal(const Vector3 &)
+ { }
void texcoord(float s)
{ texcoord(s, 0, 0, 1); }
add("generic", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
add("generic", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
add("generic", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
- add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
- add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
add("group", static_cast<void (Loader::*)(int)>(&Loader::group));
add("group", static_cast<void (Loader::*)(int, int)>(&Loader::group));
add("group", static_cast<void (Loader::*)(int, int, int)>(&Loader::group));
add("generic2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
add("generic3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
add("generic4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
+ add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
+ add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
+#pragma GCC diagnostic pop
}
} // namespace GL
#include <algorithm>
+#include <msp/io/print.h>
#include <msp/strings/format.h>
#include <msp/strings/lexicalcast.h>
#include <msp/strings/utils.h>
else if(str=="TANGENT3")
a = TANGENT3;
else if(str=="BINORMAL3")
- a = BINORMAL3;
+ {
+ IO::print(IO::cerr, "BINORMAL3 attribute is deprecated\n");
+ a = make_indexed_attribute(GENERIC3, 5);
+ }
else if(!convert_attribute(str, "VERTEX", 2, 4, a, VERTEX2) &&
!convert_attribute(str, "GROUP", 1, 4, a, GROUP1) &&
!convert_attribute(str, "WEIGHT", 1, 4, a, WEIGHT1) &&
COLOR4_FLOAT,
NORMAL3 = 18,
TANGENT3 = 26,
- BINORMAL3 = 34,
- GROUP1 = 40,
+ GROUP1 = 32,
GROUP2,
GROUP3,
GROUP4,
- WEIGHT1 = 48,
+ WEIGHT1 = 40,
WEIGHT2,
WEIGHT3,
WEIGHT4,
- TEXCOORD1 = 56,
+ TEXCOORD1 = 48,
TEXCOORD2,
TEXCOORD3,
TEXCOORD4,
- GENERIC1 = 88,
+ GENERIC1 = 80,
GENERIC2,
GENERIC3,
GENERIC4,