0

現在、3D 空間内の点で構成された (曲線) 線があります (開いている発明者ですが、この問題の解決策は製品固有ではない可能性があります)。

その線から直角に投影されたリボンを記述し、回転するときに常にカメラに面するサーフェスを描きたいと考えています。

(たとえば、ユーザーは、線自体をその辺の 1 つとする線の曲線を表すリボンを表示します。次に、シーンを回転させると、リボンは線を中心に「回転」し、常に常にユーザーに面している)

我々は持っています:

  • カメラの位置と回転

  • 線に沿った各点の位置

アプローチの方法は、隣接するポイントのペアごとに、カメラに直交する平面とそれらのポイント間のラインに直交する平面に交差するラインを見つけ、そのラインに沿って設定された距離を投影することであると考えましたが、これはうまくいきませんでした正しい結果に近づくことはできません。(以下のコードは機能していません)。

このアプローチは正しいですか?もしそうなら、それを説明する以下のコードのどこが間違っていますか?

そうでない場合、コアの目的 (リボンは常にユーザーに面している) をどのように達成しますか?

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);
}
4

1 に答える 1

0

あなたの質問に対する具体的な回答は比較的簡単です。質問に記載されているアプローチは正しいように聞こえますが、提供したコードは複雑すぎるようです...簡単に言うと、リボン パス内の 2 つの連続するポイントによって定義された 1 つのベクトルと、カメラの方向によって定義された 2 番目のベクトルがあります。必要なベクトルは、これら 2 つのベクトルの外積です。カメラの位置は関係ありません。方向のみが重要です。Open Inventor を使用して、デフォルトの方向ベクトルと現在のカメラの向きを次のように使用してカメラの方向を計算する必要があります。

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

'verts' がリボン パスの場合、パスの各セグメントに対して 2 つの座標があり、2 つの追加のオフセット座標を計算して、4 つの座標がユーザーに面する四角形のポリゴンを定義するようにすることができます。

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;

これで、より難しい部分に取り組むことができます-これらのポリゴン間の「ジョイント」を処理して、リボンが見栄えがするようにする方法...

于 2016-06-10T19:10:40.223 に答える