Commit 22986819 authored by Aron Helser's avatar Aron Helser

Avatar: add torso and upper arms, positioned automatically.

Torso hangs below the head according to the user-supplied
up-vector, and rotates with the head. Upper arms attach at
the shoulder, and rotate to point at the elbow, according to
the hand/forearm position. Arm will be disconnected at the
elbow if things don't match up.
parent 706e3b25
......@@ -49,6 +49,8 @@ set(geometry_files
data/vtkAvatarTorso.vtp
data/vtkAvatarLeftForeArm.vtp
data/vtkAvatarRightForeArm.vtp
data/vtkAvatarLeftUpperArm.vtp
data/vtkAvatarRightUpperArm.vtp
)
unset(geometry_h_files)
foreach(file ${geometry_files})
......
......@@ -77,18 +77,18 @@ int TestAvatar(int argc, char *argv[])
vtkNew<vtkAvatar> avatar;
avatar->SetHeadPosition(-2.4, 0.2, 0);
avatar->SetHeadOrientation(20, 20, 0);
avatar->SetLeftHandPosition(-0.6, -0.3, -0.5);
avatar->SetLeftHandOrientation(0, 0, 30);
avatar->SetHeadOrientation(0, 20, 0);
avatar->SetLeftHandPosition(-0.9, -0.3, -0.7);
avatar->SetLeftHandOrientation(-10, -20, 15);
avatar->SetRightHandPosition(-0.6, -0.4, 0.5);
avatar->SetRightHandOrientation(0, 0, 0);
avatar->GetProperty()->SetColor(0.8, 1.0, 0.8);
// avatar->SetScale(0.3);
renderer->AddActor(avatar);
renderer->GetActiveCamera()->SetPosition(-1.0, 0.25, 4.0);
renderer->GetActiveCamera()->SetPosition(-1.0, 0.25, 5.0);
renderer->GetActiveCamera()->SetFocalPoint(-1.0, 0.25, 0.0);
renderer->GetActiveCamera()->SetViewAngle(60.0);
renderer->GetActiveCamera()->SetViewAngle(55.0);
renderer->GetActiveCamera()->Zoom(1.1);
renderer->GetActiveCamera()->Azimuth(0);
renderer->GetActiveCamera()->Elevation(15);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -28,16 +28,27 @@
#include "vtkRenderWindow.h"
#include "vtkShaderProgram.h"
#include "vtkTexture.h"
#include "vtkTransform.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkAvatarHead.h" // geometry for head
#include "vtkAvatarLeftHand.h" // geometry for hand
#include "vtkAvatarRightHand.h" // geometry for hand
#include "vtkAvatarTorso.h" // geometry for torso
#include "vtkAvatarLeftForeArm.h" // geometry for torso
#include "vtkAvatarRightForeArm.h" // geometry for torso
#include "vtkAvatarLeftForeArm.h" // geometry for arm
#include "vtkAvatarRightForeArm.h" // geometry for arm
#include "vtkAvatarLeftUpperArm.h" // geometry for arm
#include "vtkAvatarRightUpperArm.h" // geometry for arm
#include <cmath>
void setOrientation(vtkTransform* trans, const double* orientation)
{
trans->Identity();
trans->RotateZ(orientation[2]);
trans->RotateX(orientation[0]);
trans->RotateY(orientation[1]);
}
vtkStandardNewMacro(vtkOpenGLAvatar);
vtkOpenGLAvatar::vtkOpenGLAvatar()
......@@ -69,15 +80,15 @@ vtkOpenGLAvatar::vtkOpenGLAvatar()
vtkAvatarTorso,
vtkAvatarLeftForeArm,
vtkAvatarRightForeArm,
nullptr,
nullptr,
vtkAvatarLeftUpperArm,
vtkAvatarRightUpperArm,
};
size_t modelSize[NUM_BODY] = {
sizeof vtkAvatarTorso,
sizeof vtkAvatarLeftForeArm,
sizeof vtkAvatarRightForeArm,
0,
0,
sizeof vtkAvatarLeftUpperArm,
sizeof vtkAvatarRightUpperArm,
};
this->GetProperty()->SetDiffuse(0.7);
......@@ -126,7 +137,7 @@ void vtkOpenGLAvatar::Render(vtkRenderer *ren, vtkMapper *mapper)
mapper->Render(ren, this->HeadActor);
this->LeftHandMapper->Render(ren, this->LeftHandActor);
this->RightHandMapper->Render(ren, this->RightHandActor);
for (int i = 0; i <= RIGHT_FORE; ++i) {
for (int i = 0; i < NUM_BODY; ++i) {
this->BodyActor[i]->SetScale(this->GetScale());
this->BodyActor[i]->SetPosition(this->BodyPosition[i]);
this->BodyActor[i]->SetOrientation(this->BodyOrientation[i]);
......@@ -163,6 +174,64 @@ void vtkOpenGLAvatar::CalcBody()
this->BodyOrientation[RIGHT_FORE][1] = this->RightHandOrientation[1];
this->BodyOrientation[RIGHT_FORE][2] = this->RightHandOrientation[2];
// Attach upper arm at shoulder, and rotate to hit the end of the forearm.
// end of forearm, relative to the hand at 0, is elbow pos.
double shoulderPos[3] = {-0.138, -0.5, -0.61};
vtkNew<vtkTransform> trans;
setOrientation(trans, this->BodyOrientation[TORSO]);
// calculate relative left shoulder position (to torso)
trans->TransformPoint(shoulderPos, this->BodyPosition[LEFT_UPPER]);
// move with torso
this->BodyPosition[LEFT_UPPER][0] += this->BodyPosition[TORSO][0];
this->BodyPosition[LEFT_UPPER][1] += this->BodyPosition[TORSO][1];
this->BodyPosition[LEFT_UPPER][2] += this->BodyPosition[TORSO][2];
shoulderPos[2] = +0.61;
// calculate relative right shoulder position (to torso)
trans->TransformPoint(shoulderPos, this->BodyPosition[RIGHT_UPPER]);
// move with torso
this->BodyPosition[RIGHT_UPPER][0] += this->BodyPosition[TORSO][0];
this->BodyPosition[RIGHT_UPPER][1] += this->BodyPosition[TORSO][1];
this->BodyPosition[RIGHT_UPPER][2] += this->BodyPosition[TORSO][2];
// orient the upper left arm to aim at the elbow.
double leftElbowPos[3] = {-0.85, 0.02, 0};
setOrientation(trans, this->LeftHandOrientation);
trans->TransformPoint(leftElbowPos, leftElbowPos);
leftElbowPos[0] += this->LeftHandPosition[0];
leftElbowPos[1] += this->LeftHandPosition[1];
leftElbowPos[2] += this->LeftHandPosition[2];
// upper-arm extends along +x at zero rotation. rotate (1,0,0) to
// vector between shoulder and elbow.
double leftUpperDir[3], cross[3], startDir[3] = { 1, 0, 0 };
vtkMath::Subtract(leftElbowPos, this->BodyPosition[LEFT_UPPER], leftUpperDir);
vtkMath::Cross(startDir, leftUpperDir, cross);
vtkMath::Normalize(cross);
double angle = vtkMath::AngleBetweenVectors(startDir, leftUpperDir) * 180 / vtkMath::Pi();
trans->Identity();
trans->RotateWXYZ(angle, cross);
trans->GetOrientation(this->BodyOrientation[LEFT_UPPER]);
// now the right upper arm
double rightElbowPos[3] = {-0.85, 0.02, 0};
setOrientation(trans, this->RightHandOrientation);
trans->TransformPoint(rightElbowPos, rightElbowPos);
rightElbowPos[0] += this->RightHandPosition[0];
rightElbowPos[1] += this->RightHandPosition[1];
rightElbowPos[2] += this->RightHandPosition[2];
// upper-arm extends along +x at zero rotation. rotate (1,0,0) to
// vector between shoulder and elbow.
double rightUpperDir[3];
vtkMath::Subtract(rightElbowPos, this->BodyPosition[RIGHT_UPPER], rightUpperDir);
vtkMath::Cross(startDir, rightUpperDir, cross);
vtkMath::Normalize(cross);
angle = vtkMath::AngleBetweenVectors(startDir, rightUpperDir) * 180 / vtkMath::Pi();
trans->Identity();
trans->RotateWXYZ(angle, cross);
trans->GetOrientation(this->BodyOrientation[RIGHT_UPPER]);
}
//----------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment