오큘러스에서 제공하는 손 스켈레탈 메시를

포저블 매시로 받아서 관절별로 회전하는걸 확인했는데

 

이제 블라즈 핸드 추론 결과로 어떻게 관절회전방향을 구하는가가 문제이다

일단 기존 mediapipepytorch 데모 코드에

정규화된 랜드마크를 따로 저장해서 다뤄보려고함

 

 

 

 

 

 

 

 

이 넘파이 파일을 한번띄워보면 과학표기법으로 나와서 알아보기힘들다.

 

 

np.set_printoptions(supress=True) 주면 과학 표기법이 꺼지고 알아보기 쉽게나옴

졍규화된 랜드마크 인줄알았는데

xy값은 정규화가 되어있지않다?

 

 

 

 

 

데모 코드에서 찍어보니

정규화된게 맞는데

세이브 되기전에 어디서 수정된듯하다.

 

 

 

 

 

세이브 시점을 저장눌렀을때가 아니라

추론 직후로 옮기고

    flags2, handed2, normalized_landmarks2 = hand_regressor(img.to(gpu))
    filename = 'normalized_landmarks2.npy'
    np.save(filename, normalized_landmarks2)
    
    landmarks2 = hand_regressor.denormalize_landmarks(normalized_landmarks2.cpu(), affine2)

 

 

 

이렇게 했을때 정상적으로 정규화된 값이 나온다.

 

 

 

일단 z축은 -256

xy축은 256으로만 반정규화시켜보면

이제 대충 원하던 형태로 값이 나온다.

 

 

 

 

 

이 포인트들을 맷플롭립으로 띄워보려는데 이상하게 나온다.

차원이 하나더 있어서였으므로 스퀴즈

 

 

 

 

 

 

대충 잘 나오긴한거같은데 알아보긴 힘들다

import numpy as np
import matplotlib.pyplot as plt

# 데이터 분리
x = denormalize_landmark[:, 0]
y = denormalize_landmark[:, 1]
z = denormalize_landmark[:, 2]

# 3차원 시각화
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z)

# 축 레이블 설정
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

# 그래프 출력
plt.show()

 

 

 

 

 

 

화면을 돌리면서 보기위해

%matplotlib widget하는데

ipympl이없단다.

 

 

 

!pip install ipympl

 

핍으로 설치뒤에

 

다시 %matplotlib widget 하면 ok

 

1~4는 엄지

5~6 검지

9~12 중지

13~16 약지

17~20 소지

이므로 색을 따로 줘서 플로팅하면

 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

%matplotlib widget


# 색상 지정
colors = ['black'] + ['red'] * 4 + ['orange'] * 4 + ['yellow'] * 4 + ['green'] * 4 + ['blue'] * 4

# 3차원 산점도 그리기
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = denormalize_landmark[:, 0]
y = denormalize_landmark[:, 1]
z = denormalize_landmark[:, 2]

ax.scatter(x, y, z, c=colors)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

 

 

 

 

 

 

 

 

 

 

 

 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

%matplotlib widget

# 3차원 산점도 그리기
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = denormalize_landmark[:, 0]
y = denormalize_landmark[:, 1]
z = denormalize_landmark[:, 2]

# 색상 지정
colors = ['black'] + ['red'] * 4 + ['orange'] * 4 + ['yellow'] * 4 + ['green'] * 4 + ['blue'] * 4
ax.scatter(x, y, z, c=colors)


#손가락
colors = ['red', 'orange', 'yellow', 'green', 'blue']
groups = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
for i, group in enumerate(groups):
    for j in range(len(group)-1):
        plt.plot([x[group[j]], x[group[j+1]]], [y[group[j]], y[group[j+1]]], [z[group[j]], z[group[j+1]]], color=colors[i])
#손등
lines = [[0, 1], [0, 5], [0, 17], [5, 9], [9, 13], [13, 17]] 
for line in lines:
    ax.plot([x[line[0]], x[line[1]]], [y[line[0]], y[line[1]]], [z[line[0]], z[line[1]]], color='gray')



ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

 

 

 

 

하면서보니 모양이 조금이상한것 같아서

z에 -1해줫는데 

손목 z가 0을 기준으로 시작하는듯하다.

 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

%matplotlib widget

# 3차원 산점도 그리기
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = denormalize_landmark[:, 0]
y = denormalize_landmark[:, 1]
z = denormalize_landmark[:, 2] * -1

# 색상 지정
colors = ['black'] + ['red'] * 4 + ['orange'] * 4 + ['yellow'] * 4 + ['green'] * 4 + ['blue'] * 4
ax.scatter(x, y, z, c=colors)


#손가락
colors = ['red', 'orange', 'yellow', 'green', 'blue']
groups = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
for i, group in enumerate(groups):
    for j in range(len(group)-1):
        plt.plot([x[group[j]], x[group[j+1]]], [y[group[j]], y[group[j+1]]], [z[group[j]], z[group[j+1]]], color=colors[i])
#손등
lines = [[0, 1], [0, 5], [0, 17], [5, 9], [9, 13], [13, 17]] 
for line in lines:
    ax.plot([x[line[0]], x[line[1]]], [y[line[0]], y[line[1]]], [z[line[0]], z[line[1]]], color='gray')



ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

 

 

이제 이점들로 오큘러스 핸드의 관절 회전각을 구해야한다.

일단 반정규화 랜드마크 z축을 -1 곱해놓긴하자

 

 

일단 검지 첫번째 관절부터 보자.

회전 상태를보면 롤피치요 다 거의 0,0,0

 

 

요 50도 정도 주면 이런식이된다.

 

근데 위의건 로컬 좌표계 기준이라 전역이랑 좀 다르다.

랜드마크로 방향을 구하면 전역 좌표계 기준 방향이 나올듯한데

 

 

 

 

 

전역계기준 저 포인트의 rpy를 계산해내야할듯

 

 

 

 

 

시작점과 끝점을 출력해보면 이런식인데

시작점으로 -시켜주면 

시작점이 원점이 되고

끝점은 원점 기준으로 이동된다.

 

 

 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

%matplotlib widget

pts = np.array([pt_start, pt_end])

# 3차원 산점도 그리기
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = pts[:, 0]
y = pts[:, 1]
z = pts[:, 2]

ax.scatter(x, y, z)



ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

 

어캐할까 싶다가

먼저 xy 평면에서 각도를 계산해보면

-71도 정도가나온다.

 

 

 

 

이번에는 xy 놈이랑 z좌표로 각을 구하면 -5도 정도가 나오는데 이것도 대충 맞겟지 싶다.

 

 

대충 각도구하긴 했는데, 언리얼에선 롤피치요를 쓰지만

여기선 각도 2개를 구했다.

 

z방향 회전 각도는 y축으로 회전한것이니 피치?

xy 평면 회전 각도는 z축으로 회전한것이니 요? 쯤 되지않나싶다.

 

 

 

언리얼에서 관절을 돌려보긴하는데 뭔가 좀 이상하다.

위에서 보니 -70도라기보단 20도쯤 될거같은데 

 

 

 

 

 

방향이 좀 달라서 그런듯싶다.

 

 

 

 

 

 

 

잠깐

기본손의 다음 뼈들의 RPY를 다 0으로 설정했을때 모습

 

 

 

 

 

 

 

 

 

 

보는데 matplotlib에서 x축 방향이 반대로되어있으니 햇갈려서 다시띄움

 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


%matplotlib widget

# 3차원 산점도 그리기
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = denormalize_landmark[:, 0]
y = denormalize_landmark[:, 1]
z = denormalize_landmark[:, 2]

# 색상 지정
colors = ['black'] + ['red'] * 4 + ['orange'] * 4 + ['yellow'] * 4 + ['green'] * 4 + ['blue'] * 4
ax.scatter(x, y, z, c=colors)


#손가락
colors = ['red', 'orange', 'yellow', 'green', 'blue']
groups = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
for i, group in enumerate(groups):
    for j in range(len(group)-1):
        plt.plot([x[group[j]], x[group[j+1]]], [y[group[j]], y[group[j+1]]], [z[group[j]], z[group[j+1]]], color=colors[i])
#손등
lines = [[0, 1], [0, 5], [0, 17], [5, 9], [9, 13], [13, 17]] 
for line in lines:
    ax.plot([x[line[0]], x[line[1]]], [y[line[0]], y[line[1]]], [z[line[0]], z[line[1]]], color='gray')



ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')


