forked from bartvdbraak/blender
Fix T49159: missing Cycles tangents for adaptive subdivision.
This commit is contained in:
parent
e767d21b74
commit
cc64872b88
@ -79,7 +79,7 @@ inline void face_split_tri_indices(const int face_flag,
|
||||
|
||||
struct MikkUserData {
|
||||
MikkUserData(const BL::Mesh& b_mesh,
|
||||
BL::MeshTextureFaceLayer *layer,
|
||||
const char *layer_name,
|
||||
const Mesh *mesh,
|
||||
float3 *tangent,
|
||||
float *tangent_sign)
|
||||
@ -89,16 +89,19 @@ struct MikkUserData {
|
||||
tangent(tangent),
|
||||
tangent_sign(tangent_sign)
|
||||
{
|
||||
Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
|
||||
const AttributeSet& attributes = (mesh->subd_faces.size()) ?
|
||||
mesh->subd_attributes : mesh->attributes;
|
||||
|
||||
Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
|
||||
vertex_normal = attr_vN->data_float3();
|
||||
|
||||
if(layer == NULL) {
|
||||
Attribute *attr_orco = mesh->attributes.find(ATTR_STD_GENERATED);
|
||||
if(layer_name == NULL) {
|
||||
Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED);
|
||||
orco = attr_orco->data_float3();
|
||||
mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size);
|
||||
}
|
||||
else {
|
||||
Attribute *attr_uv = mesh->attributes.find(ustring(layer->name()));
|
||||
Attribute *attr_uv = attributes.find(ustring(layer_name));
|
||||
if(attr_uv != NULL) {
|
||||
texface = attr_uv->data_float3();
|
||||
}
|
||||
@ -120,13 +123,47 @@ struct MikkUserData {
|
||||
static int mikk_get_num_faces(const SMikkTSpaceContext *context)
|
||||
{
|
||||
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
|
||||
return userdata->mesh->num_triangles();
|
||||
if(userdata->mesh->subd_faces.size()) {
|
||||
return userdata->mesh->subd_faces.size();
|
||||
}
|
||||
else {
|
||||
return userdata->mesh->num_triangles();
|
||||
}
|
||||
}
|
||||
|
||||
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext * /*context*/,
|
||||
const int /*face_num*/)
|
||||
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context,
|
||||
const int face_num)
|
||||
{
|
||||
return 3;
|
||||
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
|
||||
if(userdata->mesh->subd_faces.size()) {
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
return mesh->subd_faces[face_num].num_corners;
|
||||
}
|
||||
else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
|
||||
{
|
||||
if(mesh->subd_faces.size()) {
|
||||
const Mesh::SubdFace& face = mesh->subd_faces[face_num];
|
||||
return mesh->subd_face_corners[face.start_corner + vert_num];
|
||||
}
|
||||
else {
|
||||
return mesh->triangles[face_num * 3 + vert_num];
|
||||
}
|
||||
}
|
||||
|
||||
static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
|
||||
{
|
||||
if(mesh->subd_faces.size()) {
|
||||
const Mesh::SubdFace& face = mesh->subd_faces[face_num];
|
||||
return face.start_corner + vert_num;
|
||||
}
|
||||
else {
|
||||
return face_num * 3 + vert_num;
|
||||
}
|
||||
}
|
||||
|
||||
static void mikk_get_position(const SMikkTSpaceContext *context,
|
||||
@ -135,9 +172,8 @@ static void mikk_get_position(const SMikkTSpaceContext *context,
|
||||
{
|
||||
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
const int vert_index = mesh->triangles[face_num * 3 + vert_num];
|
||||
const float3 vP = mesh->verts[vert_index];
|
||||
|
||||
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
|
||||
const float3 vP = mesh->verts[vertex_index];
|
||||
P[0] = vP.x;
|
||||
P[1] = vP.y;
|
||||
P[2] = vP.z;
|
||||
@ -148,15 +184,15 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context,
|
||||
const int face_num, const int vert_num)
|
||||
{
|
||||
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
if(userdata->texface != NULL) {
|
||||
const size_t corner_index = face_num * 3 + vert_num;
|
||||
const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
|
||||
float3 tfuv = userdata->texface[corner_index];
|
||||
uv[0] = tfuv.x;
|
||||
uv[1] = tfuv.y;
|
||||
}
|
||||
else if(userdata->orco != NULL) {
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
const size_t vertex_index = mesh->triangles[face_num * 3 + vert_num];
|
||||
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
|
||||
const float3 orco_loc = userdata->orco_loc;
|
||||
const float3 orco_size = userdata->orco_size;
|
||||
const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size;
|
||||
@ -177,13 +213,25 @@ static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3],
|
||||
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
float3 vN;
|
||||
if(mesh->smooth[face_num]) {
|
||||
const size_t vert_index = mesh->triangles[face_num * 3 + vert_num];
|
||||
vN = userdata->vertex_normal[vert_index];
|
||||
if(mesh->subd_faces.size()) {
|
||||
const Mesh::SubdFace& face = mesh->subd_faces[face_num];
|
||||
if(face.smooth) {
|
||||
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
|
||||
vN = userdata->vertex_normal[vertex_index];
|
||||
}
|
||||
else {
|
||||
vN = face.normal(mesh);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const Mesh::Triangle tri = mesh->get_triangle(face_num);
|
||||
vN = tri.compute_normal(&mesh->verts[0]);
|
||||
if(mesh->smooth[face_num]) {
|
||||
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
|
||||
vN = userdata->vertex_normal[vertex_index];
|
||||
}
|
||||
else {
|
||||
const Mesh::Triangle tri = mesh->get_triangle(face_num);
|
||||
vN = tri.compute_normal(&mesh->verts[0]);
|
||||
}
|
||||
}
|
||||
N[0] = vN.x;
|
||||
N[1] = vN.y;
|
||||
@ -196,7 +244,8 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context,
|
||||
const int face_num, const int vert_num)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData *)context->m_pUserData;
|
||||
const size_t corner_index = face_num * 3 + vert_num;
|
||||
const Mesh *mesh = userdata->mesh;
|
||||
const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
|
||||
userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]);
|
||||
if(userdata->tangent_sign != NULL) {
|
||||
userdata->tangent_sign[corner_index] = sign;
|
||||
@ -204,27 +253,27 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context,
|
||||
}
|
||||
|
||||
static void mikk_compute_tangents(const BL::Mesh& b_mesh,
|
||||
BL::MeshTextureFaceLayer *b_layer,
|
||||
const char *layer_name,
|
||||
Mesh *mesh,
|
||||
bool need_sign,
|
||||
bool active_render)
|
||||
{
|
||||
/* Create tangent attributes. */
|
||||
AttributeSet& attributes = (mesh->subd_faces.size()) ?
|
||||
mesh->subd_attributes : mesh->attributes;
|
||||
Attribute *attr;
|
||||
ustring name;
|
||||
if(b_layer != NULL) {
|
||||
name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str());
|
||||
if(layer_name != NULL) {
|
||||
name = ustring((string(layer_name) + ".tangent").c_str());
|
||||
}
|
||||
else {
|
||||
name = ustring("orco.tangent");
|
||||
}
|
||||
if(active_render) {
|
||||
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
|
||||
attr = attributes.add(ATTR_STD_UV_TANGENT, name);
|
||||
}
|
||||
else {
|
||||
attr = mesh->attributes.add(name,
|
||||
TypeDesc::TypeVector,
|
||||
ATTR_ELEMENT_CORNER);
|
||||
attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
|
||||
}
|
||||
float3 *tangent = attr->data_float3();
|
||||
/* Create bitangent sign attribute. */
|
||||
@ -232,8 +281,8 @@ static void mikk_compute_tangents(const BL::Mesh& b_mesh,
|
||||
if(need_sign) {
|
||||
Attribute *attr_sign;
|
||||
ustring name_sign;
|
||||
if(b_layer != NULL) {
|
||||
name_sign = ustring((string(b_layer->name().c_str()) +
|
||||
if(layer_name != NULL) {
|
||||
name_sign = ustring((string(layer_name) +
|
||||
".tangent_sign").c_str());
|
||||
}
|
||||
else {
|
||||
@ -241,18 +290,17 @@ static void mikk_compute_tangents(const BL::Mesh& b_mesh,
|
||||
}
|
||||
|
||||
if(active_render) {
|
||||
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN,
|
||||
name_sign);
|
||||
attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
|
||||
}
|
||||
else {
|
||||
attr_sign = mesh->attributes.add(name_sign,
|
||||
TypeDesc::TypeFloat,
|
||||
ATTR_ELEMENT_CORNER);
|
||||
attr_sign = attributes.add(name_sign,
|
||||
TypeDesc::TypeFloat,
|
||||
ATTR_ELEMENT_CORNER);
|
||||
}
|
||||
tangent_sign = attr_sign->data_float();
|
||||
}
|
||||
/* Setup userdata. */
|
||||
MikkUserData userdata(b_mesh, b_layer, mesh, tangent, tangent_sign);
|
||||
MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
|
||||
/* Setup interface. */
|
||||
SMikkTSpaceInterface sm_interface;
|
||||
memset(&sm_interface, 0, sizeof(sm_interface));
|
||||
@ -399,45 +447,9 @@ static void attr_create_uv_map(Scene *scene,
|
||||
Mesh *mesh,
|
||||
BL::Mesh& b_mesh,
|
||||
const vector<int>& nverts,
|
||||
const vector<int>& face_flags,
|
||||
bool subdivision,
|
||||
bool subdivide_uvs)
|
||||
const vector<int>& face_flags)
|
||||
{
|
||||
if(subdivision) {
|
||||
BL::Mesh::uv_layers_iterator l;
|
||||
int i = 0;
|
||||
|
||||
for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
|
||||
bool active_render = b_mesh.uv_textures[i].active_render();
|
||||
AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
|
||||
ustring name = ustring(l->name().c_str());
|
||||
|
||||
/* UV map */
|
||||
if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
|
||||
Attribute *attr;
|
||||
|
||||
if(active_render)
|
||||
attr = mesh->subd_attributes.add(std, name);
|
||||
else
|
||||
attr = mesh->subd_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
|
||||
|
||||
if(subdivide_uvs) {
|
||||
attr->flags |= ATTR_SUBDIVIDED;
|
||||
}
|
||||
|
||||
BL::Mesh::polygons_iterator p;
|
||||
float3 *fdata = attr->data_float3();
|
||||
|
||||
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
int n = p->loop_total();
|
||||
for(int j = 0; j < n; j++) {
|
||||
*(fdata++) = get_float3(l->data[p->loop_start() + j].uv());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(b_mesh.tessface_uv_textures.length() != 0) {
|
||||
if(b_mesh.tessface_uv_textures.length() != 0) {
|
||||
BL::Mesh::tessface_uv_textures_iterator l;
|
||||
|
||||
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
|
||||
@ -512,7 +524,7 @@ static void attr_create_uv_map(Scene *scene,
|
||||
bool need_sign = (mesh->need_attribute(scene, sign_name) ||
|
||||
mesh->need_attribute(scene, sign_std));
|
||||
mikk_compute_tangents(b_mesh,
|
||||
&(*l),
|
||||
l->name().c_str(),
|
||||
mesh,
|
||||
need_sign,
|
||||
active_render);
|
||||
@ -532,6 +544,88 @@ static void attr_create_uv_map(Scene *scene,
|
||||
}
|
||||
}
|
||||
|
||||
static void attr_create_subd_uv_map(Scene *scene,
|
||||
Mesh *mesh,
|
||||
BL::Mesh& b_mesh,
|
||||
const vector<int>& nverts,
|
||||
const vector<int>& face_flags,
|
||||
bool subdivide_uvs)
|
||||
{
|
||||
if(b_mesh.uv_layers.length() != 0) {
|
||||
BL::Mesh::uv_layers_iterator l;
|
||||
int i = 0;
|
||||
|
||||
for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
|
||||
bool active_render = b_mesh.uv_textures[i].active_render();
|
||||
AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
|
||||
ustring uv_name = ustring(l->name().c_str());
|
||||
AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT
|
||||
: ATTR_STD_NONE;
|
||||
ustring tangent_name = ustring(
|
||||
(string(l->name().c_str()) + ".tangent").c_str());
|
||||
|
||||
/* Denotes whether UV map was requested directly. */
|
||||
const bool need_uv = mesh->need_attribute(scene, uv_name) ||
|
||||
mesh->need_attribute(scene, uv_std);
|
||||
/* Denotes whether tangent was requested directly. */
|
||||
const bool need_tangent =
|
||||
mesh->need_attribute(scene, tangent_name) ||
|
||||
(active_render && mesh->need_attribute(scene, tangent_std));
|
||||
|
||||
Attribute *uv_attr = NULL;
|
||||
|
||||
/* UV map */
|
||||
if(need_uv || need_tangent) {
|
||||
if(active_render)
|
||||
uv_attr = mesh->subd_attributes.add(uv_std, uv_name);
|
||||
else
|
||||
uv_attr = mesh->subd_attributes.add(uv_name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
|
||||
|
||||
if(subdivide_uvs) {
|
||||
uv_attr->flags |= ATTR_SUBDIVIDED;
|
||||
}
|
||||
|
||||
BL::Mesh::polygons_iterator p;
|
||||
float3 *fdata = uv_attr->data_float3();
|
||||
|
||||
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
int n = p->loop_total();
|
||||
for(int j = 0; j < n; j++) {
|
||||
*(fdata++) = get_float3(l->data[p->loop_start() + j].uv());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* UV tangent */
|
||||
if(need_tangent) {
|
||||
AttributeStandard sign_std =
|
||||
(active_render)? ATTR_STD_UV_TANGENT_SIGN
|
||||
: ATTR_STD_NONE;
|
||||
ustring sign_name = ustring(
|
||||
(string(l->name().c_str()) + ".tangent_sign").c_str());
|
||||
bool need_sign = (mesh->need_attribute(scene, sign_name) ||
|
||||
mesh->need_attribute(scene, sign_std));
|
||||
mikk_compute_tangents(b_mesh,
|
||||
l->name().c_str(),
|
||||
mesh,
|
||||
need_sign,
|
||||
active_render);
|
||||
}
|
||||
/* Remove temporarily created UV attribute. */
|
||||
if(!need_uv && uv_attr != NULL) {
|
||||
mesh->subd_attributes.remove(uv_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
|
||||
bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
|
||||
mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
|
||||
if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
|
||||
mesh->subd_attributes.remove(ATTR_STD_GENERATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create vertex pointiness attributes. */
|
||||
|
||||
/* Compare vertices by sum of their coordinates. */
|
||||
@ -857,7 +951,13 @@ static void create_mesh(Scene *scene,
|
||||
*/
|
||||
attr_create_pointiness(scene, mesh, b_mesh, subdivision);
|
||||
attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
|
||||
attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs);
|
||||
|
||||
if(subdivision) {
|
||||
attr_create_subd_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivide_uvs);
|
||||
}
|
||||
else {
|
||||
attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
|
||||
}
|
||||
|
||||
/* for volume objects, create a matrix to transform from object space to
|
||||
* mesh texture space. this does not work with deformations but that can
|
||||
|
Loading…
Reference in New Issue
Block a user