Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
gptoolbox/mesh/stretch_bones_lbs.m
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
73 lines (65 sloc)
2.27 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function [U] = stretch_bones_lbs(V,C,BE,new_C,WB,WE) | |
% STRETCH_BONES_LBS Linear blend skinning with stretchable bones | |
% | |
% [U] = stretch_bones_lbs(V,C,BE,new_C,WB,WE) | |
% | |
% Inputs: | |
% V #V by dim list of vertex positions | |
% C #C by dim list of control vertex rest positions | |
% BE #B by 2 list of bone indices into C | |
% new_C #C by dim list of update postions for control vertices | |
% WB #V by #B list of bone weights | |
% WE #V by #B list of bone endpoint weights cooresponding to BE(:,2) | |
% Output: | |
% U #V by dim list of new vertex positions | |
% | |
assert(size(V,2) == size(C,2)); | |
% number of dimensions | |
dim = size(V,2); | |
% number of domain vertices | |
n = size(V,1); | |
% number of bones | |
m = size(BE,1); | |
assert(size(BE,2) == 2); | |
assert(max(BE(:)) <= size(C,1)); | |
assert(min(BE(:)) >= 1); | |
assert(size(WB,1) == n); | |
assert(size(WB,2) == m); | |
assert(size(WE,1) == n); | |
assert(size(WE,2) == m); | |
assert(all(size(C) == size(new_C))); | |
rest = C(BE(:,2),:) - C(BE(:,1),:); | |
pose = new_C(BE(:,2),:) - new_C(BE(:,1),:); | |
% compute rotations | |
[w,a] = axisanglebetween(pose,rest,[ 0 0 1]); | |
R = axisangle2matrix(w,a); | |
if(dim == 2) | |
R = R(1:dim,1:dim,:); | |
end | |
% compute stretch factor | |
stretch = normrow(pose)./normrow(rest) - 1; | |
% compute new position according to each bone | |
% stack R as one tall dim*m by dim matrix | |
RR = reshape(R,[dim dim*m])'; | |
% RV multiply vertices by each matrix and reshape so that RV is #V by dim by | |
% #B | |
RV = reshape((RR*(V'))',[n dim m]); | |
% compute offsets rotation times inner translation (stretch) | |
% repmat WE for each dimension and rearrange so bones are last index | |
WEdim = permute(repmat(WE,[1 1 dim]),[1 3 2]); | |
stretch_offset = stacktimes(RR,(repmat(stretch,[1 dim]).*rest)); | |
%stretch_offset = RR*((repmat(stretch,[1 dim]).*rest)'); | |
WE_stretch_offset = WEdim .* permute(repmat(stretch_offset,[1 1 n]),[3 2 1]); | |
Roffset = stacktimes(RR,(-C(BE(:,1),:))); | |
% translation part | |
T = ... | |
permute(repmat(new_C(BE(:,1),:) + Roffset,[1 1 n]),[3 2 1]) + ... | |
WE_stretch_offset; | |
% sum across bones | |
WBdim = permute(repmat(WB,[1 1 dim]),[1 3 2]); | |
U = sum( WBdim.*(T+RV),3); | |
%%% convert point weights to end point weights | |
%%WE1 = WC(:,BE(:,1)); | |
%%WE2 = WC(:,BE(:,2)); | |
%%WE = WE1 ./ (WE1 + WE2); | |
end |