plt.gca().invert_xaxis()
plt.show()

 

 

 

 

 

y 방향이 아래로 가므로 -1해주면 70도로 맞긴한데

 

 

문제는 관절 rpy들을 0으로 했을때랑 다르다

 

 

 

저런 식으로 맞추려면

관절에선 전역계 요를 -20도로 찍어줘야함.

 

 

z방향 각도 그러니까 y축 회전 피치는

-5도 나오는데

 

언리얼 본에선 +방향으로 회전시켜줘야 손바닥 안쪽으로 들어온다.

아래 그림은 전역 피치 80줬을때 상황

 

정리해보면 일단

요는 계산결과 - 90

피치는 * -1 

를 해주면 원하는 방향이 나올듯한데

 

소지의 경우도 봐야할듯하다.

 

 

 

소지(17, 18)는 계산 결과 131도가 나오는데 

17번점 기준으로 xy평면에서 131도가 맞긴 하다. 

 

 

 

 

 

 

 

90 - 131 = -41이 되는데

-41을 전역계 요

 

z축 회전각은 -10도 이므로

-10 * -1 = 10을 전역계 피치

를주면 

피치는 맞는데 요가 좀잘못됨

 

 

 

 

 

 

-41이 아닌 41을 주면 원하는 각이나오긴하다.

 

 

 

전역계 요각 계산할때 

보라색 y축 기준 각도로 해야될듯하다.

 

 

 

 

 

두점 사이 피치, 요 계산하는 코드는 이런식으로 정리

 

 

 

 

 

c++로 고친결과

void ADesktopGameModeBase::get_pitch_yaw(cv::Point3f pt_start, cv::Point3f pt_end, float& pitch, float& yaw) {
	float dx = pt_end.x - pt_start.x;
	float dy = pt_end.y - pt_start.y;
	dy *= -1;
	yaw = std::atan2(dy, dx) * 180 / CV_PI;
	yaw = yaw - 90;

	float dz = pt_end.z - pt_start.z;
	float xy_norm = std::sqrt(dx * dx + dy * dy);
	pitch = std::atan2(dz, xy_norm) * 180 / CV_PI;
	pitch *= -1;
}

 

 

 

 

c++ 롤피치요 를 블루프린트 가져와서 쓸수있도록 코드수정

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once


#include "Blaze.h"

#include "Windows/AllowWindowsPlatformTypes.h"
#include <Windows.h>
#include "Windows/HideWindowsPlatformTypes.h"

#include "PreOpenCVHeaders.h"
#include <opencv2/opencv.hpp>
#include "PostOpenCVHeaders.h"

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "DesktopGameModeBase.generated.h"

/**
 * 
 */
UCLASS()
class HANDDESKTOP_API ADesktopGameModeBase : public AGameModeBase
{
	GENERATED_BODY()

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	UFUNCTION(BlueprintCallable)
	void ReadFrame();




	int monitorWidth = 1920;
	int monitorHeight = 1080;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UTexture2D* imageTextureScreen1;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UTexture2D* imageTextureScreen2;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UTexture2D* imageTextureScreen3;
	cv::Mat imageScreen1;
	cv::Mat imageScreen2;
	cv::Mat imageScreen3;

	void ScreensToCVMats();
	void CVMatsToTextures();



	int webcamWidth = 640;
	int webcamHeight = 480;

	cv::VideoCapture capture;
	cv::Mat webcamImage;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UTexture2D* webcamTexture;
	void MatToTexture2D(const cv::Mat InMat);


	//var and functions with blaze
	Blaze blaze;
	cv::Mat img256;
	cv::Mat img128;
	float scale;
	cv::Scalar pad;





	// vars and funcs for rotator
	int hand_conns_indexes[14] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
	void get_pitch_yaw(cv::Point3f pt_start, cv::Point3f pt_end, float& pitch, float& yaw);
	void make_map_for_rotators(std::vector<cv::Mat> denorm_imgs_landmarks);
	void make_map_bone();

