// rotate bone's y-axis with target. AnimPose boneLookAt(const glm::vec3& target, const AnimPose& bone) { glm::vec3 u, v, w; generateBasisVectors(target - bone.trans(), bone.rot() * Vectors::UNIT_X, u, v, w); glm::mat4 lookAt(glm::vec4(v, 0.0f), glm::vec4(u, 0.0f), // AJT: TODO REVISIT THIS, this could be -w. glm::vec4(glm::normalize(glm::cross(v, u)), 0.0f), glm::vec4(bone.trans(), 1.0f)); return AnimPose(lookAt); }
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose. // if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward // such that it lies on the surface of the kdop. bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) { // transform point into local space of jointShape. glm::vec3 localPoint = shapePose.inverse().xformPoint(point); // Only works for 14-dop shape infos. if (shapeInfo.dots.size() != DOP14_COUNT) { return false; } glm::vec3 minDisplacement(FLT_MAX); float minDisplacementLen = FLT_MAX; glm::vec3 p = localPoint - shapeInfo.avgPoint; float pLen = glm::length(p); if (pLen > 0.0f) { int slabCount = 0; for (int i = 0; i < DOP14_COUNT; i++) { float dot = glm::dot(p, DOP14_NORMALS[i]); if (dot > 0.0f && dot < shapeInfo.dots[i]) { slabCount++; float distToPlane = pLen * (shapeInfo.dots[i] / dot); float displacementLen = distToPlane - pLen; // keep track of the smallest displacement if (displacementLen < minDisplacementLen) { minDisplacementLen = displacementLen; minDisplacement = (p / pLen) * displacementLen; } } } if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { // we are within the k-dop so push the point along the minimum displacement found displacementOut = shapePose.xformVectorFast(minDisplacement); return true; } else { // point is outside of kdop return false; } } else { // point is directly on top of shapeInfo.avgPoint. // push the point out along the x axis. displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); return true; } }
AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap& animVars, const JointVar& jointVar, const AnimPose& defaultRelPose, const AnimPoseVec& underPoses) { AnimPose defaultAbsPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses); if (jointVar.type == JointVar::Type::AbsoluteRotation || jointVar.type == JointVar::Type::AbsolutePosition) { if (jointVar.type == JointVar::Type::AbsoluteRotation) { defaultAbsPose.rot = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.rot); } else if (jointVar.type == JointVar::Type::AbsolutePosition) { defaultAbsPose.trans = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.trans); } // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose. AnimPose parentAbsPose = AnimPose::identity; int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); if (parentIndex >= 0) { parentAbsPose = _skeleton->getAbsolutePose(parentIndex, underPoses); } // convert from absolute to relative return parentAbsPose.inverse() * defaultAbsPose; } else { // override the default rel pose AnimPose relPose = defaultRelPose; if (jointVar.type == JointVar::Type::RelativeRotation) { relPose.rot = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.rot); } else if (jointVar.type == JointVar::Type::RelativePosition) { relPose.trans = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.trans); } return relPose; } }
void AnimDebugDraw::update() { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (!scene) { return; } if (!render::Item::isValidID(_itemID)) { return; } render::Transaction transaction; transaction.updateItem<AnimDebugDrawData>(_itemID, [&](AnimDebugDrawData& data) { const size_t VERTICES_PER_BONE = (6 + (NUM_CIRCLE_SLICES * 2) * 3); const size_t VERTICES_PER_LINK = 8 * 2; const size_t VERTICES_PER_RAY = 2; const float BONE_RADIUS = 0.01f; // 1 cm const float POSE_RADIUS = 0.1f; // 10 cm // figure out how many verts we will need. int numVerts = 0; for (auto& iter : _absolutePoses) { AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second); numVerts += skeleton->getNumJoints() * VERTICES_PER_BONE; for (auto i = 0; i < skeleton->getNumJoints(); i++) { auto parentIndex = skeleton->getParentIndex(i); if (parentIndex >= 0) { numVerts += VERTICES_PER_LINK; } } } // count marker verts from shared DebugDraw singleton auto markerMap = DebugDraw::getInstance().getMarkerMap(); numVerts += (int)markerMap.size() * VERTICES_PER_BONE; auto myAvatarMarkerMap = DebugDraw::getInstance().getMyAvatarMarkerMap(); numVerts += (int)myAvatarMarkerMap.size() * VERTICES_PER_BONE; auto rays = DebugDraw::getInstance().getRays(); DebugDraw::getInstance().clearRays(); numVerts += (int)rays.size() * VERTICES_PER_RAY; // allocate verts! std::vector<AnimDebugDrawData::Vertex> vertices; vertices.resize(numVerts); //Vertex* verts = (Vertex*)data._vertexBuffer->editData(); AnimDebugDrawData::Vertex* v = nullptr; if (numVerts) { v = &vertices[0]; } // draw absolute poses for (auto& iter : _absolutePoses) { AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second); AnimPoseVec& absPoses = std::get<1>(iter.second); AnimPose rootPose = std::get<2>(iter.second); glm::vec4 color = std::get<3>(iter.second); for (int i = 0; i < skeleton->getNumJoints(); i++) { const float radius = BONE_RADIUS / (absPoses[i].scale().x * rootPose.scale().x); // draw bone addBone(rootPose, absPoses[i], radius, color, v); // draw link to parent auto parentIndex = skeleton->getParentIndex(i); if (parentIndex >= 0) { assert(parentIndex < skeleton->getNumJoints()); addLink(rootPose, absPoses[i], absPoses[parentIndex], radius, color, v); } } } // draw markers from shared DebugDraw singleton for (auto& iter : markerMap) { glm::quat rot = std::get<0>(iter.second); glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos()); for (auto& iter : myAvatarMarkerMap) { glm::quat rot = std::get<0>(iter.second); glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } // draw rays from shared DebugDraw singleton for (auto& iter : rays) { addLine(std::get<0>(iter), std::get<1>(iter), std::get<2>(iter), v); } data._vertexBuffer->resize(sizeof(AnimDebugDrawData::Vertex) * numVerts); data._vertexBuffer->setSubData<AnimDebugDrawData::Vertex>(0, vertices); assert((!numVerts && !v) || (numVerts == (v - &vertices[0]))); render::Item::Bound theBound; for (int i = 0; i < numVerts; i++) { theBound += vertices[i].pos; } data._bound = theBound; data._isVisible = (numVerts > 0); data._indexBuffer->resize(sizeof(uint16_t) * numVerts); for (int i = 0; i < numVerts; i++) { data._indexBuffer->setSubData<uint16_t>(i, (uint16_t)i);; } }); scene->enqueueTransaction(transaction); }
static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius, glm::vec4& vecColor, AnimDebugDrawData::Vertex*& v) { const float XYZ_AXIS_LENGTH = radius * 4.0f; const uint32_t color = toRGBA(vecColor); AnimPose finalPose = rootPose * pose; glm::vec3 base = rootPose * pose.trans(); glm::vec3 xRing[NUM_CIRCLE_SLICES + 1]; // one extra for last index. glm::vec3 yRing[NUM_CIRCLE_SLICES + 1]; glm::vec3 zRing[NUM_CIRCLE_SLICES + 1]; const float dTheta = (2.0f * (float)M_PI) / NUM_CIRCLE_SLICES; for (int i = 0; i < NUM_CIRCLE_SLICES + 1; i++) { float rCosTheta = radius * cosf(dTheta * i); float rSinTheta = radius * sinf(dTheta * i); xRing[i] = finalPose * glm::vec3(0.0f, rCosTheta, rSinTheta); yRing[i] = finalPose * glm::vec3(rCosTheta, 0.0f, rSinTheta); zRing[i] = finalPose * glm::vec3(rCosTheta, rSinTheta, 0.0f); } // x-axis v->pos = base; v->rgba = red; v++; v->pos = finalPose * glm::vec3(XYZ_AXIS_LENGTH, 0.0f, 0.0f); v->rgba = red; v++; // x-ring for (int i = 0; i < NUM_CIRCLE_SLICES; i++) { v->pos = xRing[i]; v->rgba = color; v++; v->pos = xRing[i + 1]; v->rgba = color; v++; } // y-axis v->pos = base; v->rgba = green; v++; v->pos = finalPose * glm::vec3(0.0f, XYZ_AXIS_LENGTH, 0.0f); v->rgba = green; v++; // y-ring for (int i = 0; i < NUM_CIRCLE_SLICES; i++) { v->pos = yRing[i]; v->rgba = color; v++; v->pos = yRing[i + 1]; v->rgba = color; v++; } // z-axis v->pos = base; v->rgba = blue; v++; v->pos = finalPose * glm::vec3(0.0f, 0.0f, XYZ_AXIS_LENGTH); v->rgba = blue; v++; // z-ring for (int i = 0; i < NUM_CIRCLE_SLICES; i++) { v->pos = zRing[i]; v->rgba = color; v++; v->pos = zRing[i + 1]; v->rgba = color; v++; } }