Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 单元着色轮廓:边网格编写器未定义所有所需的边_C++_Opengl_3d - Fatal编程技术网

C++ 单元着色轮廓:边网格编写器未定义所有所需的边

C++ 单元着色轮廓:边网格编写器未定义所有所需的边,c++,opengl,3d,C++,Opengl,3d,我正在编写的程序接收3D网格的顶点数据,执行一系列计算(请原谅含糊不清的地方,我稍后将尝试更详细地解释),并输出一个二进制文件,该文件定义网格上边的位置。然后,我的程序在边所在的位置绘制一条彩色线。如果没有适当的顶点着色器,这将看起来像常规三角网格,但一旦应用了适当的顶点着色器,只有“锐利”(其法线的点积大于接近零的值)的边才会在其上绘制线,我对轮廓的实现是不正确的,因为我假设如果一条边不在边缘后面,并且没有定义一条锐边,那么它将是一条轮廓边。我还没有在其他地方找到令人满意的答案,我不想依赖旧的

我正在编写的程序接收3D网格的顶点数据,执行一系列计算(请原谅含糊不清的地方,我稍后将尝试更详细地解释),并输出一个二进制文件,该文件定义网格上边的位置。然后,我的程序在边所在的位置绘制一条彩色线。如果没有适当的顶点着色器,这将看起来像常规三角网格,但一旦应用了适当的顶点着色器,只有“锐利”(其法线的点积大于接近零的值)的边才会在其上绘制线,我对轮廓的实现是不正确的,因为我假设如果一条边不在边缘后面,并且没有定义一条锐边,那么它将是一条轮廓边。我还没有在其他地方找到令人满意的答案,我不想依赖旧的技巧,将网格重新绘制为纯色,并将其渲染为略大于原始网格。该方法完全基于数学,仅依赖网格的顶点数据。我正在编写一个使用以下顶点着色器的程序:

uniform mat4 worldMatrix;
uniform mat4 projMatrix;
uniform mat4 viewProjMatrix;
uniform vec4 eyepos;

attribute vec3 a;
attribute vec3 b;
attribute vec3 n1;
attribute vec3 n2;
attribute float w;

void main()
{
    float a_vertex = dot(eyepos.xyz - a, n1);
    float b_vertex = dot(eyepos.xyz - a, n2);

    if (a_vertex * b_vertex > 0.0) // signs are different, edge is behind the object
    {
        gl_Position = vec4(2.0,2.0,2.0,1.0);
    }

    else // the outline of the figure
    {
        if(w == 0.0)
        {
            vec4 p = vec4(a.x, a.y, a.z, 1.0);
            p = p * worldMatrix * viewProjMatrix;
            gl_Position = p;
        }

        else
        {
            vec4 p = vec4(b.x, b.y, b.z, 1.0);
            p = p * worldMatrix * viewProjMatrix;
            gl_Position = p;
        }
    }

    if(dot(n1, n2) <= 0.2) // there is a sharp edge
    {
        if(w == 0.0)
        {
            vec4 p = vec4(a.x, a.y, a.z, 1.0);
            p = p * worldMatrix * viewProjMatrix;
            gl_Position = p;
        }

        else
        {
            vec4 p = vec4(b.x, b.y, b.z, 1.0);
            p = p * worldMatrix * viewProjMatrix;
            gl_Position = p;
        }
    }
}
uniform mat4 worldMatrix; /* the matrix that defines how to project a point from 
object space to world space.*/
uniform mat4 viewProjMatrix; // the view (pertaining to screen size) matrix times the projection (how to project points to 3D) matrix.
uniform vec4 eyepos; // the position of the eye, given by the program.

attribute vec3 a; // one vertex on an edge, having an x,y,z, and w coordinate.
attribute vec3 b; // the other edge vertex.
attribute vec3 n1; // the normal of the face the edge is on.
attribute vec3 n2; // another normal in the case that an edge shares two faces... otherwise, this is the same as n1.
attribute float w; // an attribute given to make a binary choice between two edges when they draw on top of one another.