	UPROPERTY(BlueprintReadWrite, Category="RotatorMap")
	TMap<int32, float> MapPitch;
	UPROPERTY(BlueprintReadWrite, Category = "RotatorMap")
	TMap<int32, float> MapYaw;
	UPROPERTY(BlueprintReadWrite, Category = "RotatorMap")
	TMap<int32, FString> MapBoneLeft;
	UPROPERTY(BlueprintReadWrite, Category = "RotatorMap")
	TMap<int32, FString> MapBoneRight;


};

 

 

 

 

 

 

 

 

// Fill out your copyright notice in the Description page of Project Settings.

#include "DesktopGameModeBase.h"


void ADesktopGameModeBase::BeginPlay()
{
	Super::BeginPlay();
	blaze = Blaze();

	capture = cv::VideoCapture(0);
	if (!capture.isOpened())
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam failed"));
		return;
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam Success"));
	}
	capture.set(cv::CAP_PROP_FRAME_WIDTH, webcamWidth);
	capture.set(cv::CAP_PROP_FRAME_HEIGHT, webcamHeight);


	webcamTexture = UTexture2D::CreateTransient(monitorWidth, monitorHeight, PF_B8G8R8A8);


	imageScreen1 = cv::Mat(monitorHeight, monitorWidth, CV_8UC4);
	imageScreen2 = cv::Mat(monitorHeight, monitorWidth, CV_8UC4);
	imageScreen3 = cv::Mat(monitorHeight, monitorWidth, CV_8UC4);
	imageTextureScreen1 = UTexture2D::CreateTransient(monitorWidth, monitorHeight, PF_B8G8R8A8);
	imageTextureScreen2 = UTexture2D::CreateTransient(monitorWidth, monitorHeight, PF_B8G8R8A8);
	imageTextureScreen3 = UTexture2D::CreateTransient(monitorWidth, monitorHeight, PF_B8G8R8A8);
	
	make_map_bone();
}


void ADesktopGameModeBase::ReadFrame()
{
	if (!capture.isOpened())
	{
		return;
	}
	capture.read(webcamImage);

	/*
	get filtered detections
	*/
	blaze.ResizeAndPad(webcamImage, img256, img128, scale, pad);
	//UE_LOG(LogTemp, Log, TEXT("scale value: %f, pad value: (%f, %f)"), scale, pad[0], pad[1]);
	std::vector<Blaze::PalmDetection> normDets = blaze.PredictPalmDetections(img128);
	std::vector<Blaze::PalmDetection> denormDets = blaze.DenormalizePalmDetections(normDets, webcamWidth, webcamHeight, pad);
	std::vector<Blaze::PalmDetection> filteredDets = blaze.FilteringDets(denormDets, webcamWidth, webcamHeight);





	std::vector<cv::Rect> handRects = blaze.convertHandRects(filteredDets);
	std::vector<cv::Mat> handImgs;
	blaze.GetHandImages(webcamImage, handRects, handImgs);
	std::vector<cv::Mat> imgs_landmarks = blaze.PredictHandDetections(handImgs);
	std::vector<cv::Mat> denorm_imgs_landmarks = blaze.DenormalizeHandLandmarks(imgs_landmarks, handRects);

	make_map_for_rotators(denorm_imgs_landmarks);



	//draw hand rects/ plam detection/ dets info/ hand detection
	blaze.DrawRects(webcamImage, handRects);
	blaze.DrawPalmDetections(webcamImage, filteredDets);
	blaze.DrawDetsInfo(webcamImage, filteredDets, normDets, denormDets);
	blaze.DrawHandDetections(webcamImage, denorm_imgs_landmarks);

	//cv::mat to utexture2d
	MatToTexture2D(webcamImage);


	/*
	모니터 시각화
	*/
	ScreensToCVMats();
	CVMatsToTextures();
}


