首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实时对象绘画

实时对象绘画
EN

Stack Overflow用户
提问于 2012-01-10 13:21:28
回答 1查看 1.4K关注 0票数 3

我正在尝试对物体纹理进行实时绘制。现在使用Irrlicht,但这并不重要。

到目前为止,我已经使用这个算法获得了正确的UV坐标:

找出哪个对象的三角形用户选择(光线投射,没有真正的difficult)

  • find出那个三角形

  • 上交点的UV (重心)坐标),找出每个三角形顶点

  • 的UV (纹理)坐标,找出每个三角形顶点

  • 的UV (纹理)坐标,求出交点

的纹理图像坐标。

但是不知怎么的,当我在纹理图像的第五步画的时候,我得到了完全错误的结果。因此,当在光标点中绘制矩形时,其X(或Z)坐标反转:

下面是我用来获取纹理坐标的代码:

代码语言:javascript
复制
core::vector2df getPointUV(core::triangle3df tri, core::vector3df p)
{
    core::vector3df 
    v0 = tri.pointC - tri.pointA,
    v1 = tri.pointB - tri.pointA,
    v2 = p - tri.pointA;

    float dot00 = v0.dotProduct(v0),
    dot01 = v0.dotProduct(v1),
    dot02 = v0.dotProduct(v2),
    dot11 = v1.dotProduct(v1),
    dot12 = v1.dotProduct(v2);

    float invDenom = 1.f / ((dot00 * dot11) - (dot01 * dot01)),
    u = (dot11 * dot02 - dot01 * dot12) * invDenom,
    v = (dot00 * dot12 - dot01 * dot02) * invDenom;

    scene::IMesh* m = Mesh->getMesh(((scene::IAnimatedMeshSceneNode*)Model)->getFrameNr());

    core::array<video::S3DVertex> VA, VB, VC;
    video::SMaterial Material;

    for (unsigned int i = 0; i < m->getMeshBufferCount(); i++)
    {
    scene::IMeshBuffer* mb = m->getMeshBuffer(i);
    video::S3DVertex* vertices = (video::S3DVertex*) mb->getVertices();

    for (unsigned long long v = 0; v < mb->getVertexCount(); v++)
    {
        if (vertices[v].Pos == tri.pointA)
        VA.push_back(vertices[v]); else
        if (vertices[v].Pos == tri.pointB)
        VB.push_back(vertices[v]); else
        if (vertices[v].Pos == tri.pointC)
        VC.push_back(vertices[v]);

        if (vertices[v].Pos == tri.pointA || vertices[v].Pos == tri.pointB || vertices[v].Pos == tri.pointC)
        Material = mb->getMaterial();

        if (VA.size() > 0 && VB.size() > 0 && VC.size() > 0)
        break;
    }

    if (VA.size() > 0 && VB.size() > 0 && VC.size() > 0)
        break;
    }

    core::vector2df 
    A = VA[0].TCoords,
    B = VB[0].TCoords,
    C = VC[0].TCoords;

    core::vector2df P(A + (u * (C - A)) + (v * (B - A)));
    core::dimension2du Size = Material.getTexture(0)->getSize();
    CursorOnModel = core::vector2di(Size.Width * P.X, Size.Height * P.Y);
    int X = Size.Width * P.X, Y = Size.Height * P.Y;

    // DRAWING SOME RECTANGLE    
    Material.getTexture(0)->lock(true);
    Device->getVideoDriver()->setRenderTarget(Material.getTexture(0), true, true, 0);
        Device->getVideoDriver()->draw2DRectangle(video::SColor(255, 0, 100, 75), core::rect<s32>((X - 10), (Y - 10), 
            (X + 10), (Y + 10)));
    Device->getVideoDriver()->setRenderTarget(0, true, true, 0);
    Material.getTexture(0)->unlock();

    return core::vector2df(X, Y);
}

我只想让我的目标实时可画。我目前的问题是:错误的纹理坐标计算非唯一顶点UV坐标(所以,在矮人斧头的一边画一些东西会在斧头的另一边画同样的东西)。

我该怎么做?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-01 12:55:25

我能用你的代码库让它为我工作。

是你的第二个问题“非唯一的顶点UV坐标”:你是完全正确的,你需要唯一的顶点uv来完成这个工作,这意味着你必须拆开你的模型,不要使用共享的uv空间,例如镜像元素和东西。(例如,左/右引导-如果他们使用相同的紫外线空间,你将自动在两者上画,在那里你希望一个是红色的,另一个是绿色的)。您可以签出"uvlayout“(工具)或uv展开修饰符ind3ds max。

是第一个也是更重要的问题:“**错误的纹理坐标计算”:以but为中心的坐标的计算是正确的,但正如我所设想的那样,输入的数据是错误的。我假设您使用irrlicht的CollisionManager和TriangleSelector获得三角形和TriangleSelector。问题是,三角形顶点的位置(您从collisionTest得到的返回值)在WorldCoordiates中。但是您需要在ModelCoordinates中使用它们进行计算,下面是您需要做的工作:

伪码

将包含命中三角形网格的节点作为参数添加到getPointUV()

  • get逆绝对变换-矩阵,方法是调用节点->getAbsoluteTransformation(),通过该逆矩阵对三角形的顶点进行inverse

  • transform,并将这些值用于该方法的其余部分。

下面您会发现我的优化方法用于非常简单的网格(一个网格,只有一个网格缓冲区)。

代码:

代码语言:javascript
复制
irr::core::vector2df getPointUV(irr::core::triangle3df tri, irr::core::vector3df p, irr::scene::IMeshSceneNode* pMeshNode, irr::video::IVideoDriver* pDriver)
{
    irr::core::matrix4 inverseTransform(
    pMeshNode->getAbsoluteTransformation(),
      irr::core::matrix4::EM4CONST_INVERSE);

    inverseTransform.transformVect(tri.pointA);
    inverseTransform.transformVect(tri.pointB);
    inverseTransform.transformVect(tri.pointC);

    irr::core::vector3df 
    v0 = tri.pointC - tri.pointA,
    v1 = tri.pointB - tri.pointA,
    v2 = p - tri.pointA;

    float dot00 = v0.dotProduct(v0),
    dot01 = v0.dotProduct(v1),
    dot02 = v0.dotProduct(v2),
    dot11 = v1.dotProduct(v1),
    dot12 = v1.dotProduct(v2);

    float invDenom = 1.f / ((dot00 * dot11) - (dot01 * dot01)),
    u = (dot11 * dot02 - dot01 * dot12) * invDenom,
    v = (dot00 * dot12 - dot01 * dot02) * invDenom;

    irr::video::S3DVertex A, B, C;
    irr::video::S3DVertex* vertices = static_cast<irr::video::S3DVertex*>(
      pMeshNode->getMesh()->getMeshBuffer(0)->getVertices());

    for(unsigned int i=0; i < pMeshNode->getMesh()->getMeshBuffer(0)->getVertexCount(); ++i)
    {
      if( vertices[i].Pos == tri.pointA)
      {
        A = vertices[i];
      }
      else if( vertices[i].Pos == tri.pointB)
      {
        B = vertices[i];
      }
      else if( vertices[i].Pos == tri.pointC)
      {
        C = vertices[i];
      }
    }

    irr::core::vector2df t2 = B.TCoords - A.TCoords;
    irr::core::vector2df t1 = C.TCoords - A.TCoords;

    irr::core::vector2df uvCoords = A.TCoords + t1*u + t2*v;

    return uvCoords;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8803917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档