Step 3/3, merging subdivision/bone creation methods using iterators

This also adds a special Embedding option called "Peel Objects". This option makes the embedding snap consider objects as whole, taking the first and last hit of each of them to calculate the embedding point (instead of peeling with first/second, third/fourth and so on). This option is useful if you have mecanical pieces with lots of details (as single objects) and want to put bones in the middle (think of adding bones to a mecha, for example).
This commit is contained in:
Martin Poirier 2008-11-29 20:37:10 +00:00
parent d467158158
commit e2fb12ea18
11 changed files with 859 additions and 704 deletions

View File

@ -62,13 +62,25 @@ typedef struct BArc {
struct BArcIterator;
void* IT_head(void* iter);
void* IT_tail(void* iter);
void* IT_peek(void* iter, int n);
void* IT_next(void* iter);
void* IT_nextN(void* iter, int n);
void* IT_previous(void* iter);
int IT_stopped(void* iter);
typedef void* (*HeadFct)(void* iter);
typedef void* (*TailFct)(void* iter);
typedef void* (*PeekFct)(void* iter, int n);
typedef void* (*NextFct)(void* iter);
typedef void* (*NextNFct)(void* iter, int n);
typedef void* (*PreviousFct)(void* iter);
typedef int (*StoppedFct)(void* iter);
typedef int (*StoppedFct)(void* iter);
typedef struct BArcIterator {
HeadFct head;
TailFct tail;
PeekFct peek;
NextFct next;
NextNFct nextN;

View File

@ -465,8 +465,6 @@ int subtreeShape(BNode *node, BArc *rootArc, int include_root)
int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root)
{
BNode *test_node;
BLI_flagNodes(graph, 0);
return subtreeShape(node, rootArc, include_root);
}
@ -1090,3 +1088,56 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit)
}
}
void* IT_head(void* arg)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->head(iter);
}
void* IT_tail(void* arg)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->tail(iter);
}
void* IT_peek(void* arg, int n)
{
BArcIterator *iter = (BArcIterator*)arg;
if (iter->index + n < 0)
{
return iter->head(iter);
}
else if (iter->index + n >= iter->length)
{
return iter->tail(iter);
}
else
{
return iter->peek(iter, n);
}
}
void* IT_next(void* arg)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->next(iter);
}
void* IT_nextN(void* arg, int n)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->nextN(iter, n);
}
void* IT_previous(void* arg)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->previous(iter);
}
int IT_stopped(void* arg)
{
BArcIterator *iter = (BArcIterator*)arg;
return iter->stopped(iter);
}

View File

@ -0,0 +1,44 @@
/**
* $Id: $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BIF_GENERATE_H
#define BIF_GENERATE_H
struct EditBone;
struct BArcIterator;
struct bArmature;
struct ListBase;
typedef int(NextSubdivisionFunc)(struct BArcIterator*, int, int, float[3], float[3]);
float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0[3], float n[3]);
int nextFixedSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
int nextLengthSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
int nextCorrelationSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
struct EditBone * subdivideArcBy(struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion);
void setBoneRollFromNormal(struct EditBone *bone, float *no, float invmat[][4], float tmat[][3]);
#endif /* BIF_GENERATE_H */

View File

@ -28,7 +28,7 @@
#ifndef REEB_H_
#define REEB_H_
#define WITH_BF_REEB
//#define WITH_BF_REEB
#include "DNA_listBase.h"
@ -120,6 +120,8 @@ typedef struct ReebArc {
} ReebArc;
typedef struct ReebArcIterator {
HeadFct head;
TailFct tail;
PeekFct peek;
NextFct next;
NextNFct nextN;
@ -151,9 +153,9 @@ void renormalizeWeight(struct EditMesh *em, float newmax);
ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions);
ReebGraph * newReebGraph();
void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end);
void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start);
void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
void initArcIterator2(BArcIterator *iter, struct ReebArc *arc, int start, int end);
void initArcIteratorStart(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start);
/* Filtering */
void filterNullReebGraph(ReebGraph *rg);

View File

@ -728,6 +728,7 @@ typedef struct Scene {
/* scene->snap_flag */
#define SCE_SNAP 1
#define SCE_SNAP_ROTATE 2
#define SCE_SNAP_PEEL_OBJECT 4
/* scene->snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1

View File

@ -2294,7 +2294,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl)
static char joint_label[32];
uiBlock *block;
uiBut *but;
int yco = 70, height = 140;
int yco = 130, height = 140;
int nb_joints;
/* replace with check call to sketching lib */
@ -2382,7 +2382,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl)
BLI_snprintf(joint_label, 32, "%i joints", nb_joints);
uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, "");
yco -= 20;
uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_DIFF, "Peel Objects", 10, yco, 200, 20, &G.scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
if(yco < 0) uiNewPanelHeight(block, height-yco);
}

View File