void ADesktopGameModeBase::MatToTexture2D(const cv::Mat InMat)
{
	if (InMat.type() == CV_8UC3)//example for pre-conversion of Mat
	{
		cv::Mat resizedImage;
		cv::resize(InMat, resizedImage, cv::Size(monitorWidth, monitorHeight));
		cv::Mat bgraImage;
		//if the Mat is in BGR space, convert it to BGRA. There is no three channel texture in UE (at least with eight bit)
		cv::cvtColor(resizedImage, bgraImage, cv::COLOR_BGR2BGRA);

		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = webcamTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, bgraImage.data, bgraImage.total() * bgraImage.elemSize());//copy the data
		Mip.BulkData.Unlock();
		webcamTexture->PostEditChange();
		webcamTexture->UpdateResource();
	}
	else if (InMat.type() == CV_8UC4)
	{
		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = webcamTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, InMat.data, InMat.total() * InMat.elemSize());//copy the data
		Mip.BulkData.Unlock();
		webcamTexture->PostEditChange();
		webcamTexture->UpdateResource();
	}
	//if the texture hasnt the right pixel format, abort.
	webcamTexture->PostEditChange();
	webcamTexture->UpdateResource();
}



void ADesktopGameModeBase::ScreensToCVMats()
{
	HDC hScreenDC = GetDC(NULL);
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
	int screenWidth = GetDeviceCaps(hScreenDC, HORZRES);
	int screenHeight = GetDeviceCaps(hScreenDC, VERTRES);

	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);

	//screen 1
	BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
	GetBitmapBits(hBitmap, imageScreen1.total() * imageScreen1.elemSize(), imageScreen1.data);

	//screen 2
	BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 1920, 0, SRCCOPY);
	GetBitmapBits(hBitmap, imageScreen2.total() * imageScreen2.elemSize(), imageScreen2.data);

	//screen 3
	BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 3840, 0, SRCCOPY);
	GetBitmapBits(hBitmap, imageScreen3.total() * imageScreen3.elemSize(), imageScreen3.data);
	SelectObject(hMemoryDC, hOldBitmap);


	DeleteDC(hScreenDC);
	DeleteDC(hMemoryDC);

	DeleteObject(hBitmap);
	DeleteObject(hOldBitmap);

}


void ADesktopGameModeBase::CVMatsToTextures()
{
	for (int i = 0; i < 3; i++)
	{
		if (i == 0)
		{
			FTexture2DMipMap& Mip = imageTextureScreen1->GetPlatformData()->Mips[0];
			void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
			FMemory::Memcpy(Data, imageScreen1.data, imageScreen1.total() * imageScreen1.elemSize());//copy the data
			Mip.BulkData.Unlock();

			imageTextureScreen1->PostEditChange();
			imageTextureScreen1->UpdateResource();
		}
		else if (i == 1)
		{
			FTexture2DMipMap& Mip = imageTextureScreen2->GetPlatformData()->Mips[0];
			void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
			FMemory::Memcpy(Data, imageScreen2.data, imageScreen2.total() * imageScreen2.elemSize());//copy the data
			Mip.BulkData.Unlock();

			imageTextureScreen2->PostEditChange();
			imageTextureScreen2->UpdateResource();
		}
		else if (i == 2)
		{
			FTexture2DMipMap& Mip = imageTextureScreen3->GetPlatformData()->Mips[0];
			void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
			FMemory::Memcpy(Data, imageScreen3.data, imageScreen3.total() * imageScreen3.elemSize());//copy the data
			Mip.BulkData.Unlock();

			imageTextureScreen3->PostEditChange();
			imageTextureScreen3->UpdateResource();
		}


	}
}





void ADesktopGameModeBase::get_pitch_yaw(cv::Point3f pt_start, cv::Point3f pt_end, float& pitch, float& yaw) {
	float dx = pt_end.x - pt_start.x;
	float dy = pt_end.y - pt_start.y;
	dy *= -1;
	yaw = std::atan2(dy, dx) * 180 / CV_PI;
	yaw = yaw - 90;

	float dz = pt_end.z - pt_start.z;
	float xy_norm = std::sqrt(dx * dx + dy * dy);
	pitch = std::atan2(dz, xy_norm) * 180 / CV_PI;
	pitch *= -1;
}

