쓰리디아이 / 2015
낙하산 시뮬레이터
실지형·아바타·관제 화면의 좌표를 연결하다
PROJECT IN ACTION
실행 화면과 시연


낙하산 시뮬레이터 · 시연 1
OVERVIEW
프로젝트와 나의 역할
Oculus HMD, 모션캡처, Unity 3D 지형과 WPF 2D 상황도 사이의 데이터 연동을 담당했습니다.
- Oculus Rift HMD Unity 통합
- GIS 데이터를 활용한 3D 실지형 맵핑
- 네트워크를 통한 외부 3D 관제 기능 구현
- Mocap 센서 데이터를 통한 실시간 아바타 움직임 구현
- GIS 데이터 맵을 이용한 2D 맵 전시 기능 구현
- 실시간 Unity3D 내 3차원 좌표 데이터와 2D GIS 맵 데이터 동기화 기능 구현
ENGINEERING NOTES
기능별 구현과 문제 해결
담당 기능의 배경부터 구현 방식과 선택한 범위까지 정리했습니다.
HMD 시점과 움직이는 아바타의 방향 정렬
배경과 과제
실제 사용자는 장비에 고정되어 있지만 가상 아바타는 낙하산 동역학에 따라 움직였습니다.
내가 구현한 방식
초기 아바타 머리 방향과 HMD 카메라 방향을 맞추고, 아바타와 카메라의 부모·자식 관계 및 오프셋을 이용해 시점을 연동했습니다.
선택의 이유와 범위
사용자의 머리 회전과 가상 공간에서의 아바타 이동을 함께 다뤄야 하는 장비형 VR의 조건을 반영했습니다.
2026 / RECONSTRUCTED EXAMPLE
공통 기준으로 자세 좌표 옮기기
센서 기준의 관절 자세를 로컬 좌표로 바꾼 뒤 아바타 기준으로 옮깁니다.
- 센서 관절
- 기준 Pose 역변환
- 아바타 기준 적용
- 출력 Pose
설명용 개념도 · 실제 제품 화면이나 전체 시스템 설계도가 아닙니다.
사용 방법과 적용 범위
보정된 sensorRoot, sensorJoint, avatarRoot Pose를 Retarget에 전달합니다.
축·단위·스케일은 미리 일치해야 합니다. 장비 캘리브레이션이나 스켈레톤 리깅 전체를 구현하지 않습니다.
예제 코드 펼치기포트폴리오용 재구성 코드 · 실제 업무 소스 아님
// 2026 portfolio reconstruction. Not original production source or a sensor SDK adapter.
using System;
using UnityEngine;
namespace PortfolioExamples
{
public static class PoseAlignment
{
// Sensor and avatar roots must both be calibrated. Scaling is intentionally unsupported.
public static Pose Retarget(Pose sensorRoot, Pose sensorJoint, Pose avatarRoot)
{
Vector3 localPosition = Quaternion.Inverse(sensorRoot.rotation) * (sensorJoint.position - sensorRoot.position);
Quaternion localRotation = Quaternion.Inverse(sensorRoot.rotation) * sensorJoint.rotation;
return new Pose(avatarRoot.position + avatarRoot.rotation * localPosition,
avatarRoot.rotation * localRotation);
}
public static Pose AlignHead(Vector3 markerWorld, Quaternion hmdRotation, Quaternion rotationOffset)
=> new Pose(markerWorld, rotationOffset * hmdRotation);
}
}
훈련 시작점을 기준으로 좌표를 다루기
배경과 과제
넓은 지형에서는 원점에서 멀어질수록 부동소수점 정밀도가 문제가 되었습니다.
내가 구현한 방식
훈련 시작점을 기준으로 지형 좌표에 오프셋을 적용했습니다. WPF 2D 상황도에 표시할 때는 해당 오프셋을 역으로 반영해 GIS 좌표와 연결했습니다.
선택의 이유와 범위
3D 훈련 화면과 2D 관제 화면이 서로 다른 좌표 기준을 사용하더라도 같은 위치를 가리키도록 구성했습니다.
훈련 데이터 동기화와 모션캡처 적용
배경과 과제
다수 훈련자의 시간축을 맞추는 동시에, 장비 모터 구동 중 일부 모션캡처 데이터가 불안정한 문제가 있었습니다.
내가 구현한 방식
메인 훈련자 측에서 데이터를 모아 처리·재전송하는 흐름을 구성했습니다. 센서 문제가 심한 다리 입력은 제외하고 팔 움직임을 중심으로 아바타 자세를 연결했습니다.
선택의 이유와 범위
센서 신뢰도에 따라 사용하는 신체 부위와 자세 표현 범위를 조정했습니다.
2026 / RECONSTRUCTED EXAMPLE
프레임 단위로 지연시키는 데이터 버퍼
정해진 개수의 샘플을 보관한 뒤 입력 순서대로 출력합니다.
- 샘플 입력
- Queue 보관
- 지연 길이 확인
- 순서대로 출력
설명용 개념도 · 실제 제품 화면이나 전체 시스템 설계도가 아닙니다.
사용 방법과 적용 범위
new FrameDelayBuffer<T>(delayFrames)를 만들고 샘플마다 Push를 호출합니다.
프레임 수 기준 지연입니다. 가변 네트워크 지연 보정이나 TCP 전송 계층은 포함하지 않습니다.
예제 코드 펼치기포트폴리오용 재구성 코드 · 실제 업무 소스 아님
// 2026 portfolio reconstruction. Not original production source.
using System;
using System.Collections.Generic;
namespace PortfolioExamples
{
// Fixed sample-count delay, not a network jitter buffer or a wall-clock guarantee.
public sealed class FrameDelayBuffer<T>
{
readonly int delay;
readonly Queue<T> queue = new Queue<T>();
public FrameDelayBuffer(int delayFrames)
{ if (delayFrames < 0) throw new ArgumentOutOfRangeException(nameof(delayFrames)); delay = delayFrames; }
public bool Push(T value, out T output)
{
queue.Enqueue(value);
if (queue.Count <= delay) { output = default(T); return false; }
output = queue.Dequeue(); return true;
}
public void Reset() => queue.Clear();
public int BufferedCount => queue.Count;
}
}
위성지도 기반 2D 관제 화면
배경과 과제
대용량 위성지도를 표시하고 Unity의 훈련 위치를 2D 지도와 연결해야 했습니다.
내가 구현한 방식
MapWinGIS 기반 지도 표시와 실시간 좌표 연동을 담당했습니다.
선택의 이유와 범위
지도 표시와 좌표 연동에 초점을 맞춘 구현입니다. 지도 파일 변환·압축의 상세 방식과 성능 측정치는 여기서 다루지 않습니다.
MORE SCREENS
추가 실행 화면
CODE & VALIDATION
코드와 검증 범위
기존 코드 발췌와 2026년 포트폴리오용 재구성 코드를 구분해 제공합니다. 재구성 코드는 실제 제품 소스가 아니며, 일반 원리를 설명하기 위해 새로 작성했습니다.
Unity 6000.0.23f1 컴파일 및 Editor 검증 56개 통과. 실제 장비 연동과 제품 통합은 검증 범위에 포함하지 않습니다.
예제별 사용법과 검증 내용 ↗