void main()
{
    // WORLD SPACE ATTRIBUTES //
    vec4 eye_world = eyepos * worldMatrix;
    vec4 a_world = vec4(a.x, a.y,a.z,1.0) * worldMatrix;
    vec4 b_world = vec4(b.x, b.y,b.z,1.0) * worldMatrix;
    vec4 n1_world = normalize(vec4(n1.x, n1.y,n1.z,0.0) * worldMatrix);
    vec4 n2_world = normalize(vec4(n2.x, n2.y,n2.z,0.0) * worldMatrix);
    // END WORLD SPACE ATTRIBUTES //

    // TEST CASE ATTRIBUTES //
    float a_vertex = dot(eye_world - a_world, n1_world);
    float b_vertex = dot(eye_world - b_world, n2_world);
    float normalDot = dot(n1_world.xyz, n2_world.xyz);
    float vertProduct = a_vertex * b_vertex;
    float hardness = 0.0; // this would be the value for an object made of sharp angles, like a box. Take a look at its use below.
    // END TEST CASE ATTRIBUTES //

    gl_Position = vec4(2.0,2.0,2.0,1.0); // if all else fails, keeping this here will discard unwanted data.

    if (vertProduct >= 0.1) // NOTE: face is behind the viewable portion of the object, normally uses 0.0 when not checking for silhouette
    {
            gl_Position = vec4(2.0,2.0,2.0,1.0);
    }

    else if(vertProduct < 0.1 && vertProduct >= -0.1) // NOTE: face makes almost a right angle with the eye vector
    {
        if(w == 0.0)
        {
            vec4 p = vec4(a_world.x, a_world.y, a_world.z, 1.0);
            p = p  * viewProjMatrix;
            gl_Position = p;
        }
        else
        {
            vec4 p = vec4(b_world.x, b_world.y, b_world.z, 1.0);
            p = p * viewProjMatrix;
            gl_Position = p;
        }
    }

    else // NOTE: this is the case where you can very clearly see a face.
    { // NOTE: the number that normalDot compares to should be its "hardness" value. The more negative the value, the smoother the surface.
       // a.k.a. the less we care about hard edges (when the normals of the faces make an obtuse angle) on the object, the more negative
       // hardness becomes on a scale of 0.0 to -1.0.
        if(normalDot <= hardness) // NOTE: the dot product of the two normals is obtuse, so we are looking at a sharp edge.
        {
            if(w == 0.0)
            {
                vec4 p = vec4(a_world.x, a_world.y, a_world.z, 1.0);
                p = p * viewProjMatrix;
                gl_Position = p;
            }
            else
            {
                vec4 p = vec4(b_world.x, b_world.y, b_world.z, 1.0);
                p = p * viewProjMatrix;
                gl_Position = p;
            }
        }
        else // NOTE: not sharp enough, just throw the vertex away
        {
            gl_Position = vec4(2.0,2.0,2.0,1.0);
        }
    }
}
统一mat4世界矩阵;
均匀mat4矩阵;
均匀mat4视图投影矩阵;
均匀vec4眼位;
属性向量3 a;
属性向量3b;
属性向量3 n1;
属性向量3 n2;
属性浮动w;
void main()
{
浮动a_顶点=点(eyepos.xyz-a,n1);
浮动b_顶点=点(eyepos.xyz-a,n2);
如果(a_顶点*b_顶点>0.0)//符号不同,则边位于对象后面
{
gl_位置=vec4(2.0,2.0,2.0,1.0);
}
else//图形的轮廓
{
如果(w==0.0)
{
vec4p=vec4(a.x,a.y,a.z,1.0);
p=p*worldMatrix*viewProjMatrix;
gl_位置=p;
}
其他的
{
vec4p=vec4(b.x,b.y,b.z,1.0);
p=p*worldMatrix*viewProjMatrix;
gl_位置=p;
}
}
if(dot(n1,n2)fName;
而(!isFileOK(fName))
{
cout>fName;
}
超级网格*模型=新超级网格(fName.c_str());
//终端输入//
模型->加载();
模型->绘图();
字符串fname=Model->fname;
string FileName=fname.substr(0,fname.size()-10);//应该从字符串中删除最后10个字符,删除“.spec.mesh”。。。
FileName=FileName+“.bin”;/…然后我们将其设为.bin文件*/
coutm[w]>vdata;
向量&idata=Model->m[w]->idata;
//创建顶点和索引变量(边网格的贴图),执行两个循环以分析网格上的所有三角形,并将其顶点值写入文件//
顶点*V=(顶点*)(&vdata[0]);
无符号短*I16=(无符号短*)(&idata[0]);
无符号字符*I8=(无符号字符*)(&idata[0]);
无符号整数*I32=(无符号整数*)(&idata[0]);
地图EM;
对于(无符号i=0;im[w]->ic;i+=3)//3,因为我们看到的是三角形//
{
网格*foo=Model->m[w];
int i1;
int i2;
int i3;
if(Model->m[w]->ise==GL\u无符号字节)
{
i1=I8[i];
i2=I8[i+1];
i3=I8[i+2];
}
否则如果(型号->m[w]->ise==GL\U无符号\U短)
{
i1=I16[i];
i2=I16[i+1];
i3=I16[i+2];
}
其他的
{
i1=I32[i];
i2=I32[i+1];
i3=I32[i+2];
}
vec3 p=vec3(V[i1].x,V[i1].y,V[i1].z);//表示网格上每个三角形上每个顶点在三维空间中的点
vec3q=vec3(V[i2].x,V[i2].y,V[i2].z);
vec3r=vec3(V[i3].x,V[i3].y,V[i3].z);
vec3v1=p-q;
vec3v2=r-q;
vec3 n=cross(v2,v1);//重要的是要确保此处的顺序正确,请执行顶点二点顶点一//
设置tmp;
tmp.insert(i1);tmp.insert(i2);
EM[tmp]。推回(n);
设置tmp2;
tmp2.insert(i2);tmp2.insert(i3);
EM[tmp2]。推回(n);
设置tmp3;
tmp3.insert(i3);tmp3.insert(i1);
EM[tmp3]。推回(n);
//现在,我们已经将每个需要的点都推到了边缘图中
}
int-edgeNumber=0;
coutsecond[0];
vec3-norm2;
if(it->second.size()==1)
norm2=-1*norm1;
其他的
norm2=它->秒[1];
写出((字符*)和一,12);
写出((字符*)&Two,12);
out.write((字符*)和norm1,12);
out.write((字符*)和norm2,12);
浮点数r=0;
out.write((char*)&r,4);
写出((字符*)和一,12);
写出((字符*)&Two,12);
out.write((字符*)和norm1,12);
out.write((字符*)和norm2,12);
r=1;
out.write((char*)&r,4);
edgeNumber++;

矩阵和向量的乘法顺序不是可换的,所以
你的顶点着色器必须输出投影*模型*顶点,而不是相反。

我通过在代码的不同部分分配更多空间来写入顶点数据,从而解决了未绘制线的奥秘。至于我的其他问题,尽管顶点着色器中的乘法顺序实际上是正确的,但我搞乱了另一个问题向量数学的基本概念。当法线形成钝角时,两个面法线的点积将是负数……就像我的模型上的尖点一样。此外,上面的错误逻辑基本上是说,如果面可见,则在其上绘制所有线。我重新编写了着色器,以首先测试面是否为visible,然后用同样的c
uniform mat4 worldMatrix; /* the matrix that defines how to project a point from 
object space to world space.*/
uniform mat4 viewProjMatrix; // the view (pertaining to screen size) matrix times the projection (how to project points to 3D) matrix.
uniform vec4 eyepos; // the position of the eye, given by the program.

attribute vec3 a; // one vertex on an edge, having an x,y,z, and w coordinate.
attribute vec3 b; // the other edge vertex.
attribute vec3 n1; // the normal of the face the edge is on.
attribute vec3 n2; // another normal in the case that an edge shares two faces... otherwise, this is the same as n1.
attribute float w; // an attribute given to make a binary choice between two edges when they draw on top of one another.

void main()
{
    // WORLD SPACE ATTRIBUTES //
    vec4 eye_world = eyepos * worldMatrix;
    vec4 a_world = vec4(a.x, a.y,a.z,1.0) * worldMatrix;
    vec4 b_world = vec4(b.x, b.y,b.z,1.0) * worldMatrix;
    vec4 n1_world = normalize(vec4(n1.x, n1.y,n1.z,0.0) * worldMatrix);
    vec4 n2_world = normalize(vec4(n2.x, n2.y,n2.z,0.0) * worldMatrix);
    // END WORLD SPACE ATTRIBUTES //

    // TEST CASE ATTRIBUTES //
    float a_vertex = dot(eye_world - a_world, n1_world);
    float b_vertex = dot(eye_world - b_world, n2_world);
    float normalDot = dot(n1_world.xyz, n2_world.xyz);
    float vertProduct = a_vertex * b_vertex;
    float hardness = 0.0; // this would be the value for an object made of sharp angles, like a box. Take a look at its use below.
    // END TEST CASE ATTRIBUTES //

    gl_Position = vec4(2.0,2.0,2.0,1.0); // if all else fails, keeping this here will discard unwanted data.

    if (vertProduct >= 0.1) // NOTE: face is behind the viewable portion of the object, normally uses 0.0 when not checking for silhouette
    {
            gl_Position = vec4(2.0,2.0,2.0,1.0);
    }

    else if(vertProduct < 0.1 && vertProduct >= -0.1) // NOTE: face makes almost a right angle with the eye vector
    {
        if(w == 0.0)
        {
            vec4 p = vec4(a_world.x, a_world.y, a_world.z, 1.0);
            p = p  * viewProjMatrix;
            gl_Position = p;
        }
        else
        {
            vec4 p = vec4(b_world.x, b_world.y, b_world.z, 1.0);
            p = p * viewProjMatrix;
            gl_Position = p;
        }
    }

    else // NOTE: this is the case where you can very clearly see a face.
    { // NOTE: the number that normalDot compares to should be its "hardness" value. The more negative the value, the smoother the surface.
       // a.k.a. the less we care about hard edges (when the normals of the faces make an obtuse angle) on the object, the more negative
       // hardness becomes on a scale of 0.0 to -1.0.
        if(normalDot <= hardness) // NOTE: the dot product of the two normals is obtuse, so we are looking at a sharp edge.
        {
            if(w == 0.0)
            {
                vec4 p = vec4(a_world.x, a_world.y, a_world.z, 1.0);
                p = p * viewProjMatrix;
                gl_Position = p;
            }
            else
            {
                vec4 p = vec4(b_world.x, b_world.y, b_world.z, 1.0);
                p = p * viewProjMatrix;
                gl_Position = p;
            }
        }
        else // NOTE: not sharp enough, just throw the vertex away
        {
            gl_Position = vec4(2.0,2.0,2.0,1.0);
        }
    }
}