2016-06-02 4 views
0

현재 (열린 발명가의 경우 3D 공간에서 포인트로 구성된 (곡선) 선이 있지만이 문제에 대한 해결책은 비 특정 제품).3D 선에서 투영 된 리본을 "앞으로 직면"하는 방법으로 시각화하는 방법

우리는 리본에서 직각으로 돌출 된 리본을 묘사하고 카메라가 회전 할 때 항상 카메라를 마주 보게하는 서페이스를 그려 보려고합니다.

(예를 들어, 사용자는 라인 자체가 측면의 하나 인 라인의 곡선을 설명하는 리본을 볼 수 있습니다. 그리고 나서 장면 주위를 회전 할 때 리본이 라인을 "회전"하므로 항상 항상 사용자)

에 직면하고 우리는이 :

  • 카메라

  • 라인을 따라 각 지점의 위치의 위치와 회전

우리는 접근 점의 각 쌍에 대해 카메라에 직각 인 평면과 그 점들 사이의 선에 직각 인 평면과 교차하는 선을 찾고 그에 따라 설정된 거리를 투영하는 방법을 생각했습니다 그러나 이것은 올바른 결과에 가까운 곳에서 우리에게 아무런 도움도되지 못했습니다. (아래의 오작동 코드).

이 접근법이 맞습니까? 그렇다면 아래 코드에서 설명해야하는 것은 무엇입니까?

그렇지 않다면 핵심 목표 (리본은 항상 사용자를 향하고 있음)를 어떻게 달성 할 수 있습니까?

SbVec3f getOuterPoint(SbVec3f p3, const float ribbon_width, float cosine, float sine) 
{ 
    return SbVec3f(p3[0] + ribbon_width*cosine, p3[1] - ribbon_width*sine, p3[2]); 
} 

SbVec3f getOuterPoint(SbVec3f old_p3, SbVec3f other_point, const float ribbon_width) 
{ 
    float oangle = atan2(old_p3[1] - other_point[1], old_p3[0] - other_point[0]); 
    float ocosine = cosf(oangle); 
    float osine = sinf(oangle); 
    return getOuterPoint(old_p3, ribbon_width, ocosine, osine); 
} 

