블로그 (Blog)/개발로그 (Devlogs)

Ray intersection with Embree 4

티클러 2025. 12. 26. 21:32

Embree 4를 이용한.. Ray intersection..

#include <embree4/rtcore.h>
#include <iostream>
#include <vector>
#include <limits>

// 내부 에러 발생 시 호출
void errorHandler(void* userPtr, enum RTCError code, const char* str) {
    std::cerr << "Embree Error: " << str << std::endl;
}

int main() {
    // 디바이스 및 장면(Scene) 초기화
    RTCDevice device = rtcNewDevice(nullptr);
    rtcSetDeviceErrorFunction(device, errorHandler, nullptr);
    RTCScene scene = rtcNewScene(device);

    // 삼각형 메시 지오메트리 생성
    RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);

    // 정점 데이터 설정 (수백만 개 가능)
    float* vertices = (float*)rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, 3 * sizeof(float), 3);
    vertices[0] = 0.f; vertices[1] = 0.f; vertices[2] = 0.f; // v0
    vertices[3] = 1.f; vertices[4] = 0.f; vertices[5] = 0.f; // v1
    vertices[6] = 0.f; vertices[7] = 1.f; vertices[8] = 0.f; // v2

    // 인덱스 데이터 설정 (삼각형 연결 정보)
    unsigned* indices = (unsigned*)rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, 3 * sizeof(unsigned), 1);
    indices[0] = 0; indices[1] = 1; indices[2] = 2;

    // 지오메트리 확정 및 장면에 추가
    rtcCommitGeometry(geom);
    rtcAttachGeometry(scene, geom);
    rtcReleaseGeometry(geom); // 장면에 붙인 후 해제 가능 (참조 카운팅)

    // 장면 확정 (BVH 빌드 시작)
    rtcCommitScene(scene);

	// 레이 쿼리 정의
    RTCRayHit rayhit;
    rayhit.ray.org_x = 0.2f; rayhit.ray.org_y = 0.2f; rayhit.ray.org_z = -1.0f;
    rayhit.ray.dir_x = 0.0f; rayhit.ray.dir_y = 0.0f; rayhit.ray.dir_z = 1.0f;
    rayhit.ray.tnear = 0.0f;
    rayhit.ray.tfar = std::numeric_limits<float>::infinity();
    rayhit.ray.mask = -1;
    rayhit.ray.flags = 0;
    rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
    rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;

	// 쿼리
    RTCIntersectArguments args;
    rtcInitIntersectArguments(&args);
    args.feature_mask = RTC_FEATURE_FLAG_ALL; // 모든 기능 활성화 (성능에 따라 조절 가능)

    rtcIntersect1(scene, &rayhit, &args);

    // 결과 확인
    if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
        std::cout << "충돌 발생! 거리: " << rayhit.ray.tfar << std::endl;
        std::cout << "충돌한 면(Primitive) ID: " << rayhit.hit.primID << std::endl;
    } else {
        std::cout << "충돌 없음" << std::endl;
    }

    // 정리
    rtcReleaseScene(scene);
    rtcReleaseDevice(device);

    return 0;
}