void ADesktopGameModeBase::make_map_for_rotators(std::vector<cv::Mat> denorm_imgs_landmarks)
{
	for (auto& denorm_landmarks : denorm_imgs_landmarks)
	{
		std::vector<std::array<int, 2>> HAND_CONNECTIONS = blaze.HAND_CONNECTIONS;
		for (auto& hand_conns_index : hand_conns_indexes)
		{
			std::array<int, 2> hand_conns = HAND_CONNECTIONS.at(hand_conns_index);
			float pitch, yaw;
			cv::Point3f pt_start, pt_end;

			pt_start.x = denorm_landmarks.at<float>(hand_conns.at(0), 0);
			pt_start.y = denorm_landmarks.at<float>(hand_conns.at(0), 1);
			pt_start.z = denorm_landmarks.at<float>(hand_conns.at(0), 2);

			pt_end.x = denorm_landmarks.at<float>(hand_conns.at(1), 0);
			pt_end.y = denorm_landmarks.at<float>(hand_conns.at(1), 1);
			pt_end.z = denorm_landmarks.at<float>(hand_conns.at(1), 2);


			get_pitch_yaw(pt_start, pt_end, pitch, yaw);
			MapPitch.Add(hand_conns_index, pitch);
			MapYaw.Add(hand_conns_index, yaw);
		}
	}
}


/*
	std::vector<std::array<int, 2>> HAND_CONNECTIONS = {
	{0, 1}, {1, 2}, {2, 3}, {3, 4},
	{5, 6}, {6, 7}, {7, 8},
	{9, 10}, {10, 11}, {11, 12},
	{13, 14}, {14, 15}, {15, 16},
	{17, 18}, {18, 19}, {19, 20},
	{0, 5}, {5, 9}, {9, 13}, {13, 17}, {0, 17}
	};
*/


void ADesktopGameModeBase::make_map_bone()
{
	MapBoneLeft.Add(2, FString("b_l_thumb2"));
	MapBoneLeft.Add(3, FString("b_l_thumb3"));
	MapBoneLeft.Add(4, FString("b_l_index1"));
	MapBoneLeft.Add(5, FString("b_l_index2"));
	MapBoneLeft.Add(6, FString("b_l_index3"));
	MapBoneLeft.Add(7, FString("b_l_middle1"));
	MapBoneLeft.Add(8, FString("b_l_middle2"));
	MapBoneLeft.Add(9, FString("b_l_middle3"));
	MapBoneLeft.Add(10, FString("b_l_ring1"));
	MapBoneLeft.Add(11, FString("b_l_ring2"));
	MapBoneLeft.Add(12, FString("b_l_ring3"));
	MapBoneLeft.Add(13, FString("b_l_pinky1"));
	MapBoneLeft.Add(14, FString("b_l_pinky2"));
	MapBoneLeft.Add(15, FString("b_l_pinky3"));


	MapBoneRight.Add(2, FString("b_r_thumb2"));
	MapBoneRight.Add(3, FString("b_r_thumb3"));
	MapBoneRight.Add(4, FString("b_r_index1"));
	MapBoneRight.Add(5, FString("b_r_index2"));
	MapBoneRight.Add(6, FString("b_r_index3"));
	MapBoneRight.Add(7, FString("b_r_middle1"));
	MapBoneRight.Add(8, FString("b_r_middle2"));
	MapBoneRight.Add(9, FString("b_r_middle3"));
	MapBoneRight.Add(10, FString("b_r_ring1"));
	MapBoneRight.Add(11, FString("b_r_ring2"));
	MapBoneRight.Add(12, FString("b_r_ring3"));
	MapBoneRight.Add(13, FString("b_r_pinky1"));
	MapBoneRight.Add(14, FString("b_r_pinky2"));
	MapBoneRight.Add(15, FString("b_r_pinky3"));


}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

출력 시켜봣는데 yaw는 좀 안맞는거같은데 피치는 대강 맞는듯하다

 

 

 

 

 

 

 

 

 

 

 

 

일단 본 회전하는걸 해봤는데

 

 

 

이유를 모르겠지만 되긴한다.

 

 

하지만 월드 공간 기준으로 회전해서 되지 

컴포넌트 공간 기준 회전으론 잘 동작되진 않는다.

 

 

 

 

 

 

https://www.youtube.com/watch?v=ZmiZ6VkSJBE

 

 

https://www.youtube.com/watch?v=9dZjcFW3BRY

 

 

 

 

 

대충 손 모델 가져와서 스켈레탈 메시로 만들어 시도해보려 했으나 일단망함

 

 

 

 

 

 

 

+ Recent posts