SbVec3f getOuterPoint(SbVec3f p0, SbVec3f p1, const float ribbon_width, SoCamera* camera) 
{ 
    SbVec3f axis; 
    float angle; 
    SoSFRotation camera_rotation = camera->orientation; 
    camera_rotation.getValue(axis, angle); 
    //std::cout << axis[0] << " " << axis[1] << " " << axis[2] << ":" << angle << std::endl; 

    const SbVec3f &camera_position = camera->position.getValue(); 

    SbVec3f camera_axis = axis; 

    SbVec3f well_axis = p1 - p0; 

    well_axis.normalize(); 
    camera_axis.normalize(); 

    float cam_constant[3] = { -p1[0], -p1[1], -p1[2] }; 
    float well_constant[3] = { -p1[0], -p1[1], -p1[2] }; 

    /* 

    //float p1_constant = camera_axis[0] * p1[0] + camera_axis[1] * p1[1] + camera_axis[2] * p1[2] 
    // - (camera_axis[0] * camera_position[0] + camera_axis[1] * camera_position[1] + camera_axis[2] * camera_position[2]); 

    //// X, Y, Z are unknown 
    //float line_unknown = camera_axis[0] * X + camera_axis[1] * Y + camera_axis[2] * Z; 

    // 
    // 
    // camera_axis.x * (x - p1[0]) + camera_axis.y * (y - p1[1]) + camera_axis.z * (z - p1[2]) = 0  (1) 
    // well_axis.x * (x - p1[0]) + well_axis.y * (y - p1[1]) + well_axis.z * (z - p1[2]) = 0  (2) 

    // let z become free variable t 

    // camera_axis.x * (x - p1[0]) + camera_axis.y * (y - p1[1]) = - camera_axis.z * (t - p1[2]) 
    // well_axis.x * (x - p1[0]) + well_axis.y * (y - p1[1]) = - well_axis.z * (t - p1[2]) 

    // camera_axis.x * (x - p1[0]) + camera_axis.y * (y - p1[1]) = - camera_axis.z * t - camera_axis.z * p1[2] 
    // well_axis.x * (x - p1[0]) + well_axis.y * (y - p1[1]) = - well_axis.z * t - well_axis.z * p1[2] 

    // camera_axis.x * x + camera_axis.y * y = - camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1] (3) 
    // well_axis.x * x + well_axis.y * y = - well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1]    (4) 

    (3) * well_axis.x: 

    well_axis.x * camera_axis.x * x + well_axis.x * camera_axis.y * y = well_axis.x * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) 

    (4) * camera_axis.x 
    camera_axis.x * well_axis.x * x + camera_axis.x * well_axis.y * y = camera_axis.x * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1]) 

    Subtracting 
    well_axis.x * camera_axis.y * y - camera_axis.x * well_axis.y * y = well_axis.x * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.x * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1]) 

    (well_axis.x * camera_axis.y - camera_axis.x * well_axis.y) * y = well_axis.x * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.x * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1]) 
    y = well_axis.x * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.x * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1])/(well_axis.x * camera_axis.y - camera_axis.x * well_axis.y) 


    (3) * well_axis.y 
    well_axis.y * camera_axis.x * x + well_axis.y * camera_axis.y * y = well_axis.y * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) 
    (4) * camera_axis.y 
    camera_axis.y * well_axis.x * x + camera_axis.y * well_axis.y * y = camera_axis.y * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1]) 

    Subtracting 
    x = well_axis.y * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.y * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1])/well_axis.y * camera_axis.x - camera_axis.y * well_axis.x 


    So: 
    x = well_axis.y * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.y * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1])/(well_axis.y * camera_axis.x - camera_axis.y * well_axis.x) 
    y = well_axis.x * (- camera_axis.z * t - camera_axis.z * p1[2] + camera_axis.x *p1[0] + camera_axis.y * p1[1]) - camera_axis.x * (- well_axis.z * t - well_axis.z * p1[2] + well_axis.x *p1[0] + well_axis.y * p1[1])/(well_axis.x * camera_axis.y - camera_axis.x * well_axis.y) 
    z = t 


    x = ((well_axis.z * camera_axis.y - camera_axis.z * well_axis.y) * t 
    - camera_axis.z * well_axis.y * p1[2] 
    + camera_axis.x * well_axis.y * p1[0] 
    + well_axis.z * camera_axis.y * p1[2] 
    - well_axis.x * camera_axis.y * p1[0]) 
    /(well_axis.y * camera_axis.x - camera_axis.y * well_axis.x) 

    y = (- camera_axis.z * well_axis.x * t - camera_axis.z * well_axis.x * p1[2] + camera_axis.x * well_axis.x * p1[0] + camera_axis.y * well_axis.x * p1[1] + well_axis.z * camera_axis.x * t + well_axis.z * camera_axis.x * p1[2] - well_axis.x * camera_axis.x * p1[0] - well_axis.y * camera_axis.x * p1[1])/(well_axis.x * camera_axis.y - camera_axis.x * well_axis.y) 


    y = ((well_axis.z * camera_axis.x - camera_axis.z * well_axis.x) * t 
    - camera_axis.z * well_axis.x * p1[2] 
    + camera_axis.y * well_axis.x * p1[1] 
    + well_axis.z * camera_axis.x * p1[2] 
    - well_axis.y * camera_axis.x * p1[1]) 
    /(well_axis.x * camera_axis.y - camera_axis.x * well_axis.y) 


    // Given these two equations, we now have a parameterised equation 

    // (x,y,z) = (mt + a, nt + b, t) = (m, n, 1)t + (a + b + 0) 
    // 
    // m = ((well_axis[2] * camera_axis[1] - camera_axis[2] * well_axis[1]))/(well_axis[1] * camera_axis[0] - camera_axis[1] * well_axis[0]) 
    // 
    // n = ((well_axis[2] * camera_axis[0] - camera_axis[2] * well_axis[0]))/(well_axis[0] * camera_axis[1] - camera_axis[0] * well_axis[1]) 
    // 
    // a = (- camera_axis[2] * well_axis[1] * p1[2] + camera_axis[0] * well_axis[1] * p1[0] + well_axis[2] * camera_axis[1] * p1[2] - well_axis[0] * camera_axis[1] * p1[0])/(well_axis[1] * camera_axis[0] - camera_axis[1] * well_axis[0]) 
    // 
    // b = (- camera_axis[2] * well_axis[0] * p1[2] +camera_axis[1] * well_axis[0] * p1[1] + well_axis[2] * camera_axis[0] * p1[2] - well_axis[1] * camera_axis[0] * p1[1])/(well_axis[0] * camera_axis[1] - camera_axis[0] * well_axis[1]) 
*/ 

    float m = ((well_axis[2] * camera_axis[1] - camera_axis[2] * well_axis[1]))/(well_axis[1] * camera_axis[0] - camera_axis[1] * well_axis[0]); 
    // 
    float n = ((well_axis[2] * camera_axis[0] - camera_axis[2] * well_axis[0]))/(well_axis[0] * camera_axis[1] - camera_axis[0] * well_axis[1]); 
    // 
    float a = (-camera_axis[2] * well_axis[1] * p1[2] + camera_axis[0] * well_axis[1] * p1[0] + well_axis[2] * camera_axis[1] * p1[2] - well_axis[0] * camera_axis[1] * p1[0])/(well_axis[1] * camera_axis[0] - camera_axis[1] * well_axis[0]); 
    // 
    float b = (-camera_axis[2] * well_axis[0] * p1[2] + camera_axis[1] * well_axis[0] * p1[1] + well_axis[2] * camera_axis[0] * p1[2] - well_axis[1] * camera_axis[0] * p1[1])/(well_axis[0] * camera_axis[1] - camera_axis[0] * well_axis[1]); 

    float t = 2; 

    return SbVec3f(m * t + a, n * t + b, t); 
} 

