计算机图形学:虚拟服装设计

    xiaoxiao2021-03-25  152

    要求:

    1)读取给定的模型文件并能够分别使用线模式、点模式、填充模式进行渲染。

    2)对模型进行平移、缩放和旋转。

    3)改变视点,对模型进行三维漫游。

    4)为模型中的衣裙添加物理模型,要求能够拖动某个节点或面片展示局部形变效果。

    5)为模型中的衣裙添加碰撞检测,使得衣裙能在重力作用下悬挂在衣架上,以及模拟风力作用下的衣裙飘动效果。

    一、实验环境

    1. 操作系统:windows 8.1

    2. 编程软件:visual studio 2013

     

    二、实验内容

    l 关键代码分析

    (1)读取obj模型

    void ReadPIC()

     {

    int dianshu;

    dianshu = 0;

     

    ifstream ifs("dress.obj"); //用文件输入流读入文件

    string s;

    Mian *f;

    POINT3 *v;

    FaXiangLiang *vn;

    WenLi *vt;

    while (getline(ifs, s))  //从标准输入流中读取一个字符串,存储到字符串string(对象)中

    {

    if (s.length()<2)continue;

    if (s[0] == 'v')

    {

    if (s[1] == 't') //vt 纹理 0.001992 0.001992

    {

    istringstream in(s); //定义一个字符串输入流的对象in,将s中所包含的字符串放入in 对象中

        vt = new WenLi();

    string head;

    in >> head >> vt->TU >> vt->TV;

    m_pic.VT.push_back(*vt);

    }

    else if (s[1] == 'n') //vn 法向量 0.000000 -1.000000 0.000000

    {

    istringstream in(s);

    vn = new FaXiangLiang();

    string head;

    in >> head >> vn->NX >> vn->NY >> vn->NZ;

    m_pic.VN.push_back(*vn);

    }

    else //v 点 - 0.500000 - 0.500000 0.500000

    {

    istringstream in(s);

    v = new POINT3();

    string head;

    in >> head >> v->X >> v->Y >> v->Z;

    m_pic.V.push_back(*v);

    dianshu++;

    }

    //printf("dianshu=%d",dianshu);

    }

    else if (s[0] == 'f')//f 面 1/1/1 2/2/2 3/3/3  这个面的顶点、纹理坐标、法向量的索引  //f 2443//2656 2442//2656 2444//2656 面

    {

    for (int k = s.size() - 1; k >= 0; k--)

    {

    if (s[k] == '/')s[k] = ' ';

    }

    istringstream in(s);

    f = new Mian();

    string head;

    in >> head;

    int i = 0;

    while (i<3)

    {

    if (m_pic.V.size() != 0)

    {

    in >> f->V[i];

    f->V[i] -= 1;

    }

    if (m_pic.VT.size() != 0)

    {

    in >> f->T[i];

    f->T[i] -= 1;

    }

    if (m_pic.VN.size() != 0)

    {

    in >> f->N[i];

    f->N[i] -= 1;

    }

    i++;

    }

    m_pic.F.push_back(*f);

    }

    }

    }

    读取文件dress.obj,依据文件中的索引将数据分别存入法向量m_pic.VN纹理坐标m_pic.VT,顶点m_pic.V依据面的索引,法向量纹理坐标顶点按所在三角形面分别存入m_pic.F中,方便后面绘制以及变换操作。由于数据量大,读取文件函数ReadPIC()设置了标志位,只在文件启动时执行1次。

    (2)绘制模型

    void InitScene()

    {

    static GLint flag = 1;//设置标志 位,第一次读取obj文件到数组,后面直接显示

    if (flag == 1)

    {

    flag = 0;

    ReadPIC();

    }

     

    glClearColor(1.000f, 1.000f, 1.000f, 1.0f); //Background color

    // TODO: Replace the following sample code with your initialization code.

    // Activate lighting and a light source

    //用于启用各种功能。具体功能由参数决定。与glDisable相对应。glDisable用以关闭各项功能。

    glEnable(GL_LIGHT0);//启用0号灯到7号灯(光源)  光源要求由函数glLight函数来完成

    glEnable(GL_LIGHTING);//启用灯源

    glEnable(GL_DEPTH_TEST);//启用深度测试。  根据坐标的远近自动隐藏被遮住的图形(材料)

    glEnable(GL_TEXTURE_2D);   // 启用二维纹理

    // Define material parameters

    static GLfloat glfMatAmbient[] = { 0.000f, 0.450f, 1.000f, 1.0f };

    static GLfloat glfMatDiffuse[] = { 0.000f, 0.000f, 0.580f, 1.0f };

    static GLfloat glfMatSpecular[] = { 1.000f, 1.000f, 1.000f, 1.0f };

    static GLfloat glfMatEmission[] = { 0.000f, 0.000f, 0.000f, 1.0f };

    static GLfloat fShininess = 128.000f;

    // Set material parameters

    //指定用于光照计算的当前材质属性。参数face的取值可以是GL_FRONT、GL_BACK或GL_FRONT_AND_BACK,指出材质属性将应用于物体的哪面。

    //void glMaterial{if}(GLenum face, GLenum pname, TYPE param);

    glMaterialfv(GL_FRONT, GL_AMBIENT, glfMatAmbient);

    glMaterialfv(GL_FRONT, GL_DIFFUSE, glfMatDiffuse);

    glMaterialfv(GL_FRONT, GL_SPECULAR, glfMatSpecular);

    glMaterialfv(GL_FRONT, GL_EMISSION, glfMatEmission);

    glMaterialf(GL_FRONT, GL_SHININESS, fShininess);

    }

     

    void DrawScene()

     {

    // TODO: Replace the following sample code with your code to draw the scene.

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // 清除屏幕及深度缓存

    glLoadIdentity(); // 重置模型观察矩阵

     

    gluLookAt(viewer[0], viewer[1], viewer[2], 0.0f, -4.0f, -9.0f, 0.0, 1.0, 0.0);

     

    glTranslatef(0.0f, -13.0f, -8.0f); // 移入屏幕 5.0

     

    if (trackballMove&&translating&&!scaling&&!rotating)

    {

    glTranslatef(tran[0], tran[1], tran[2]);

    //printf("tran[0]=%f, tran[1]=%f, tran[2]=%f\n", tran[0], tran[1], tran[2]);

    }

    if (trackballMove&&!translating&&scaling&&!rotating)

    {

    glScalef(scale[0], scale[1], scale[2]);

    }

    if (trackballMove&&!translating&&!scaling&&rotating)

    {

    glRotatef(angle0, axis[0], axis[1], axis[2]);//旋转(角度,轴)

    }

    GLCube();// Draw a cube

    glFlush();

    }

     

    void GLCube()

    {

    if (dian_model&&!xian_model&&!mian_model)

    //if (0)

    {

    for (int i = 0; i < (m_pic.F.size()); i++)

    //for (int i = 0; i<7959; i++)

    {

    glBegin(GL_POINTS);//点模式

    if (qizhi0 == 1)

    {

    printf("dianmoshi");

    qizhi0 = 0;

    }

    /*glVertex3f(m_pic.V[m_pic.F[3 * i].V[0]].X / YU, m_pic.V[m_pic.F[3 * i].V[0]].Y / YU, m_pic.V[m_pic.F[3 * i].V[0]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[3 * i].V[1]].X / YU, m_pic.V[m_pic.F[3 * i].V[1]].Y / YU, m_pic.V[m_pic.F[3 * i].V[1]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[3 * i].V[2]].X / YU, m_pic.V[m_pic.F[3 * i].V[2]].Y / YU, m_pic.V[m_pic.F[3 * i].V[2]].Z / YU);

    */

     

    glVertex3f(m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[1]].X / YU, m_pic.V[m_pic.F[i].V[1]].Y / YU, m_pic.V[m_pic.F[i].V[1]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[2]].X / YU, m_pic.V[m_pic.F[i].V[2]].Y / YU, m_pic.V[m_pic.F[i].V[2]].Z / YU);

     

    //glVertex3f(10*(model.vertices[3 * i]), 10*(model.vertices[3 * i + 1]), 10*(model.vertices[3 * i + 2]));

    glEnd();

    }

    }

    if (!dian_model&&xian_model&&!mian_model)

    //if (0)

    {

    for (int i = 0; i<(m_pic.F.size()); i++)

    {

    glBegin(GL_LINES);//线模式

    if (qizhi1 == 1)

    {

    printf("xianmoshi");

    qizhi1 = 0;

    }

    glVertex3f(m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[1]].X / YU, m_pic.V[m_pic.F[i].V[1]].Y / YU, m_pic.V[m_pic.F[i].V[1]].Z / YU);

    //glVertex3f(m_pic.V[m_pic.F[i].V[2]].X / YU, m_pic.V[m_pic.F[i].V[2]].Y / YU, m_pic.V[m_pic.F[i].V[2]].Z / YU);

    glEnd();

    glBegin(GL_LINES);

    //glVertex3f(m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[1]].X / YU, m_pic.V[m_pic.F[i].V[1]].Y / YU, m_pic.V[m_pic.F[i].V[1]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[2]].X / YU, m_pic.V[m_pic.F[i].V[2]].Y / YU, m_pic.V[m_pic.F[i].V[2]].Z / YU);

    glEnd();

    glBegin(GL_LINES);

    glVertex3f(m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU);

    //glVertex3f(m_pic.V[m_pic.F[i].V[1]].X / YU, m_pic.V[m_pic.F[i].V[1]].Y / YU, m_pic.V[m_pic.F[i].V[1]].Z / YU);

    glVertex3f(m_pic.V[m_pic.F[i].V[2]].X / YU, m_pic.V[m_pic.F[i].V[2]].Y / YU, m_pic.V[m_pic.F[i].V[2]].Z / YU);

    glEnd();

    }

    }

    if (!dian_model&&!xian_model&&mian_model)

    //if (1)

    {

    for (int i = 0; i<(m_pic.F.size()); i++)

    {

    //printf("m_pic.F.size()=%d", m_pic.F.size());//16213

    glBegin(GL_TRIANGLES);//面模式// 绘制三角形

    if (qizhi2 == 1)

    {

    printf("mianmoshi");

    qizhi2 = 0;

    }

    if (m_pic.VT.size() != 0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[0]].TU, m_pic.VT[m_pic.F[i].T[0]].TV);  //纹理

    if (m_pic.VN.size() != 0)glNormal3f(m_pic.VN[m_pic.F[i].N[0]].NX, m_pic.VN[m_pic.F[i].N[0]].NY, m_pic.VN[m_pic.F[i].N[0]].NZ);//法向量

    glVertex3f(m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU); // 上顶点

    //printf("dian:%f,%f,%f\n",m_pic.V[m_pic.F[i].V[0]].X / YU, m_pic.V[m_pic.F[i].V[0]].Y / YU, m_pic.V[m_pic.F[i].V[0]].Z / YU);

    if (m_pic.VT.size() != 0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[1]].TU, m_pic.VT[m_pic.F[i].T[1]].TV);  //纹理

    if (m_pic.VN.size() != 0)glNormal3f(m_pic.VN[m_pic.F[i].N[1]].NX, m_pic.VN[m_pic.F[i].N[1]].NY, m_pic.VN[m_pic.F[i].N[1]].NZ);//法向量

    glVertex3f(m_pic.V[m_pic.F[i].V[1]].X / YU, m_pic.V[m_pic.F[i].V[1]].Y / YU, m_pic.V[m_pic.F[i].V[1]].Z / YU); // 左下

    if (m_pic.VT.size() != 0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[2]].TU, m_pic.VT[m_pic.F[i].T[2]].TV);  //纹理

    if (m_pic.VN.size() != 0)glNormal3f(m_pic.VN[m_pic.F[i].N[2]].NX, m_pic.VN[m_pic.F[i].N[2]].NY, m_pic.VN[m_pic.F[i].N[2]].NZ);//法向量

    glVertex3f(m_pic.V[m_pic.F[i].V[2]].X / YU, m_pic.V[m_pic.F[i].V[2]].Y / YU, m_pic.V[m_pic.F[i].V[2]].Z / YU); // 右下

    glEnd(); // 三角形绘制结束

    }

    }

    }

    InitScene()函数中设置了场景的光源和模型的材质。DrawScene()中绘制模型,调用函数GLCube()实现具体绘制,并由标志位设置绘制模式:点模式,线模式和面模式;同时使用库函数实现模型旋转缩放平移变换操作,具体参数由虚拟球设定;同时gluLookAt(viewer[0], viewer[1], viewer[2], 0.0f, -4.0f, -9.0f, 0.0, 1.0, 0.0);函数实现三维漫游,viewer[0], viewer[1], viewer[2]数值由键盘设置,后面的视点方向等用于使模型位于世界坐标系正中间。

    (3)物理模型

    Cloth::Cloth(GLMmodel *model)

    {

    //

    SpringConstant = 1000;//弹力

    DampingFactor = 10;//阻尼

    density = 1.2;//密度

    drag = 0.4;//阻力

     

    //set vert

    Myvertex vert;

    verts_.push_back(vert);

    for (int i = 1; i <= 7959; i++) // m_pic.V[m_pic.F[i].V[2]].X

    {

    //printf("%d\n", m_pic.V.size());//7959

    vert.id_ = i;

    vert.position_ = point(model->vertices[3 * i], model->vertices[3 * i + 1], model->vertices[3 * i + 2]);//point: vec

    //printf("[1]=%lf\n", model->vertices[3 * i]);

    //printf("[2]=%lf\n", model->vertices[3 * i+1]);

    //printf("[3]=%lf\n", model->vertices[3 * i+2]);

    //vert.texCoord_ = Vec2f(model->)

    verts_.push_back(vert);

    }

     

     

    //calculate hanger_aabb 衣架aabb包围盒

    for (int i = 3381; i <= model->numvertices; i++)

    {

    if (model->vertices[3 * i] > hanger_aabb.max_x)

    {

    hanger_aabb.max_x = model->vertices[3 * i];

    }

    if (model->vertices[3 * i] < hanger_aabb.min_x)

    {

    hanger_aabb.min_x = model->vertices[3 * i];

    }

    if (model->vertices[3 * i + 1] > hanger_aabb.max_y)

    {

    hanger_aabb.max_y = model->vertices[3 * i + 1];

    }

    if (model->vertices[3 * i + 1] < hanger_aabb.min_y)

    {

    hanger_aabb.min_y = model->vertices[3 * i + 1];

    }

    if (model->vertices[3 * i + 2] > hanger_aabb.max_z)

    {

    hanger_aabb.max_z = model->vertices[3 * i + 2];

    }

    if (model->vertices[3 * i + 2] < hanger_aabb.min_z)

    {

    hanger_aabb.min_z = model->vertices[3 * i + 2];

    }

    }

     

    update_aabb(); //calculate_cloth_aabb

     

    for (int i = 1; i <= model->numvertices; i++) //if points in hanger_aabb,point is static

    {

    if (p_in_aabb(verts_[i].position_))

    {

    verts_[i].is_fixed = true;

    }

    else

    verts_[i].is_fixed = false;

    }

     

    //set face

    Myface face;

    for (int i = 0; i < model->numtriangles; i++)

    {

    face.id_ = i;

    int nid = model->triangles[i].findex;

    face.verId = ivec3(model->triangles[i].vindices[0], model->triangles[i].vindices[1], model->triangles[i].vindices[2]);

    face.normal_ = Vec3f(model->facetnorms[nid * 3], model->facetnorms[nid * 3 + 1], model->facetnorms[nid * 3 + 2]);

    for (int j = 0; j < 3; j++)

    {

    int tid = model->triangles[i].tindices[j];

    face.texCoord_[j] = Vec2f(model->texcoords[tid * 2], model->texcoords[2 * tid + 1]);

    }

    int id[3];

    for (int j = 0; j < 3; j++)

    {

    id[j] = face.verId[j];

    face.vertex3[j] = &verts_[id[j]];

    }

    face.s = fabs(((verts_[id[1]].position_ - verts_[id[0]].position_)CROSS(verts_[id[2]].position_ - verts_[id[0]].position_)).length() / 2.0);

    faces_.push_back(face);

     

    }

     

    //delete some bad faces

    for (int i = 0; i < 6546; i++)

    {

    if ((faces_[i].normal_[0] * faces_[i].vertex3[0]->position_[0] + faces_[i].normal_[2] * faces_[i].vertex3[0]->position_[2]) < -0.05)

    {

    faces_[i].badface = true;

    }

    }

     

     

     

    //delete some bad verts,and find bound

    for (int i = 0; i < 6546; i++)

    {

    if (faces_[i].badface)

    {

    for (int j = 0; j < 3; j++)

    {

    faces_[i].vertex3[j]->kengdie = true;

    faces_[i].vertex3[j]->is_bound = true;

    }

     

    }

    }

    for (int i = 0; i < 6546; i++)

    {

    if (!faces_[i].badface)

    {

    for (int j = 0; j < 3; j++)

    {

    faces_[i].vertex3[j]->kengdie = false;

    }

    }

    }

     

     

     

    set_neighbor();

    set_weight();

    //Update(float deltatime);

     

    }

    }

    服装模型类,设置了服装的物理模型,为服装添加了SpringConstant弹力DampingFactor阻尼density密度drag 阻力属性;分别找到衣架和服装的顶点取值范围,确定衣架和服装的包围盒;形变是针对服装模型的三角形面片作变化,将模型的基本数据存储到face中;由于原模型中裙摆双层布料,碰撞检测的效果不好,故删去裙摆内衬,即badface。

     

     

    4)碰撞检测

    static void idle() {

    if (phy_){ if (loop < 16){ Update(); loop++; } else loop = 0; }

    }

     

    void keys(unsigned char key, int x, int y)

    {

    /* Use x, X, y, Y, z, and Z keys to move viewer */

    if (key == 'x') viewer[0] -= 1.0;

    if (key == 'X') viewer[0] += 1.0;

    if (key == 'y') viewer[1] -= 1.0;

    if (key == 'Y') viewer[1] += 1.0;

    if (key == 'z') viewer[2] -= 1.0;

    if (key == 'Z') viewer[2] += 1.0;

    //display();

    if (!phy_){

    DrawScene();

    }

     

    if (key == 'p'){

    phy_ = true; printf("phy_=true\n");

    }

     

    if (key == 'o'){

    wind.x += 0.5;

    wind.Print("New Wind:");

    }

    if (key == 'i'){

    wind.y += 0.5;

    wind.Print("New Wind:");

    }

    if (key == 'u'){

    wind.z += 0.5;

    wind.Print("New Wind:");

    }

    }

     

    void Cloth::Update(float deltatime)

    {

    //set gravity

    for (int i = 1; i < verts_.size(); i++)

    {

    verts_[i].applyForce(Vec3f(0, -0.1, 0)*verts_[i].weight);

    //verts_[i].applyForce(Vec3f(0, 0, 0.01));

    //verts_[i].Update(deltatime);

    }

     

     

    change_wind();

     

    //set wind

    for (int i = 0; i < faces_.size(); i++)

    {

    faces_[i].updateface();

    }

     

     

    //set  spring

    for (int i = 0; i < springDampers.size(); i++)

    {

    springDampers[i].CalculateForces();

    }

     

    collision_detection();//碰撞检测

     

    //update verts

    for (int i = 1; i < verts_.size(); i++)

    {

    verts_[i].Update(deltatime);

    }

     

    //update normals

    update_normal();

    }

     

    void Cloth::change_wind()

    {

    for (int i = 0; i < 6546; i++)

    {

    faces_[i].Changewind(wind);

    }

    }

     

    void Cloth::update_normal()

    {

    for (int i = 0; i < faces_.size(); i++)

    {

    Vec3f p = verts_[faces_[i].verId[0]].position_;

    Vec3f q = verts_[faces_[i].verId[1]].position_;

    Vec3f r = verts_[faces_[i].verId[2]].position_;

    Vec3f normal_update = ((p - r) CROSS(q - r));

    normal_update.normalize();

     

    //normal is  continuous variable

     

    if (normal_update DOT faces_[i].normal_>0)

    {

    faces_[i].normal_ = normal_update;

     

    }

    else

    {

    faces_[i].normal_ = -normal_update;

    }

    }

    }

     

    void Cloth::set_neighbor()

    {

    for (int i = 0; i < faces_.size(); i++)

    {

    if (!faces_[i].badface)

    {

    int vid1;

    int vid2;

    for (int j = 0; j < 3; j++)

    {

    vid1 = faces_[i].verId[j];

    vid2 = faces_[i].verId[(j + 1) % 3];

    verts_[vid1].neighborIdx.push_back(vid2);

    float dis;

    dis = (verts_[vid1].position_ - verts_[vid2].position_).length();

    verts_[vid1].nei_dis.push_back(dis);

    verts_[vid1].neighborfaceId.push_back(i);

    if (verts_[vid1].is_bound&&verts_[vid2].is_bound)

    {

    verts_[vid2].neighborIdx.push_back(vid1);

    verts_[vid2].nei_dis.push_back(dis);

    }

    }

     

    }

    }

     

    for (int i = 1; i < verts_.size(); i++)

    {

    verts_[i].degree_ = verts_[i].neighborIdx.size();

    }

     

    for (int i = 0; i < faces_.size(); i++)

    {

    if (!faces_[i].badface)

    {

    int vid1;

    int vid2;

    for (int j = 0; j < 3; j++)

    {

    vid1 = faces_[i].verId[j];

    vid2 = faces_[i].verId[(j + 1) % 3];

    springDampers.push_back(springDamper(&verts_[vid1], &verts_[vid2], SpringConstant, DampingFactor));//弹簧阻尼

     

    }

    }

    }

     

    }

     

    void Cloth::collision_detection()

    {

    update_aabb();

    for (int i = 0; i < 40; i++)

    for (int j = 0; j < 40; j++)

    for (int k = 0; k < 40; k++)

    {

    voxels[i][j][k].clear();

    }

     

     

    for (int i = 0; i < 6546; i++)

    {

    faces_[i].voxel_pos.clear();

    }

    for (int i = 0; i < 6546; i++)

    {

    if (!faces_[i].badface)

    {

    aabb ab_ = faces_[i].get_aabb();

    int l = floor((ab_.min_x - cloth_aabb.min_x) / (cloth_aabb.max_x - cloth_aabb.min_x)*40.f);

    int m = floor((ab_.min_y - cloth_aabb.min_y) / (cloth_aabb.max_y - cloth_aabb.min_y)*40.f);

    int n = floor((ab_.min_z - cloth_aabb.min_z) / (cloth_aabb.max_z - cloth_aabb.min_z)*40.f);

    if (l < 0)

    l = 0;

    if (m < 0)

    m = 0;

    if (n < 0)

    n = 0;

    voxels[l][m][n].push_back(i);

    faces_[i].voxel_pos = ivec3(l, m, n);

    }

    }

     

    for (int i = 0; i < 6546; i++)

    {

    ivec3 voxel = faces_[i].voxel_pos;

    for (int j = 0; j < voxels[voxel[0]][voxel[1]][voxel[2]].size(); j++)

    {

    int face_id = voxels[voxel[0]][voxel[1]][voxel[2]][j];

    bool b = tri_collision_detection(i, face_id);

    }

    }

    /*for (int i = 0; i < 6546; i++)

    for (int j = 0; j < 6546; j++)

    {

    tri_collision_detection(i, j);

    }*/

     

    }

     

    bool Cloth::tri_collision_detection(int id1, int id2)

    {

    if ((faces_[id1].normal_ DOT faces_[id2].normal_)>0)

    return false;

    if (faces_[id1].badface || faces_[id2].badface)

    return false;

    Vec3f dis(0, 0, 0);

    for (int i = 0; i < 3; i++)

    {

    dis += (faces_[id1].vertex3[i]->position_ - faces_[id2].vertex3[i]->position_) / 3.0f;

    }

    if (dis.length() > 0.001)

    return false;

     

    else

    {

    Vec3f n = Vec3f(0, 0, 0);

     

    for (int i = 0; i < 3; i++)

    {

    n = (faces_[id2].normal_ DOT(faces_[id1].vertex3[i]->position_ - faces_[id2].vertex3[1]->position_))*faces_[id2].normal_;

    if (n.length() < 0.01)

    {

    n.normalize();

    if (n DOT faces_[id1].vertex3[i]->velocity < 0)

    {

    Vec3f vv = Vec3f(0, 0, 0);

    vv = (n DOT faces_[id1].vertex3[i]->velocity)*-1.1f*n;

    faces_[id1].vertex3[i]->velocity += vv;

    /*for (int j = 0; j < 3; j++)

    {

    faces_[id2].vertex3[j]->velocity += vv / -1.1f  / 3.0f;

    }*/

    //faces_[id1].vertex3[i]->velocity = Vec3f(0, faces_[id1].vertex3[i]->velocity[1], 0);

     

    }

    }

    }

    return true;

    }

     

    }

     

    由键盘设置是否开启碰撞检测,按下’p’键即开启碰撞检测,风力大小也由键盘设置。碰撞检测具体实现流程见上述代码。

     

     

     

     

     

     

     

     

    转载请注明原文地址: https://ju.6miu.com/read-12687.html

    最新回复(0)