triangle_index mesh_basic::connectivity(int const index) const { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size_connectivity(),"Index ("+std::to_string(index)+") must be less than the current size of the connectivity ("+std::to_string(size_connectivity())+")"); return connectivity_data[index]; }
vec3& mesh_basic::vertex(int const index) { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size_vertex(),"Index ("+std::to_string(index)+") must be less than the current size of the vertices ("+std::to_string(size_vertex())+")"); return vertex_data[index]; }
vec3& mesh_basic::color(int const index) { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size_color(),"Index ("+std::to_string(index)+") must be less than the current size of the colors ("+std::to_string(size_color())+")"); return color_data[index]; }
vec2& mesh_basic::texture_coord(int const index) { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size_texture_coord(),"Index ("+std::to_string(index)+") must be less than the current size of the texture coordinates ("+std::to_string(size_texture_coord())+")"); return texture_coord_data[index]; }
skinning_weight& vertex_weight_parameter::operator[](int const index) { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size(),"Index ("+std::to_string(index)+") must be less than the number of weight per vertex ("+std::to_string(size())+")"); return weight_data[index]; }
vec3 mesh_basic::normal(int const index) const { ASSERT_CPE(index>=0,"Index ("+std::to_string(index)+") must be positive"); ASSERT_CPE(index<size_normal(),"Index ("+std::to_string(index)+") must be less than the current size of the normals ("+std::to_string(size_normal())+")"); return normal_data[index]; }
vec3 mesh_parametric::normal(int const ku,int const kv) const { ASSERT_CPE(ku >= 0 , "Value ku ("+std::to_string(ku)+") should be >=0 "); ASSERT_CPE(ku < size_u() , "Value ku ("+std::to_string(ku)+") should be < size_u ("+std::to_string(size_u())+")"); ASSERT_CPE(ku >= 0 , "Value kv ("+std::to_string(kv)+") should be >=0 "); ASSERT_CPE(ku < size_v() , "Value kv ("+std::to_string(kv)+") should be < size_v ("+std::to_string(size_v())+")"); int const offset = ku+size_u_data*kv; return mesh_basic::normal(offset); }
void mesh_parametric_cloth::integration_step(float const dt) { ASSERT_CPE(speed_data.size() == force_data.size(),"Incorrect size"); ASSERT_CPE(static_cast<int>(speed_data.size()) == size_vertex(),"Incorrect size"); int const Nu = size_u();//nombre de ressort int const Nv = size_v();//nombre de ressort //*************************************************************// // TO DO: Calculer l'integration numerique des positions au cours de l'intervalle de temps dt. //*************************************************************// //security check (throw exception if divergence is detected) static float const LIMIT=30.0f; for(int ku=0 ; ku<Nu; ++ku) { for(int kv=0; kv<Nv; ++kv) { vec3 & p = vertex(ku,kv); speed(ku,kv)=(1-mu*dt)*speed(ku,kv)+ dt*force(ku,kv);//gg c'est beau p = p + dt*speed(ku,kv); // collision avec le sol if (p.z() < -1.101f)// hauteur du sol { p.z()= -1.100f; force(ku,kv).z() = 0.0f; speed(ku,kv).z() = 0.0f; } // collision avec la sphere vec3 centre_sphere = {0.5f,0.05f,-1.1f}; vec3 normale= p-centre_sphere; float rayon =0.4f; if (norm(normale)<rayon) { p= centre_sphere + normale/norm(normale) * rayon; //on annule la composante normale de la force et de la vitesse speed(ku,kv) -= dot (speed(ku,kv),normale/norm(normale)) * normale; force(ku,kv) -= dot (force(ku,kv),normale/norm(normale)) * normale; //on annule la composante normale de la force et de la vitesse } } } }
vec3& mesh_parametric_cloth::force(int const ku,int const kv) { ASSERT_CPE(ku >= 0 , "Value ku ("+std::to_string(ku)+") should be >=0 "); ASSERT_CPE(ku < size_u() , "Value ku ("+std::to_string(ku)+") should be < size_u ("+std::to_string(size_u())+")"); ASSERT_CPE(kv >= 0 , "Value kv ("+std::to_string(kv)+") should be >=0 "); ASSERT_CPE(kv < size_v() , "Value kv ("+std::to_string(kv)+") should be < size_v ("+std::to_string(size_v())+")"); int const offset = ku + size_u()*kv; ASSERT_CPE(offset < static_cast<int>(force_data.size()),"Internal error"); return force_data[offset]; }
void line_opengl::init() { shader_id_data = read_shader("shaders/shader_line.vert","shaders/shader_line.frag"); vec3 line[]={ {0.0f,0.0f,0.0f} , {1.0f,0.0f,0.0f} }; glGenBuffers(1,&vbo_data); PRINT_OPENGL_ERROR(); ASSERT_CPE(vbo_data!=0,"Problem creating VBO"); glBindBuffer(GL_ARRAY_BUFFER,vbo_data); PRINT_OPENGL_ERROR(); glBufferData(GL_ARRAY_BUFFER,6*sizeof(float),&line[0],GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); ASSERT_CPE(glIsBuffer(vbo_data),"Problem creating VBO"); }
void mesh_opengl::update_vbo_texture(mesh_basic const& m) { //VBO vertex glBindBuffer(GL_ARRAY_BUFFER,vbo_texture); PRINT_OPENGL_ERROR(); ASSERT_CPE(glIsBuffer(vbo_texture),"vbo_buffer incorrect"); glBufferSubData(GL_ARRAY_BUFFER,0,3*sizeof(float)*m.size_texture_coord(),m.pointer_texture_coord()); PRINT_OPENGL_ERROR(); }
void mesh_basic::fill_empty_field_by_default() { int const N_vertex=size_vertex(); if(size_normal()!=N_vertex) fill_normal(); ASSERT_CPE(size_normal()==N_vertex,"Invalid normal computation"); if(size_color()!=N_vertex) fill_color({0.8f,0.8f,0.8f}); ASSERT_CPE(size_color()==N_vertex,"Invalid color set up"); if(size_texture_coord()!=N_vertex) { texture_coord_data.clear(); for(int k=0;k<N_vertex;++k) add_texture_coord({0.0f,0.0f}); } }
void mesh_basic::fill_normal() { int const N_vertex=size_vertex(); if(size_normal()!=N_vertex) normal_data.resize(N_vertex); //init normal data to 0 for(auto& n : normal_data) n=vec3(); //walk through all the triangles and add each triangle normal to the vertices int const N_triangle=size_connectivity(); for(int k_triangle=0;k_triangle<N_triangle;++k_triangle) { //get current triangle index triangle_index const& tri=connectivity(k_triangle); //check that the index given have correct values ASSERT_CPE(tri.u0()>=0 && tri.u0()<N_vertex,"Incorrect triangle index"); ASSERT_CPE(tri.u1()>=0 && tri.u1()<N_vertex,"Incorrect triangle index"); ASSERT_CPE(tri.u2()>=0 && tri.u2()<N_vertex,"Incorrect triangle index"); //compute current normal vec3 const& p0=vertex(tri.u0()); vec3 const& p1=vertex(tri.u1()); vec3 const& p2=vertex(tri.u2()); vec3 const u1=normalized(p1-p0); vec3 const u2=normalized(p2-p0); vec3 const n=normalized(cross(u1,u2)); //add the computed normal to the normal_data for(int kv=0;kv<3;++kv) normal_data[tri[kv]] += n; } //normalize all normal value for(auto& n : normal_data) n=normalized(n); }
void line_opengl::draw(vec3 const& p0,vec3 const& p1) { glBindBuffer(GL_ARRAY_BUFFER,vbo_data); ASSERT_CPE(glIsBuffer(vbo_data),"vbo incorrect"); vec3 line[]={p0,p1}; glBufferData(GL_ARRAY_BUFFER,6*sizeof(float),&line[0],GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); glVertexPointer(3, GL_FLOAT, 0, 0); PRINT_OPENGL_ERROR(); glDrawArrays(GL_LINES,0,2); }
void mesh_parametric::set_plane_xy_unit(int const size_u_param,int const size_v_param) { ASSERT_CPE(size_u_param>0 && size_v_param>0 , "Problem of mesh size"); size_u_data = size_u_param; size_v_data = size_v_param; //set data for(int kv=0 ; kv<size_v_param ; ++kv) { float const v = static_cast<float>(kv)/(size_v_param-1); for(int ku=0 ; ku<size_u_param ; ++ku) { float const u = static_cast<float>(ku)/(size_u_param-1); add_vertex( {u,v,0.0f} ); add_texture_coord( {u,v} ); add_normal( {0.0f,0.0f,1.0f} ); } } //set connectivity for(int kv=0 ; kv<size_v_param-1 ; ++kv) { for(int ku=0 ; ku<size_u_param-1 ; ++ku) { int const offset = ku+size_u_param*kv; triangle_index tri0 = {offset,offset+1,offset+size_u_param+1}; triangle_index tri1 = {offset,offset+size_u_param+1,offset+size_u_param}; add_triangle_index(tri0); add_triangle_index(tri1); } } fill_empty_field_by_default(); ASSERT_CPE(valid_mesh(),"Mesh is not valid"); }
ivec2::ivec2(std::initializer_list<int> const& arg) :x_data(0),y_data(0) { ASSERT_CPE(arg.size()>=2,"initializer list should have at least 2 arguments"); int counter=0; for(int v : arg) { if(counter==0) x_data=v; else if(counter==1) y_data=v; counter++; } }
void mesh_parametric_cloth::update_force() { int const Nu = size_u(); int const Nv = size_v(); int const N_total = Nu*Nv; ASSERT_CPE(static_cast<int>(force_data.size()) == Nu*Nv , "Error of size"); //wind direction vec3 uw=vec3( x_wind,y_wind,z_wind); uw= normalized(uw); //Gravity and wind static vec3 const g (0.0f,0.0f,-9.81f); vec3 const g_normalized = g/N_total; for(int ku=0 ; ku<Nu ; ++ku) { for(int kv=0 ; kv<Nv ; ++kv) { force(ku,kv) = g_normalized; vec3 n=this->normal(ku,kv); force(ku,kv) += Kw*dot(n,uw)*n; } } //*************************************************************// // TO DO, Calculer les forces s'appliquant sur chaque sommet //*************************************************************// //*************************************************************// float L01= 1.0f/(Nu-1); float L02= sqrt(2)/(Nu-1); float L03= 2.0f/(Nu-1); for(int ku=0 ; ku<Nu; ++ku) { for(int kv=0 ; kv<Nv; ++kv) { vec3 const& p = vertex(ku,kv); std::vector<vec3> pvd; std::vector<vec3> pvdiag; std::vector<vec3> pvb; /** cas general **/ //voisin directs if( kv < Nv-1) { pvd.push_back(vertex(ku,kv+1)); } if( kv > 0) { pvd.push_back(vertex(ku,kv-1)); } if( ku < Nu-1) { pvd.push_back(vertex(ku+1,kv)); } if( ku > 0) { pvd.push_back(vertex(ku-1,kv)); } //voisin diagonale if( ku< Nu -1 && kv < Nv-1 ) { pvdiag.push_back(vertex(ku+1,kv+1)); } if( ku < Nu-1 && kv >0 ) { pvdiag.push_back(vertex(ku+1,kv-1)); } if( ku > 0 && kv > 0 ) { pvdiag.push_back(vertex(ku-1,kv-1)); } if( ku>0 && kv< Nu -1) { pvdiag.push_back(vertex(ku-1,kv+1)); } //voisin bend if( ku < Nu -2) { pvb.push_back(vertex(ku+2,kv)); } if( ku >1 ) { pvb.push_back(vertex(ku-2,kv)); } if( kv < Nv -2) { pvb.push_back(vertex(ku,kv+2)); } if( kv >1 ) { pvb.push_back(vertex(ku,kv-2)); } for (int i=0; i<int(pvd.size());i++) { vec3 u=p-pvd[i]; force(ku,kv) += (Kdirect *(L01 - norm(u)) *u) /norm(u); } for (int i=0; i<int (pvdiag.size());i++) { vec3 u=p-pvdiag[i]; force(ku,kv) +=( Kdiag *(L02 - norm(u))*u) /norm(u); } for (int i=0; i<int (pvb.size());i++) { vec3 u=p-pvb[i]; force(ku,kv) +=( Kdouble *(L03 - norm(u))*u) /norm(u); } // on bloque les angles if ((ku == 0 && kv == 0 ) || (ku == 0 && kv == Nv -1)) { //if ((ku == Nu-1 && kv == Nv-1 )||(ku == Nu-1 && kv == 0 )||(ku == 0 && kv == 0 ) || (ku == 0 && kv == Nv -1)) { force(ku,kv) = vec3(0.0f,0.0f, 0.0f); } } } }
float const* mesh_basic::pointer_texture_coord() const { ASSERT_CPE(size_texture_coord()>0,"No texture coord"); return texture_coord_data[0].pointer(); }
void mesh_opengl::fill_vbo(mesh_basic const& m) { if(m.valid_mesh()!=true) throw cpe::exception_cpe("Mesh is considered as invalid, cannot fill vbo",EXCEPTION_PARAMETERS_CPE); number_of_triangles=m.size_connectivity(); if(number_of_triangles<=0) throw cpe::exception_cpe("incorrect number of triangles",MACRO_EXCEPTION_PARAMETER); //create the new vbo if(vbo_vertex==0) {glGenBuffers(1,&vbo_vertex);PRINT_OPENGL_ERROR();} ASSERT_CPE(vbo_vertex!=0,"Problem creation of VBO"); if(vbo_normal==0) {glGenBuffers(1,&vbo_normal);PRINT_OPENGL_ERROR();} ASSERT_CPE(vbo_normal!=0,"Problem creation of VBO"); if(vbo_color==0) {glGenBuffers(1,&vbo_color);PRINT_OPENGL_ERROR();} ASSERT_CPE(vbo_color!=0,"Problem creation of VBO"); if(vbo_texture==0) {glGenBuffers(1,&vbo_texture);PRINT_OPENGL_ERROR();} ASSERT_CPE(vbo_texture!=0,"Problem creation of VBO"); if(vbo_index==0) {glGenBuffers(1,&vbo_index);PRINT_OPENGL_ERROR();} ASSERT_CPE(vbo_index!=0,"Problem creation of VBO"); //VBO vertex glBindBuffer(GL_ARRAY_BUFFER,vbo_vertex); PRINT_OPENGL_ERROR(); if(!glIsBuffer(vbo_vertex)) throw cpe::exception_cpe("vbo_buffer incorrect",EXCEPTION_PARAMETERS_CPE); glBufferData(GL_ARRAY_BUFFER,3*sizeof(float)*m.size_vertex(),m.pointer_vertex(),GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); //VBO normal glBindBuffer(GL_ARRAY_BUFFER,vbo_normal); PRINT_OPENGL_ERROR(); if(!glIsBuffer(vbo_normal)) throw cpe::exception_cpe("vbo_normal incorrect",EXCEPTION_PARAMETERS_CPE); glBufferData(GL_ARRAY_BUFFER,3*sizeof(float)*m.size_normal(),m.pointer_normal(),GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); //VBO color glBindBuffer(GL_ARRAY_BUFFER,vbo_color); PRINT_OPENGL_ERROR(); if(!glIsBuffer(vbo_color)) throw cpe::exception_cpe("vbo_color incorrect",EXCEPTION_PARAMETERS_CPE); glBufferData(GL_ARRAY_BUFFER,3*sizeof(float)*m.size_color(),m.pointer_color(),GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); //VBO texture glBindBuffer(GL_ARRAY_BUFFER,vbo_texture); PRINT_OPENGL_ERROR(); if(!glIsBuffer(vbo_texture)) throw cpe::exception_cpe("vbo_texture incorrect",EXCEPTION_PARAMETERS_CPE); glBufferData(GL_ARRAY_BUFFER,2*sizeof(float)*m.size_texture_coord(),m.pointer_texture_coord(),GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); //VBO index glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo_index); PRINT_OPENGL_ERROR(); if(!glIsBuffer(vbo_index)) throw cpe::exception_cpe("vbo_index incorrect",EXCEPTION_PARAMETERS_CPE); glBufferData(GL_ELEMENT_ARRAY_BUFFER,3*sizeof(int)*m.size_connectivity(),m.pointer_triangle_index(),GL_DYNAMIC_DRAW); PRINT_OPENGL_ERROR(); }
float const* mesh_basic::pointer_vertex() const { ASSERT_CPE(size_vertex()>0,"No vertex"); return vertex_data[0].pointer(); }
float const* mesh_basic::pointer_normal() const { ASSERT_CPE(size_normal()>0,"No normal"); return normal_data[0].pointer(); }
float const* mesh_basic::pointer_color() const { ASSERT_CPE(size_color()>0,"No color"); return color_data[0].pointer(); }
int const* mesh_basic::pointer_triangle_index() const { ASSERT_CPE(size_connectivity()>0,"No connectivity"); return connectivity_data[0].pointer(); }