void setVertices(WellBore * pWell, SoVertexProperty * vertex_property, SoCamera* camera) 
{ 
    int nPoints = pWell->nPoints; 

    const float ribbon_width = 50.0f; 

    int vertex_index = 0; 
    int face_index = 0; 

    int max_to_draw = nPoints; 
    vertex_property->vertex.deleteValues(max_to_draw); 

    SbVec3f on_well0x = pWell->points[1]; 
    SbVec3f in_space0x = getOuterPoint(pWell->points[0], on_well0x, ribbon_width, camera); 

    for (int i = 0; i < max_to_draw - 1; ++i) 
    { 
     SbVec3f on_well0 = pWell->points[i]; 
     SbVec3f on_well1 = pWell->points[i + 1]; 

     SbVec3f in_space1 = getOuterPoint(on_well0, on_well1, ribbon_width, camera); 

     vertex_property->vertex.set1Value(vertex_index + 0, in_space0x); 
     vertex_property->vertex.set1Value(vertex_index + 1, on_well0x); 
     vertex_property->vertex.set1Value(vertex_index + 2, on_well1); 
     vertex_property->vertex.set1Value(vertex_index + 3, in_space0x); 
     vertex_property->vertex.set1Value(vertex_index + 4, in_space1); 

     vertex_index += 5; 

     on_well0x = on_well1; 
     in_space0x = in_space1; 
    } 
} 

void cameraDebug(SoXtViewer * myViewer, WellBore* pWell) 
{ 
    SoCamera* camera = myViewer->getCamera(); 

    SbVec3f camera_position = camera->position.getValue(); 
    //std::cout << camera_position[0] << " " << camera_position[1] << " " << camera_position[2] << std::endl; 

    SbVec3f axis; 
    float angle; 
    SoSFRotation camera_rotation = camera->orientation; 
    camera_rotation.getValue(axis, angle); 
    //std::cout << axis[0] << " " << axis[1] << " " << axis[2] << ":" << angle << std::endl; 

    SoNode* node = SoNode::getByName(SbName("points")); 
    SbString str; 
    SoVertexProperty* vertices = static_cast<SoVertexProperty*>(static_cast<SoVertexShape*>(node)->vertexProperty.getValue()); 
    //std::cout << vertices->vertex.getNum() << str << std::endl; 

    setVertices(pWell, vertices, camera); 
} 

답변

0

질문에 대한 구체적인 답변은 비교적 쉽습니다. 귀하의 질문에 명시된 접근 방식은 정확하지만, 귀하가 제공 한 코드가 너무 복잡해 보입니다. 간단히 : 리본 경로의 두 연속 점과 카메라 방향으로 정의 된 두 번째 벡터로 정의 된 하나의 벡터가 있습니다. 필요한 벡터는이 두 벡터의 교차 곱입니다. 카메라 위치는 관련이 없으며 방향 만 중요합니다.

// Camera (reverse) direction vector 
SbVec3f defVec(0,0,1), camVec; 
const SbRotation& camRot = camera->orientation.getValue(); 
camRot.multVec(defVec, camVec); 
camVec.normalize(); 

'버텍스'는 리본 경로 인 경우, 경로의 각 세그먼트에 대한 두 개의 좌표를 가지고 : 당신이 기본 방향 벡터와 같은 현재 카메라 방향을 사용하여 카메라 방향을 계산하는 열기 발명가를 사용하여 추가 두 사람은 네 개의 좌표가 사용자에 직면 사각형 다각형을 정의하도록 좌표를 오프셋 계산할 수, 뭔가 같은 : 이제

SbVec3f ribVec, orthoVec; 
for (int i = 0; i < numSegs; ++i) { 
    ribVec = verts[i+1] - verts[i]; 
    ribVec.normalize(); 
    orthoVec = camVec.cross(ribVec); 
    orthoVec.normalize(); 
    verts2[i*4 ] = verts[i]; // i*4 because 4 verts per segment 
    verts2[i*4+1] = verts[i+1]; 
    verts2[i*4+2] = verts[i+1] + ribbonWidth * orthoVec; 
    verts2[i*4+3] = verts[i ] + ribbonWidth * orthoVec; 

당신이 열심히 부분에서 작업 할 수 있습니다 -이 사이의 "조인트"를 처리하는 방법 다각형이므로 리본이 멋지게 보입니다 ...