@ -93,6 +93,7 @@
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BIF_transform.h"
#include "BIF_generate.h"
#include "BDR_editobject.h"
#include "BDR_drawobject.h"
@ -4655,7 +4656,8 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
EditBone *lastBone = NULL;
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
float *previous = NULL, *current = NULL;
EditBone *child = NULL;
EditBone *parent = NULL;
@ -4668,18 +4670,18 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
root = parent;
initArcIterator(&iter, arc, head);
iter.next(&iter);
previous = iter.p;
initArcIterator(iter, arc, head);
IT_next(iter);
previous = iter->p;
for (iter.next(&iter);
iter.stopped(&iter) == 0;
previous = iter.p, iter.next(&iter))
for (IT_next(iter);
IT_stopped(iter) == 0;
previous = iter->p, IT_next(iter))
{
float vec1[3], vec2[3];
float len1, len2;
current = iter.p;
current = iter->p;
VecSubf(vec1, previous, parent->head);
VecSubf(vec2, current, previous);
@ -4716,173 +4718,26 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
return lastBone;
}
float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3])
EditBone * test_subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
{
int len = 2 + abs(end - start);
if (len > 2)
{
ReebArcIterator iter;
float avg_t = 0.0f;
float s_t = 0.0f;
float s_xyz = 0.0f;
/* First pass, calculate average */
for (initArcIterator2(&iter, arc, start, end), iter.next(&iter);
iter.stopped(&iter) == 0;
iter.next(&iter))
{
float v[3];
VecSubf(v, iter.p, v0);
avg_t += Inpf(v, n);
}
avg_t /= Inpf(n, n);
avg_t += 1.0f; /* adding start (0) and end (1) values */
avg_t /= len;
/* Second pass, calculate s_xyz and s_t */
for (initArcIterator2(&iter, arc, start, end), iter.next(&iter);
iter.stopped(&iter) == 0;
iter.next(&iter))
{
float v[3], d[3];
float dt;
VecSubf(v, iter.p, v0);
Projf(d, v, n);
VecSubf(v, v, d);
dt = VecLength(d) - avg_t;
s_t += dt * dt;
s_xyz += Inpf(v, v);
}
/* adding start(0) and end(1) values to s_t */
s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
return s_xyz / s_t;
}
else
{
return 0;
}
}
float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3])
{
ReebArcIterator iter;
float max_dist = 0;
/* calculate maximum distance */
for (initArcIterator2(&iter, arc, start, end), iter.next(&iter);
iter.stopped(&iter) == 0;
iter.next(&iter))
{
float v1[3], v2[3], c[3];
float dist;
VecSubf(v1, head, tail);
VecSubf(v2, iter.p, tail);
Crossf(c, v1, v2);
dist = Inpf(c, c) / Inpf(v1, v1);
max_dist = dist > max_dist ? dist : max_dist;
}
return max_dist;
}
EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
{
ReebArcIterator iter;
float n[3];
float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
EditBone *lastBone = NULL;
/* init iterator to get start and end from head */
initArcIterator(&iter, arc, head);
/* Calculate overall */
VecSubf(n, arc->buckets[iter.end].p, head->p);
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
{
EditBone *child = NULL;
EditBone *parent = NULL;
float normal[3] = {0, 0, 0};
float avg_normal[3];
int total = 0;
int boneStart = iter.start;
float invmat[4][4] = { {1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}};
float tmat[3][3] = { {1, 0, 0},
{0, 1, 0},
{0, 0, 1}};
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
bArmature *arm= G.obedit->data;
parent = add_editbone("Bone");
parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
VECCOPY(parent->head, head->p);
initArcIterator(iter, arc, head);
while(iter.next(&iter))
{
float btail[3];
float value = 0;
if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
{
VECCOPY(btail, iter.p);
}
else
{
float length;
/* Calculate normal */
VecSubf(n, iter.p, parent->head);
length = Normalize(n);
total += 1;
VecAddf(normal, normal, n);
VECCOPY(avg_normal, normal);
VecMulf(avg_normal, 1.0f / total);
VECCOPY(btail, avg_normal);
VecMulf(btail, length);
VecAddf(btail, btail, parent->head);
}
if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
{
value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
}
else
{
float n[3];
VecSubf(n, btail, parent->head);
value = calcVariance(arc, boneStart, iter.index, parent->head, n);
}
if (value > ADAPTIVE_THRESHOLD)
{
VECCOPY(parent->tail, btail);
child = add_editbone("Bone");
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
parent = child; // new child is next parent
boneStart = iter.index; // start from end
normal[0] = normal[1] = normal[2] = 0;
total = 0;
}
}
VECCOPY(parent->tail, tail->p);
lastBone = parent; /* set last bone in the chain */
lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision);
}
return lastBone;
@ -4915,106 +4770,26 @@ float arcLengthRatio(ReebArc *arc)
return embedLength / arcLength;
}
EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
EditBone * test_subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
{
EditBone *lastBone = NULL;
if ((G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
{
ReebArcIterator iter;
float *previous = NULL;
EditBone *child = NULL;
EditBone *parent = NULL;
float lengthLimit = G.scene->toolsettings->skgen_length_limit;
int same = 0;
float invmat[4][4] = { {1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}};
float tmat[3][3] = { {1, 0, 0},
{0, 1, 0},
{0, 0, 1}};
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
bArmature *arm= G.obedit->data;
parent = add_editbone("Bone");
parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
VECCOPY(parent->head, head->p);
initArcIterator(&iter, arc, head);
iter.next(&iter);
initArcIterator(iter, arc, head);
while (iter.stopped(&iter) == 0)
{
float *vec0 = NULL;
float *vec1 = iter.p;
/* first bucket. Previous is head */
if (previous == NULL)
{
vec0 = head->p;
}
/* Previous is a valid bucket */
else
{
vec0 = previous;
}
/* If lengthLimit hits the current segment */
if (VecLenf(vec1, parent->head) > lengthLimit)
{
if (same == 0)
{
float dv[3], off[3];
float a, b, c, f;
/* Solve quadratic distance equation */
VecSubf(dv, vec1, vec0);
a = Inpf(dv, dv);
VecSubf(off, vec0, parent->head);
b = 2 * Inpf(dv, off);
c = Inpf(off, off) - (lengthLimit * lengthLimit);
f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
//printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
if (isnan(f) == 0 && f < 1.0f)
{
VECCOPY(parent->tail, dv);
VecMulf(parent->tail, f);
VecAddf(parent->tail, parent->tail, vec0);
}
else
{
VECCOPY(parent->tail, vec1);
}
}
else
{
float dv[3];
VecSubf(dv, vec1, vec0);
Normalize(dv);
VECCOPY(parent->tail, dv);
VecMulf(parent->tail, lengthLimit);
VecAddf(parent->tail, parent->tail, parent->head);
}
child = add_editbone("Bone");
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
parent = child; // new child is next parent
same = 1; // mark as same
}
else
{
previous = iter.p;
iter.next(&iter);
same = 0; // Reset same
}
}
VECCOPY(parent->tail, tail->p);
lastBone = parent; /* set last bone in the chain */
lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision);
}
return lastBone;
@ -5107,13 +4882,13 @@ void generateSkeletonFromReebGraph(ReebGraph *rg)
switch(G.scene->toolsettings->skgen_subdivisions[i])
{
case SKGEN_SUB_LENGTH:
lastBone = subdivideByLength(arc, head, tail);
lastBone = test_subdivideByLength(arc, head, tail);
break;
case SKGEN_SUB_ANGLE:
lastBone = subdivideByAngle(arc, head, tail);
break;
case SKGEN_SUB_CORRELATION:
lastBone = subdivideByCorrelation(arc, head, tail);
lastBone = test_subdivideByCorrelation(arc, head, tail);
break;
}
}

View File

@ -0,0 +1,327 @@
/**
* $Id: editarmature_generate.c $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
* editarmature.c: Interface for creating and posing armature objects
*/
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_graph.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BIF_editarmature.h"
#include "BIF_generate.h"
void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3])
{
if (no != NULL && !VecIsNull(no))
{
float tangent[3], cotangent[3], normal[3];
VECCOPY(normal, no);
Mat3MulVecfl(tmat, normal);
VecSubf(tangent, bone->tail, bone->head);
Crossf(cotangent, tangent, normal);
Crossf(normal, cotangent, tangent);
Normalize(normal);
bone->roll = rollBoneToVector(bone, normal);
}
}
float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
{
int len = 2 + abs(end - start);
if (len > 2)
{
float avg_t = 0.0f;
float s_t = 0.0f;
float s_xyz = 0.0f;
int i;
/* First pass, calculate average */
for (i = start; i <= end; i++)
{
float v[3];
IT_peek(iter, i);
VecSubf(v, iter->p, v0);
avg_t += Inpf(v, n);
}
avg_t /= Inpf(n, n);
avg_t += 1.0f; /* adding start (0) and end (1) values */
avg_t /= len;
/* Second pass, calculate s_xyz and s_t */
for (i = start; i <= end; i++)
{
float v[3], d[3];
float dt;
IT_peek(iter, i);
VecSubf(v, iter->p, v0);
Projf(d, v, n);
VecSubf(v, v, d);
dt = VecLength(d) - avg_t;
s_t += dt * dt;
s_xyz += Inpf(v, v);
}
/* adding start(0) and end(1) values to s_t */
s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
return 1.0f - s_xyz / s_t;
}
else
{
return 1.0f;
}
}
int nextFixedSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
{
static float stroke_length = 0;
static float current_length;
static char n;
float *v1, *v2;
float length_threshold;
int i;
if (stroke_length == 0)
{
current_length = 0;
IT_peek(iter, start);
v1 = iter->p;
for (i = start + 1; i <= end; i++)
{
IT_peek(iter, i);
v2 = iter->p;
stroke_length += VecLenf(v1, v2);
v1 = v2;
}
n = 0;
current_length = 0;
}
n++;
length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number;
IT_peek(iter, start);
v1 = iter->p;
/* < and not <= because we don't care about end, it is P_EXACT anyway */
for (i = start + 1; i < end; i++)
{
IT_peek(iter, i);
v2 = iter->p;
current_length += VecLenf(v1, v2);
if (current_length >= length_threshold)
{
VECCOPY(p, v2);
return i;
}
v1 = v2;
}
stroke_length = 0;
return -1;
}
int nextCorrelationSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
{
float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit;
float *start_p;
float n[3];
int i;
IT_peek(iter, start);
start_p = iter->p;
for (i = start + 2; i <= end; i++)
{
/* Calculate normal */
IT_peek(iter, i);
VecSubf(n, iter->p, head);
if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
{
IT_peek(iter, i - 1);
VECCOPY(p, iter->p);
return i - 1;
}
}
return -1;
}
int nextLengthSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
{
float lengthLimit = G.scene->toolsettings->skgen_length_limit;
int same = 1;
int i;
i = start + 1;
while (i <= end)
{
float *vec0;
float *vec1;
IT_peek(iter, i - 1);
vec0 = iter->p;
IT_peek(iter, i);
vec1 = iter->p;
/* If lengthLimit hits the current segment */
if (VecLenf(vec1, head) > lengthLimit)
{
if (same == 0)
{
float dv[3], off[3];
float a, b, c, f;
/* Solve quadratic distance equation */
VecSubf(dv, vec1, vec0);
a = Inpf(dv, dv);
VecSubf(off, vec0, head);
b = 2 * Inpf(dv, off);
c = Inpf(off, off) - (lengthLimit * lengthLimit);
f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
//printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
if (isnan(f) == 0 && f < 1.0f)
{
VECCOPY(p, dv);
VecMulf(p, f);
VecAddf(p, p, vec0);
}
else
{
VECCOPY(p, vec1);
}
}
else
{
float dv[3];
VecSubf(dv, vec1, vec0);
Normalize(dv);
VECCOPY(p, dv);
VecMulf(p, lengthLimit);
VecAddf(p, p, head);
}
return i - 1; /* restart at lower bound */
}
else
{
i++;
same = 0; // Reset same
}
}
return -1;
}
EditBone * subdivideArcBy(bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
{
EditBone *lastBone = NULL;
EditBone *child = NULL;
EditBone *parent = NULL;
int bone_start = 0;
int end = iter->length;
int index;
IT_head(iter);
parent = addEditBone("Bone", editbones, arm);
VECCOPY(parent->head, iter->p);
index = next_subdividion(iter, bone_start, end, parent->head, parent->tail);
while (index != -1)
{
IT_peek(iter, index);
child = addEditBone("Bone", editbones, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
/* going to next bone, fix parent */
Mat4MulVecfl(invmat, parent->tail);
Mat4MulVecfl(invmat, parent->head);
setBoneRollFromNormal(parent, iter->no, invmat, tmat);
parent = child; // new child is next parent
bone_start = index; // start next bone from current index
index = next_subdividion(iter, bone_start, end, parent->head, parent->tail);
}
iter->tail(iter);
VECCOPY(parent->tail, iter->p);
/* fix last bone */
Mat4MulVecfl(invmat, parent->tail);
Mat4MulVecfl(invmat, parent->head);
setBoneRollFromNormal(parent, iter->no, invmat, tmat);
lastBone = parent;
return lastBone;
}

View File

@ -1655,100 +1655,6 @@ static EditBone *add_editbonetolist(char *name, ListBase *list)
return bone;
}
EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, ReebNode *tail)
{
ReebArcIterator iter;
float n[3];
float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
EditBone *lastBone = NULL;
/* init iterator to get start and end from head */
initArcIterator(&iter, arc, head);
/* Calculate overall */
VecSubf(n, arc->buckets[iter.end].p, head->p);
if (1 /* G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION */ )
{
EmbedBucket *bucket = NULL;
EmbedBucket *previous = NULL;
EditBone *child = NULL;
EditBone *parent = NULL;
float normal[3] = {0, 0, 0};
float avg_normal[3];
int total = 0;
int boneStart = iter.start;
parent = add_editbonetolist("Bone", rigg->editbones);
parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
VECCOPY(parent->head, head->p);
for (previous = iter.next(&iter), bucket = iter.next(&iter);
bucket;
previous = bucket, bucket = iter.next(&iter))
{
float btail[3];
float value = 0;
if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
{
VECCOPY(btail, bucket->p);
}
else
{
float length;
/* Calculate normal */
VecSubf(n, bucket->p, parent->head);
length = Normalize(n);
total += 1;
VecAddf(normal, normal, n);
VECCOPY(avg_normal, normal);
VecMulf(avg_normal, 1.0f / total);
VECCOPY(btail, avg_normal);
VecMulf(btail, length);
VecAddf(btail, btail, parent->head);
}
if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
{
value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
}
else
{
float n[3];
VecSubf(n, btail, parent->head);
value = calcVariance(arc, boneStart, iter.index, parent->head, n);
}
if (value > ADAPTIVE_THRESHOLD)
{
VECCOPY(parent->tail, btail);
child = add_editbonetolist("Bone", rigg->editbones);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
parent = child; // new child is next parent
boneStart = iter.index; // start from end
normal[0] = normal[1] = normal[2] = 0;
total = 0;
}
}
VECCOPY(parent->tail, tail->p);
lastBone = parent; /* set last bone in the chain */
}
return lastBone;
}
void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
{
while (node->multi_level > multi_level_limit && node->link_up)
@ -1775,7 +1681,7 @@ void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level
earc->flag = ARC_USED;
generateBonesForArc(rigg, earc, node, other);
//generateBonesForArc(rigg, earc, node, other);
generateMissingArcsFromNode(rigg, other, multi_level_limit);
}
}
@ -2048,7 +1954,7 @@ static void printPositions(int *positions, int nb_positions)
#define MAX_COST FLT_MAX /* FIX ME */
static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i0, int i1)
static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1)
{
EmbedBucket *bucket = NULL;
float max_dist = 0;
@ -2068,7 +1974,7 @@ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i
{
float dist;
bucket = iter->peek(iter, j);
bucket = IT_peek(iter, j);
VecSubf(v2, bucket->p, vec1);
@ -2128,7 +2034,7 @@ static float costLength(float original_length, float current_length)
}
}
static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
{
float vec[3];
float length;
@ -2139,7 +2045,7 @@ static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, Ri
return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
}
static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2)
static float calcCostAngleLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2)
{
float vec_second[3], vec_first[3];
float length2;
@ -2189,7 +2095,7 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions,
}
}
static MemoNode * solveJoints(MemoNode *table, ReebArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left)
static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left)
{
MemoNode *node;
int index = indexMemoNode(nb_positions, previous, current, joints_left);
@ -2277,7 +2183,8 @@ static int testFlipArc(RigArc *iarc, RigNode *inode_start)
static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
RigEdge *edge;
EmbedBucket *bucket = NULL;
ReebNode *node_start, *node_end;
@ -2332,15 +2239,15 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
positions_cache[0] = node_start->p;
positions_cache[nb_positions + 1] = node_end->p;
initArcIterator(&iter, earc, node_start);
initArcIterator(iter, earc, node_start);
for (i = 1; i <= nb_positions; i++)
{
EmbedBucket *bucket = iter.peek(&iter, i);
EmbedBucket *bucket = IT_peek(iter, i);
positions_cache[i] = bucket->p;
}
result = solveJoints(table, &iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints);
result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints);
min_cost = result->weight;
copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
@ -2422,7 +2329,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
}
/* calculating cost */
initArcIterator(&iter, earc, node_start);
initArcIterator(iter, earc, node_start);
vec0 = NULL;
vec1 = node_start->p;
@ -2443,13 +2350,13 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
if (i < nb_joints)
{
i2 = positions[i];
bucket = iter.peek(&iter, positions[i]);
bucket = IT_peek(iter, positions[i]);
vec2 = bucket->p;
vec_cache[i + 1] = vec2; /* update cache for updated position */
}
else
{
i2 = iter.length;
i2 = iter->length;
vec2 = node_end->p;
}
@ -2485,7 +2392,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
new_cost += costLength(edge->length, length2);
/* Distance Cost */
new_cost += costDistance(&iter, vec1, vec2, i1, i2);
new_cost += costDistance(iter, vec1, vec2, i1, i2);
cost_cache[i] = new_cost;
}
@ -2518,7 +2425,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
}
vec0 = node_start->p;
initArcIterator(&iter, earc, node_start);
initArcIterator(iter, earc, node_start);
#ifndef USE_THREADS
printPositions(best_positions, nb_joints);
@ -2535,7 +2442,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
float *no = NULL;
if (i < nb_joints)
{
bucket = iter.peek(&iter, best_positions[i]);
bucket = IT_peek(iter, best_positions[i]);
vec1 = bucket->p;
no = bucket->no;
}
@ -2558,7 +2465,8 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
ReebArc *earc = iarc->link_mesh;
ReebNode *node_start, *node_end;
RigEdge *edge;
@ -2580,9 +2488,9 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
node_end = (ReebNode*)earc->tail;
}
initArcIterator(&iter, earc, node_start);
initArcIterator(iter, earc, node_start);
bucket = iter.next(&iter);
bucket = IT_next(iter);
vec0 = node_start->p;
@ -2593,15 +2501,15 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
embedding_length += VecLenf(vec0, vec1);
vec0 = vec1;
bucket = iter.next(&iter);
bucket = IT_next(iter);
}
embedding_length += VecLenf(node_end->p, vec1);
/* fit bones */
initArcIterator(&iter, earc, node_start);
initArcIterator(iter, earc, node_start);
bucket = iter.next(&iter);
bucket = IT_next(iter);
vec0 = node_start->p;
previous_vec = vec0;
@ -2616,7 +2524,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
while (bucket && new_bone_length > length)
{
length += VecLenf(previous_vec, vec1);
bucket = iter.next(&iter);
bucket = IT_next(iter);
previous_vec = vec1;
vec1 = bucket->p;
no = bucket->no;

View File

@ -54,6 +54,7 @@
#include "BIF_editarmature.h"
#include "BIF_sketch.h"
#include "BIF_retarget.h"
#include "BIF_generate.h"
#include "blendef.h"
#include "mydevice.h"
@ -117,6 +118,26 @@ typedef struct SK_Sketch
SK_Point next_point;
} SK_Sketch;
typedef struct SK_StrokeIterator {
HeadFct head;
TailFct tail;
PeekFct peek;
NextFct next;
NextNFct nextN;
PreviousFct previous;
StoppedFct stopped;
float *p, *no;
int length;
int index;
/*********************************/
SK_Stroke *stroke;
int start;
int end;
int stride;
} SK_StrokeIterator;
SK_Sketch *GLOBAL_sketch = NULL;
SK_Point boneSnap;
@ -124,7 +145,7 @@ SK_Point boneSnap;
/******************** PROTOTYPES ******************************/
typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]);
void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
void sk_deleteSelectedStrokes(SK_Sketch *sketch);
@ -133,10 +154,6 @@ void sk_freeSketch(SK_Sketch *sketch);
SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
/******************** TEMPLATES UTILS *************************/
char *TEMPLATES_MENU = NULL;
@ -990,18 +1007,20 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3])
// glEnd();
}
void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionFunc next_subdividion)
void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdividion)
{
float head[3], tail[3];
int bone_start = start;
int bone_start = 0;
int end = iter->length;
int index;
VECCOPY(head, stk->points[start].p);
iter->head(iter);
VECCOPY(head, iter->p);
glColor3f(0, 1, 1);
glBegin(GL_POINTS);
index = next_subdividion(stk, bone_start, end, head, tail);
index = next_subdividion(iter, bone_start, end, head, tail);
while (index != -1)
{
glVertex3fv(tail);
@ -1009,7 +1028,7 @@ void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionF
VECCOPY(head, tail);
bone_start = index; // start next bone from current index
index = next_subdividion(stk, bone_start, end, head, tail);
index = next_subdividion(iter, bone_start, end, head, tail);
}
glEnd();
@ -1040,17 +1059,22 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk)
{
if (i - head_index > 1)
{
SK_StrokeIterator sk_iter;
BArcIterator *iter = (BArcIterator*)&sk_iter;
initStrokeIterator(iter, stk, head_index, i);
if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION)
{
drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision);
drawSubdividedStrokeBy(iter, nextCorrelationSubdivision);
}
else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
{
drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision);
drawSubdividedStrokeBy(iter, nextLengthSubdivision);
}
else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
{
drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision);
drawSubdividedStrokeBy(iter, nextFixedSubdivision);
}
}
@ -1354,13 +1378,29 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D
float vec[3];
float new_dist;
p1->flag = 0;
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
p1->flag = 1;
/* if peeling objects, take the first and last from each object */
if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
{
/* nothing to do here */
SK_DepthPeel *peel;
for (peel = p1->next; peel; peel = peel->next)
{
if (peel->ob == p1->ob)
{
peel->flag = 1;
p2 = peel;
}
}
}
/* otherwise, pair first with second and so on */
else
{
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
{
/* nothing to do here */
}
}
if (p2)
{
@ -1528,250 +1568,175 @@ void sk_initDrawData(SK_DrawData *dd)
}
/********************************************/
/* bone is assumed to be in GLOBAL space */
void setBoneRollFromPoint(EditBone *bone, SK_Point *pt, float invmat[][4], float tmat[][3])
{
float tangent[3], cotangent[3], normal[3];
VecSubf(tangent, bone->tail, bone->head);
Crossf(cotangent, tangent, pt->no);
Crossf(normal, cotangent, tangent);
Mat3MulVecfl(tmat, normal);
Normalize(normal);
bone->roll = rollBoneToVector(bone, normal);
static void* headPoint(void *arg);
static void* tailPoint(void *arg);
static void* nextPoint(void *arg);
static void* nextNPoint(void *arg, int n);
static void* peekPoint(void *arg, int n);
static void* previousPoint(void *arg);
static int iteratorStopped(void *arg);
static void initIteratorFct(SK_StrokeIterator *iter)
{
iter->head = headPoint;
iter->tail = tailPoint;
iter->peek = peekPoint;
iter->next = nextPoint;
iter->nextN = nextNPoint;
iter->previous = previousPoint;
iter->stopped = iteratorStopped;
}
float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3])
static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
{
int len = 2 + abs(end - start);
SK_Point *pt = NULL;
if (len > 2)
if (index >= 0 && index < iter->length)
{
float avg_t = 0.0f;
float s_t = 0.0f;
float s_xyz = 0.0f;
int i;
/* First pass, calculate average */
for (i = start; i <= end; i++)
{
float v[3];
VecSubf(v, stk->points[i].p, v0);
avg_t += Inpf(v, n);
}
avg_t /= Inpf(n, n);
avg_t += 1.0f; /* adding start (0) and end (1) values */
avg_t /= len;
/* Second pass, calculate s_xyz and s_t */
for (i = start; i <= end; i++)
{
float v[3], d[3];
float dt;
VecSubf(v, stk->points[i].p, v0);
Projf(d, v, n);
VecSubf(v, v, d);
dt = VecLength(d) - avg_t;
s_t += dt * dt;
s_xyz += Inpf(v, v);
}
/* adding start(0) and end(1) values to s_t */
s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
return 1.0f - s_xyz / s_t;
pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
iter->p = pt->p;
iter->no = pt->no;
}
else
{
return 1.0f;
iter->p = NULL;
iter->no = NULL;
}
return pt;
}
int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
{
static float stroke_length = 0;
static float current_length;
static char n;
float length_threshold;
int i;
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
initIteratorFct(iter);
iter->stroke = stk;
if (stroke_length == 0)
if (start < end)
{
current_length = 0;
for (i = start + 1; i <= end; i++)
{
stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p);
}
iter->start = start + 1;
iter->end = end - 1;
iter->stride = 1;
}
else
{
iter->start = start - 1;
iter->end = end + 1;
iter->stride = -1;
}
iter->length = iter->stride * (iter->end - iter->start + 1);
iter->index = -1;
}
static void* headPoint(void *arg)
{
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
result = &(iter->stroke->points[iter->start - iter->stride]);
iter->p = result->p;
iter->no = result->no;
return result;
}
static void* tailPoint(void *arg)
{
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
result = &(iter->stroke->points[iter->end + iter->stride]);
iter->p = result->p;
iter->no = result->no;
return result;
}
static void* nextPoint(void *arg)
{
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
if (iter->index < iter->length)
{
iter->index++;
result = setIteratorValues(iter, iter->index);
}
return result;
}
static void* nextNPoint(void *arg, int n)
{
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
n = 0;
current_length = 0;
}
n++;
length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number;
/* < and not <= because we don't care about end, it is P_EXACT anyway */
for (i = start + 1; i < end; i++)
{
current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p);
iter->index += n;
if (current_length >= length_threshold)
{
VECCOPY(p, stk->points[i].p);
return i;
}
/* check if passed end */
if (iter->index < iter->length)
{
result = setIteratorValues(iter, iter->index);
}
stroke_length = 0;
return -1;
else
{
/* stop iterator if passed end */
iter->index = iter->length;
}
return result;
}
int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
static void* peekPoint(void *arg, int n)
{
float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit;
float n[3];
int i;
for (i = start + 2; i <= end; i++)
{
/* Calculate normal */
VecSubf(n, stk->points[i].p, head);
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
int index = iter->index + n;
if (calcStrokeCorrelation(stk, start, i, stk->points[start].p, n) < correlation_threshold)
{
VECCOPY(p, stk->points[i - 1].p);
return i - 1;
}
/* check if passed end */
if (index < iter->length)
{
result = setIteratorValues(iter, index);
}
return -1;
return result;
}
int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
static void* previousPoint(void *arg)
{
float lengthLimit = G.scene->toolsettings->skgen_length_limit;
int same = 1;
int i;
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
SK_Point *result = NULL;
i = start + 1;
while (i <= end)
if (iter->index > 0)
{
float *vec0 = stk->points[i - 1].p;
float *vec1 = stk->points[i].p;
/* If lengthLimit hits the current segment */
if (VecLenf(vec1, head) > lengthLimit)
{
if (same == 0)
{
float dv[3], off[3];
float a, b, c, f;
/* Solve quadratic distance equation */
VecSubf(dv, vec1, vec0);
a = Inpf(dv, dv);
VecSubf(off, vec0, head);
b = 2 * Inpf(dv, off);
c = Inpf(off, off) - (lengthLimit * lengthLimit);
f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
//printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
if (isnan(f) == 0 && f < 1.0f)
{
VECCOPY(p, dv);
VecMulf(p, f);
VecAddf(p, p, vec0);
}
else
{
VECCOPY(p, vec1);
}
}
else
{
float dv[3];
VecSubf(dv, vec1, vec0);
Normalize(dv);
VECCOPY(p, dv);
VecMulf(p, lengthLimit);
VecAddf(p, p, head);
}
return i - 1; /* restart at lower bound */
}
else
{
i++;
same = 0; // Reset same
}
iter->index--;
result = setIteratorValues(iter, iter->index);
}
return -1;
return result;
}
EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
static int iteratorStopped(void *arg)
{
bArmature *arm = G.obedit->data;
EditBone *lastBone = NULL;
EditBone *child = NULL;
EditBone *parent = NULL;
int bone_start = start;
int index;
parent = addEditBone("Bone", &G.edbo, arm);
VECCOPY(parent->head, stk->points[start].p);
index = next_subdividion(stk, bone_start, end, parent->head, parent->tail);
while (index != -1)
SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
if (iter->index == iter->length)
{
setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat);
child = addEditBone("Bone", &G.edbo, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
/* going to next bone, fix parent */
Mat4MulVecfl(invmat, parent->tail);
Mat4MulVecfl(invmat, parent->head);
parent = child; // new child is next parent
bone_start = index; // start next bone from current index
index = next_subdividion(stk, bone_start, end, parent->head, parent->tail);
return 1;
}
else
{
return 0;
}
VECCOPY(parent->tail, stk->points[end].p);
setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat);
/* fix last bone */
Mat4MulVecfl(invmat, parent->tail);
Mat4MulVecfl(invmat, parent->head);
lastBone = parent;
return lastBone;
}
void sk_convertStroke(SK_Stroke *stk)
{
bArmature *arm= G.obedit->data;
bArmature *arm = G.obedit->data;
SK_Point *head;
EditBone *parent = NULL;
float invmat[4][4]; /* move in caller function */
@ -1804,17 +1769,22 @@ void sk_convertStroke(SK_Stroke *stk)
if (i - head_index > 1)
{
SK_StrokeIterator sk_iter;
BArcIterator *iter = (BArcIterator*)&sk_iter;
initStrokeIterator(iter, stk, head_index, i);
if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION)
{
bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision);
bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision);
}
else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
{
bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision);
bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision);
}
else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
{
bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision);
bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextFixedSubdivision);
}
}
@ -1824,10 +1794,10 @@ void sk_convertStroke(SK_Stroke *stk)
VECCOPY(bone->head, head->p);
VECCOPY(bone->tail, pt->p);
setBoneRollFromPoint(bone, pt, invmat, tmat);
Mat4MulVecfl(invmat, bone->head);
Mat4MulVecfl(invmat, bone->tail);
setBoneRollFromNormal(bone, pt->no, invmat, tmat);
}
new_parent = bone;
@ -1995,6 +1965,9 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
{
SK_StrokeIterator sk_iter;
BArcIterator *iter = (BArcIterator*)&sk_iter;
float CORRELATION_THRESHOLD = 0.99f;
float *vec;
int i, j;
@ -2002,6 +1975,8 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
sk_appendStrokePoint(segments, &gesture->points[0]);
vec = segments->points[segments->nb_points - 1].p;
initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
for (i = 1, j = 0; i < gesture->nb_points; i++)
{
float n[3];
@ -2009,7 +1984,7 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
/* Calculate normal */
VecSubf(n, gesture->points[i].p, vec);
if (calcStrokeCorrelation(gesture, j, i, vec, n) < CORRELATION_THRESHOLD)
if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
{
j = i - 1;
sk_appendStrokePoint(segments, &gesture->points[j]);

View File

@ -850,7 +850,8 @@ void fillArcEmptyBuckets(ReebArc *arc)
static void ExtendArcBuckets(ReebArc *arc)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
EmbedBucket *last_bucket, *first_bucket;
float *previous = NULL;
float average_length = 0, length;
@ -861,16 +862,16 @@ static void ExtendArcBuckets(ReebArc *arc)
return; /* failsafe, shouldn't happen */
}
initArcIterator(&iter, arc, arc->head);
iter.next(&iter);
previous = iter.p;
initArcIterator(iter, arc, arc->head);
IT_next(iter);
previous = iter->p;
for ( iter.next(&iter);
iter.stopped(&iter) == 0;
previous = iter.p, iter.next(&iter)
for ( IT_next(iter);
IT_stopped(iter) == 0;
previous = iter->p, IT_next(iter)
)
{
average_length += VecLenf(previous, iter.p);
average_length += VecLenf(previous, iter->p);
}
average_length /= (arc->bcount - 1);
@ -927,19 +928,20 @@ void extendGraphBuckets(ReebGraph *rg)
void calculateArcLength(ReebArc *arc)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
float *vec0, *vec1;
arc->length = 0;
initArcIterator(&iter, arc, arc->head);
initArcIterator(iter, arc, arc->head);
vec0 = arc->head->p;
vec1 = arc->head->p; /* in case there's no embedding */
while (iter.next(&iter))
while (IT_next(iter))
{
vec1 = iter.p;
vec1 = iter->p;
arc->length += VecLenf(vec0, vec1);
@ -996,28 +998,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count)
* */
if (arc1->bcount > 0 && arc2->bcount > 0)
{
ReebArcIterator iter1, iter2;
ReebArcIterator arc_iter1, arc_iter2;
BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
initArcIterator(&iter1, arc1, (ReebNode*)root_node);
initArcIterator(&iter2, arc2, (ReebNode*)root_node);
initArcIterator(iter1, arc1, (ReebNode*)root_node);
initArcIterator(iter2, arc2, (ReebNode*)root_node);
bucket1 = iter1.next(&iter1);
bucket2 = iter2.next(&iter2);
bucket1 = IT_next(iter1);
bucket2 = IT_next(iter2);
/* Make sure they both start at the same value */
while(bucket1 && bucket2 && bucket1->val < bucket2->val)
{
bucket1 = iter1.next(&iter1);
bucket1 = IT_next(iter1);
}
while(bucket1 && bucket2 && bucket2->val < bucket1->val)
{
bucket2 = iter2.next(&iter2);
bucket2 = IT_next(iter2);
}
for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter2.next(&iter2))
for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
{
bucket2->nv += bucket1->nv; /* add counts */
@ -1056,28 +1060,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count)
* */
if (arc1->bcount > 0 && arc2->bcount > 0)
{
ReebArcIterator iter1, iter2;
ReebArcIterator arc_iter1, arc_iter2;
BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
initArcIterator(&iter1, arc1, node);
initArcIterator(&iter2, arc2, node);
initArcIterator(iter1, arc1, node);
initArcIterator(iter2, arc2, node);
bucket1 = iter1.next(&iter1);
bucket2 = iter2.next(&iter2);
bucket1 = IT_next(iter1);
bucket2 = IT_next(iter2);
/* Make sure they both start at the same value */
while(bucket1 && bucket1->val < bucket2->val)
{
bucket1 = iter1.next(&iter1);
bucket1 = IT_next(iter1);
}
while(bucket2 && bucket2->val < bucket1->val)
{
bucket2 = iter2.next(&iter2);
bucket2 = IT_next(iter2);
}
for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter1.next(&iter2))
for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
{
/* copy and mirror back to bucket2 */
bucket2->nv = bucket1->nv;
@ -1115,28 +1121,30 @@ void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BAr
* */
if (arc1->bcount > 0 && arc2->bcount > 0)
{
ReebArcIterator iter1, iter2;
ReebArcIterator arc_iter1, arc_iter2;
BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
initArcIterator(&iter1, arc1, (ReebNode*)root_node);
initArcIterator(&iter2, arc2, (ReebNode*)root_node);
initArcIterator(iter1, arc1, (ReebNode*)root_node);
initArcIterator(iter2, arc2, (ReebNode*)root_node);
bucket1 = iter1.next(&iter1);
bucket2 = iter2.next(&iter2);
bucket1 = IT_next(iter1);
bucket2 = IT_next(iter2);
/* Make sure they both start at the same value */
while(bucket1 && bucket1->val < bucket2->val)
{
bucket1 = iter1.next(&iter1);
bucket1 = IT_next(iter1);
}
while(bucket2 && bucket2->val < bucket1->val)
{
bucket2 = iter1.next(&iter2);
bucket2 = IT_next(iter2);
}
for ( ;bucket1 && bucket2; bucket1 = iter2.next(&iter1), bucket2 = iter2.next(&iter2))
for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
{
bucket1->nv += bucket2->nv; /* add counts */
@ -1763,15 +1771,16 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold)
EditFace *efa = BLI_ghashIterator_getValue(&ghi);
#if 0
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
EmbedBucket *bucket = NULL;
EmbedBucket *previous = NULL;
float min_distance = -1;
float angle = 0;
initArcIterator(&iter, arc, arc->head);
initArcIterator(iter, arc, arc->head);
bucket = nextBucket(&iter);
bucket = nextBucket(iter);
while (bucket != NULL)
{
@ -1806,7 +1815,7 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold)
}
previous = bucket;
bucket = nextBucket(&iter);
bucket = nextBucket(iter);
}
avg_angle += saacos(fabs(angle));
@ -3296,14 +3305,18 @@ void arcToVCol(ReebGraph *rg, EditMesh *em, int index)
/****************************************** BUCKET ITERATOR **************************************************/
void* nextBucket(void *arg);
void* nextNBucket(void *arg, int n);
void* peekBucket(void *arg, int n);
void* previousBucket(void *arg);
int iteratorStopped(void *arg);
static void* headNode(void *arg);
static void* tailNode(void *arg);
static void* nextBucket(void *arg);
static void* nextNBucket(void *arg, int n);
static void* peekBucket(void *arg, int n);
static void* previousBucket(void *arg);
static int iteratorStopped(void *arg);
void initIteratorFct(ReebArcIterator *iter)
static void initIteratorFct(ReebArcIterator *iter)
{
iter->head = headNode;
iter->tail = tailNode;
iter->peek = peekBucket;
iter->next = nextBucket;
iter->nextN = nextNBucket;
@ -3311,7 +3324,7 @@ void initIteratorFct(ReebArcIterator *iter)
iter->stopped = iteratorStopped;
}
void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket)
static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket)
{
if (bucket)
{
@ -3325,8 +3338,10 @@ void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket)
}
}
void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head)
void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
initIteratorFct(iter);
iter->arc = arc;
@ -3345,11 +3360,13 @@ void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head)
iter->length = arc->bcount;
iter->index = iter->start - iter->stride;
iter->index = -1;
}
void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start)
void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
initIteratorFct(iter);
iter->arc = arc;
@ -3366,7 +3383,7 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str
iter->stride = -1;
}
iter->index = iter->start - iter->stride;
iter->index = -1;
iter->length = arc->bcount - start;
@ -3376,8 +3393,10 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str
}
}
void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end)
void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
initIteratorFct(iter);
iter->arc = arc;
@ -3393,86 +3412,124 @@ void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end)
iter->stride = -1;
}
iter->index = iter->start - iter->stride;
iter->index = -1;
iter->length = abs(iter->end - iter->start) + 1;
}
void* nextBucket(void *arg)
static void* headNode(void *arg)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
ReebNode *node;
if (iter->start < iter->end)
{
node = iter->arc->head;
}
else
{
node = iter->arc->tail;
}
iter->p = node->p;
iter->no = node->no;
return node;
}
static void* tailNode(void *arg)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
ReebNode *node;
if (iter->start < iter->end)
{
node = iter->arc->tail;
}
else
{
node = iter->arc->head;
}
iter->p = node->p;
iter->no = node->no;
return node;
}
static void* nextBucket(void *arg)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
EmbedBucket *result = NULL;
if (iter->index != iter->end)
if (iter->index < iter->length)
{
iter->index += iter->stride;
result = &(iter->arc->buckets[iter->index]);
iter->index++;
result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
}
setIteratorValues(iter, result);
return result;
}
void* nextNBucket(void *arg, int n)
static void* nextNBucket(void *arg, int n)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
EmbedBucket *result = NULL;
iter->index += n * iter->stride;
iter->index += n;
/* check if passed end */
if ((iter->stride == 1 && iter->index <= iter->end) ||
(iter->stride == -1 && iter->index >= iter->end))
if (iter->index < iter->length)
{
result = &(iter->arc->buckets[iter->index]);
result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
}
else
{
/* stop iterator if passed end */
iter->index = iter->end;
iter->index = iter->length;
}
setIteratorValues(iter, result);
return result;
}
void* peekBucket(void *arg, int n)
static void* peekBucket(void *arg, int n)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
EmbedBucket *result = NULL;
int index = iter->index + n * iter->stride;
int index = iter->index + n;
/* check if passed end */
if ((iter->stride == 1 && index <= iter->end && index >= iter->start) ||
(iter->stride == -1 && index >= iter->end && index <= iter->start))
if (index < iter->length)
{
result = &(iter->arc->buckets[index]);
result = &(iter->arc->buckets[iter->start + (iter->stride * index)]);
}
setIteratorValues(iter, result);
return result;
}
void* previousBucket(void *arg)
static void* previousBucket(void *arg)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
EmbedBucket *result = NULL;
if (iter->index != iter->start)
if (iter->index > 0)
{
iter->index -= iter->stride;
result = &(iter->arc->buckets[iter->index]);
iter->index--;
result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
}
setIteratorValues(iter, result);
return result;
}
int iteratorStopped(void *arg)
static int iteratorStopped(void *arg)
{
ReebArcIterator *iter = (ReebArcIterator*)arg;
if (iter->index == iter->end)
if (iter->index == iter->length)
{
return 1;
}
@ -3711,7 +3768,8 @@ void REEB_draw()
glDisable(GL_DEPTH_TEST);
for (arc = rg->arcs.first; arc; arc = arc->next, i++)
{
ReebArcIterator iter;
ReebArcIterator arc_iter;
BArcIterator *iter = (BArcIterator*)&arc_iter;
float vec[3];
char text[128];
char *s = text;
@ -3723,10 +3781,10 @@ void REEB_draw()
if (arc->bcount)
{
initArcIterator(&iter, arc, arc->head);
for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter))
initArcIterator(iter, arc, arc->head);
for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter))
{
glVertex3fv(iter.p);
glVertex3fv(iter->p);
}
}
@ -3756,10 +3814,10 @@ void REEB_draw()
if (arc->bcount)
{
initArcIterator(&iter, arc, arc->head);
for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter))
initArcIterator(iter, arc, arc->head);
for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
{
glVertex3fv(iter.p);
glVertex3fv(iter->p);
}
}
@ -3777,10 +3835,10 @@ void REEB_draw()
glColor3f(0.5f, 0.5f, 1);
if (arc->bcount)
{
initArcIterator(&iter, arc, arc->head);
for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter))
initArcIterator(iter, arc, arc->head);
for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
{
glVertex3fv(iter.p);
glVertex3fv(iter->p);
}
}
glEnd();