Commit: 0740ae9fe5d25e90c6d8c4fe726a1c2d89a3bcf2 Author: Lukas Tönne Date: Sat Aug 9 19:28:38 2014 +0200 Branches: hair_system https://developer.blender.org/rB0740ae9fe5d25e90c6d8c4fe726a1c2d89a3bcf2
Added regular display options for hair systems. Only has a mode setting so far, which defines the overall style of display. =================================================================== M release/scripts/startup/bl_ui/properties_data_modifier.py M source/blender/editors/space_view3d/drawhair.c M source/blender/makesdna/DNA_hair_types.h M source/blender/makesdna/DNA_modifier_types.h M source/blender/makesrna/intern/rna_hair.c M source/blender/makesrna/intern/rna_modifier.c =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index d9b11f7..e81210a 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1225,6 +1225,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): def HAIR(self, layout, ob, md): hsys = md.hair_system params = hsys.params + display = hsys.display col = layout.column() col.separator() @@ -1261,12 +1262,17 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.separator() + col.label("Display:") + row = col.row() + row.prop(display, "mode", expand=True) + + col.separator() + col.prop(md, "show_debug") col2 = col.column() col2.active = md.show_debug col2.prop(md, "show_debug_contacts") col2.prop(md, "show_debug_size") - col2.prop(md, "show_debug_cylinders") col2.prop(md, "show_debug_roots") col2.prop(md, "show_debug_frames") col2.prop(md, "show_debug_smoothing") diff --git a/source/blender/editors/space_view3d/drawhair.c b/source/blender/editors/space_view3d/drawhair.c index 012d73e..f37e022 100644 --- a/source/blender/editors/space_view3d/drawhair.c +++ b/source/blender/editors/space_view3d/drawhair.c @@ -83,6 +83,203 @@ static void draw_hair_curve(HairSystem *UNUSED(hsys), HairCurve *hair) glPointSize(1.0f); } +static void count_hairs(HairSystem *hsys, int *totpoints, int *validhairs) +{ + HairCurve *hair; + int i; + + *totpoints = *validhairs = 0; + for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) { + if (hair->totpoints > 1) { + *totpoints += hair->totpoints; + *validhairs += 1; + } + } +} + +/* preview of hairs as cylinders */ +/* XXX warning, computation here hurts a lot! */ +static void draw_hair_hulls(HairSystem *hsys) +{ + HairCurve *hair; + HairPoint *point, *next_point; + int k, i, s; + float upvec[] = {0.0f, 0.0f, 1.0f}; + float sidevec[] = {1.0f, 0.0f, 0.0f}; + + float radius_factor = 1.0f; + /* number of cylinder subdivisions */ + int subdiv = 8; + + int totpoints, validhairs; + int tot_verts, tot_elems; + + /* vertex array variables */ + float (*vert_data)[3]; + unsigned int *elem_data; + unsigned int offset = 0; + unsigned int elem_offset = 0; + + static unsigned int hairbuf = 0; + static unsigned int hairelem = 0; + + count_hairs(hsys, &totpoints, &validhairs); + /* twice for all for the normals */ + tot_verts = totpoints * 2 * subdiv; + tot_elems = (totpoints - validhairs) * 6 * subdiv; + + /* set up OpenGL code */ + if (!hairbuf) { + glGenBuffers(1, &hairbuf); + glGenBuffers(1, &hairelem); + } + glBindBuffer(GL_ARRAY_BUFFER, hairbuf); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hairelem); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * tot_verts, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * tot_elems, NULL, GL_DYNAMIC_DRAW); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), NULL); + glNormalPointer(GL_FLOAT, 6 * sizeof(float), (GLubyte *)NULL + 3 * sizeof(float)); + + vert_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elem_data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + + /* generate the data and copy to the display buffers */ + for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) { + float normal[3]; + float dir[3]; + float tangent[3]; + unsigned int cur_offset = offset / 2; + + if (hair->totpoints == 1) + continue; + point = hair->points; + next_point = hair->points + 1; + + sub_v3_v3v3(dir, next_point->co, point->co); + normalize_v3_v3(normal, dir); + + /* calculate a tangent by cross product between z vector and normal */ + if (fabs(dot_v3v3(normal, upvec)) < 0.99f) { + cross_v3_v3v3(tangent, normal, upvec); + } + else + cross_v3_v3v3(tangent, normal, sidevec); + + normalize_v3(tangent); + + for (k = 0; k < hair->totpoints - 1; ++point, ++next_point, ++k) { + float pivot_axis[3]; + float new_normal[3]; + float cosine; + /* first step is to compute a tangent vector to the surface and rotate around the normal */ + sub_v3_v3v3(dir, next_point->co, point->co); + normalize_v3_v3(new_normal, dir); + cosine = dot_v3v3(new_normal, normal); + + cur_offset = offset / 2; + + /* if needed rotate the previous original tangent to the new frame by using cross product between current + * and previous segment */ + if (fabs(cosine) < 0.999f) { + float rot_quat[4]; + float halfcosine; + float halfsine; + /* substitute by cosine of half angle because we are doing smooth-like interpolation */ + cosine = sqrt(0.5 + cosine * 0.5); + + /* half angle cosines needed for quaternion rotation */ + halfcosine = sqrt(0.5 + cosine * 0.5); + halfsine = sqrt(0.5 - cosine * 0.5); + + cross_v3_v3v3(pivot_axis, normal, new_normal); + normalize_v3(pivot_axis); + + rot_quat[0] = halfcosine; + rot_quat[1] = halfsine * pivot_axis[0]; + rot_quat[2] = halfsine * pivot_axis[1]; + rot_quat[3] = halfsine * pivot_axis[2]; + + mul_qt_v3(rot_quat, tangent); + + /* also rotate by the half amount the rotation axis */ + copy_v3_v3(pivot_axis, normal); + mul_qt_v3(rot_quat, pivot_axis); + + normalize_v3(tangent); + } + else + copy_v3_v3(pivot_axis, normal); + + copy_v3_v3(normal, new_normal); + + /* and repeat */ + copy_v3_v3(vert_data[offset], tangent); + mul_v3_fl(vert_data[offset], point->radius * radius_factor); + add_v3_v3(vert_data[offset++], point->co); + copy_v3_v3(vert_data[offset++], tangent); + + /* create quaternion to rotate tangent around normal */ + for (s = 1; s < subdiv; s++) { + float v_nor[3]; + float rot_quat[4]; + float half_angle = (M_PI * s) / subdiv; + float sine = sin(half_angle); + + copy_v3_v3(v_nor, tangent); + + rot_quat[0] = cos(half_angle); + rot_quat[1] = sine * pivot_axis[0]; + rot_quat[2] = sine * pivot_axis[1]; + rot_quat[3] = sine * pivot_axis[2]; + + mul_qt_v3(rot_quat, v_nor); + copy_v3_v3(vert_data[offset], v_nor); + mul_v3_fl(vert_data[offset], point->radius * radius_factor); + add_v3_v3(vert_data[offset++], point->co); + copy_v3_v3(vert_data[offset++], v_nor); + } + + for (s = 0; s < subdiv; s++) { + elem_data[elem_offset++] = cur_offset + s; + elem_data[elem_offset++] = cur_offset + s + subdiv; + elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv; + + elem_data[elem_offset++] = cur_offset + s + subdiv; + elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv; + elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv + subdiv; + } + } + + /* finally add the last point */ + for (s = 0; s < subdiv; s++) { + add_v3_v3v3(vert_data[offset], vert_data[offset - 2 * subdiv], dir); + offset++; + copy_v3_v3(vert_data[offset], vert_data[offset - 2 * subdiv]); + offset++; + } + + } + + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + glEnable(GL_LIGHTING); + /* draw */ + glShadeModel(GL_SMOOTH); + glDrawElements(GL_TRIANGLES, elem_offset, GL_UNSIGNED_INT, NULL); + glDisable(GL_LIGHTING); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + /* called from drawobject.c, return true if nothing was drawn */ bool draw_hair_system(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Base *base, HairSystem *hsys) { @@ -95,8 +292,18 @@ bool draw_hair_system(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Ba glLoadMatrixf(rv3d->viewmat); glMultMatrixf(ob->obmat); - for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) { - draw_hair_curve(hsys, hair); + switch (hsys->display.mode) { + case HAIR_DISPLAY_LINE: + for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) { + draw_hair_curve(hsys, hair); + } + break; + case HAIR_DISPLAY_RENDER: + // TODO + break; + case HAIR_DISPLAY_HULL: + draw_hair_hulls(hsys); + break; } return retval; @@ -109,7 +316,6 @@ bool draw_hair_system(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Ba #define SHOW_ROOTS #define SHOW_FRAMES //#define SHOW_SMOOTHING -#define SHOW_CYLINDERS #define SHOW_CONTACTS static void draw_hair_debug_points(HairSystem *hsys, HAIR_SolverDebugPoint *dpoints, int dtotpoints) @@ -353,190 +559,6 @@ static void draw_hair_debug_contacts(HairSystem *UNUSED(hsys), HAIR_SolverDebugC #endif } -/* debug preview of hairs as cylinders. warning, computation here hurts a lot! */ -static void draw_hair_debug_cylinders(HairSystem *hsys, int totpoints, int valid_points) -{ -#ifdef SHOW_CYLINDERS - HairCurve *hair; - HairPoint *point, *next_point; - int k, i, s; - float upvec[] = {0.0f, 0.0f, 1.0f}; - float sidevec[] = {1.0f, 0.0f, 0.0f}; - - float radius_factor = 1.0f; - /* number of cylinder subdivisions */ - int subdiv = 8; - - /* vertex array variables */ - float (*vert_data)[3]; - unsigned int *elem_data; - unsigned int offset = 0; - unsigned int elem_offset = 0; - - /* twive for all for the normals */ - int tot_verts = totpoints * 2 * subdiv; - int tot_elems = (totpoints - valid_points) * 6 * subdiv; - - static unsigned int hairbuf = 0; - static unsigned int hairelem = 0; - - /* set up OpenGL code */ - if (!hairbuf) { - glGenBuffers(1, &hairbuf); - glGenBuffers(1, &hairelem); - } - glBindBuffer(GL_ARRAY_BUFFER, hairbuf); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hairelem); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * tot_verts, NULL, GL_DYNAMIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * tot_elems, NULL, GL_DYNAMIC_DRAW); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), NULL); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), (GLubyte *)NULL + 3 * sizeof(float)); - - vert_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elem_data = glMapB @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs