void test_getEntArrAdj_up() { iMesh_Instance mesh = create_mesh(); int err; // get hexes adjacent to a row of faces in the z=0 plane iBase_EntityHandle *adj = 0; int *off = 0; int adj_alloc = 0, off_alloc = 0; int adj_size = -1, off_size = -1; iMesh_getEntArrAdj( mesh, FACES[4][0], INTERVALS, iBase_REGION, &adj, &adj_alloc, &adj_size, &off, &off_alloc, &off_size, &err ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK( 0 != adj ); CHECK( 0 != off ); CHECK_EQUAL( INTERVALS, adj_size ); // one hex adjacent to each skin face CHECK_EQUAL( INTERVALS+1, off_size ); // one more than number of input handles CHECK( adj_alloc >= adj_size ); CHECK( off_alloc >= off_size ); for (int i = 0; i < INTERVALS; ++i) { CHECK_EQUAL( 1, off[i+1] - off[i] ); CHECK_EQUAL( HEXES[0][i][0], adj[off[i]] ); } free(adj); free(off); }
int init( ) { // etape 1 : decrire le triangle, les coordonnees des 3 sommets. // creer un mesh pour stocker les coordonnees des sommets du triangle triangle= create_mesh(GL_TRIANGLES); // choisir une couleur pour les sommets, rouge + vert = jaune vertex_color(triangle, make_color(1, 1, 0)); // donner les positions des 3 sommets, entre -1 1 sur x, y, z push_vertex(triangle, -0.5, -0.5, 0); push_vertex(triangle, 0.5, 0.5, 0); push_vertex(triangle, -0.5, 0.5, 0); return 0; // ras, pas d'erreur // on peut aussi donner des couleurs differentes aux sommets du triangle : /* vertex_color(triangle, make_color(1, 0, 0)); push_vertex(triangle, -0.5, -0.5, 0); vertex_color(triangle, make_color(0, 1, 0)); push_vertex(triangle, 0.5, 0.5, 0); vertex_color(triangle, make_color(0, 0, 1)); push_vertex(triangle, -0.5, 0.5, 0); return 0; // ras, pas d'erreur */ }
int init() { ASSERT(initSDL()); ASSERT(initGL() == 1); ASSERT(create_mesh(mesh, N, M, SCREEN_WIDTH, SCREEN_HEIGHT)); ASSERT(init_simulation()); resize_window(SCREEN_WIDTH, SCREEN_HEIGHT); #ifdef OPENMP omp_set_num_treads(MAX_THREADS); #endif ASSERT(init_simulation()); int size = (N+2)*(M+2); velocity_vectors = new Vector[size]; velocity_indices = new GLuint [size*2]; for(int i = 0; i < size*2; i++){ velocity_indices[i] = i; } for(int i = 0; i < size; i++){ velocity_vectors[i].p0.x = mesh.vertices[i].x; velocity_vectors[i].p0.y = mesh.vertices[i].y; velocity_vectors[i].p1.x = mesh.vertices[i].x; velocity_vectors[i].p1.y = mesh.vertices[i].y; } return (TRUE); }
int send_create_mesh(int i) { send_event(EVENT_CREATE_MESH); send_index(i); return create_mesh(i); }
int main(int argc, char* argv[]) { Mesh* mesh = create_mesh(); mesh_write("quad.mesh", mesh); mesh_destroy(mesh); Application app("my x11/win32 window", 600, 600, true); return app.run(); }
void test_getEntArrAdj_invalid_size() { iMesh_Instance mesh = create_mesh(); int err = -1; const int SPECIAL1 = 0xDeadBeef; const int SPECIAL2 = 0xCafe5; const int SPECIAL3 = 0xbabb1e; // test a downward query volatile int marker1 = SPECIAL1; iBase_EntityHandle adj1[8*INTERVALS-1]; // one too small volatile int marker2 = SPECIAL2; int off1[INTERVALS+1]; int adj1_alloc = sizeof(adj1)/sizeof(adj1[0]); int off1_alloc = sizeof(off1)/sizeof(off1[0]); int adj_size, off_size; iBase_EntityHandle* adj_ptr = adj1; int* off_ptr = off1; iMesh_getEntArrAdj( mesh, HEXES[0][0], INTERVALS, iBase_VERTEX, &adj_ptr, &adj1_alloc, &adj_size, &off_ptr, &off1_alloc, &off_size, &err ); CHECK_EQUAL( &adj1[0], adj_ptr ); CHECK_EQUAL( &off1[0], off_ptr ); // first ensure no stack corruption from writing off end of array CHECK_EQUAL( SPECIAL1, marker1 ); CHECK_EQUAL( SPECIAL2, marker2 ); // now verify that it correctly failed CHECK_EQUAL( iBase_BAD_ARRAY_SIZE, err ); // now test an upwards query volatile int marker3 = SPECIAL3; int off2[INTERVALS]; volatile int marker4 = SPECIAL1; int off2_alloc = sizeof(off2)/sizeof(off2[0]); err = iBase_SUCCESS; adj_ptr = adj1; off_ptr = off2; iMesh_getEntArrAdj( mesh, VERTS[0][0], INTERVALS+1, iBase_REGION, &adj_ptr, &adj1_alloc, &adj_size, &off_ptr, &off2_alloc, &off_size, &err ); // first ensure no stack corruption from writing off end of array CHECK_EQUAL( &adj1[0], adj_ptr ); CHECK_EQUAL( &off2[0], off_ptr ); CHECK_EQUAL( SPECIAL3, marker3 ); CHECK_EQUAL( SPECIAL1, marker4 ); // now verify that it correctly failed CHECK_EQUAL( iBase_BAD_ARRAY_SIZE, err ); }
static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Object& b_ob, BL::Mesh& b_mesh, const vector<Shader*>& used_shaders, float dicing_rate, int max_subdivisions) { BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length()-1]); bool subdivide_uvs = subsurf_mod.use_subsurf_uv(); create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs); /* export creases */ size_t num_creases = 0; BL::Mesh::edges_iterator e; for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { if(e->crease() != 0.0f) { num_creases++; } } mesh->subd_creases.resize(num_creases); Mesh::SubdEdgeCrease* crease = mesh->subd_creases.data(); for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { if(e->crease() != 0.0f) { crease->v[0] = e->vertices()[0]; crease->v[1] = e->vertices()[1]; crease->crease = e->crease(); crease++; } } /* set subd params */ if(!mesh->subd_params) { mesh->subd_params = new SubdParams(mesh); } SubdParams& sdparams = *mesh->subd_params; PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); sdparams.max_level = max_subdivisions; scene->camera->update(); sdparams.camera = scene->camera; sdparams.objecttoworld = get_transform(b_ob.matrix_world()); }
geometry_ptr create_geometry(const attributes& attr, const std::string& name, const parameter_list& params) { if (name == PLANE) { return geometry_ptr(new plane(attr.object_to_world, attr.material)); } else if (name == RECTANGLE) { return geometry_ptr(new rectangle(attr.object_to_world, attr.material)); } else if (name == SPHERE) { return geometry_ptr(new sphere(attr.object_to_world, attr.material)); } else if (name == MESH) { return create_mesh(attr, params); } else { throw std::invalid_argument("invalid geometry: " + name); } }
int init( ) { // etape 1 : decrire le triangle, les coordonnees des 3 sommets. // creer un mesh pour stocker les coordonnees des sommets du triangle triangle= create_mesh(GL_TRIANGLES); vertex_color(triangle, make_color(1, 0, 0)); push_vertex(triangle, -0.5, -0.5, 0); vertex_color(triangle, make_color(0, 1, 0)); push_vertex(triangle, 0.5, 0.5, 0); vertex_color(triangle, make_color(0, 0, 1)); push_vertex(triangle, -0.5, 0.5, 0); return 0; // ras, pas d'erreur }
int init( ) { // etape 1 : decrire le triangle, les coordonnees des 3 sommets. // creer un mesh pour stocker les coordonnees des sommets du triangle triangle= create_mesh(GL_TRIANGLES); vertex_color(triangle, make_color(1, 0, 0)); push_vertex(triangle, -0.5, -0.5, 0); vertex_color(triangle, make_color(0, 1, 0)); push_vertex(triangle, 0.5, 0.5, 0); vertex_color(triangle, make_color(0, 0, 1)); push_vertex(triangle, -0.5, 0.5, 0); // etape 2 : creer une camera par defaut, elle est placee en 0, 0, 5 et regarde les objets situes en 0, 0, 0 camera= make_orbiter(); return 0; // ras, pas d'erreur }
void test_getEntArrAdj_none() { iMesh_Instance mesh = create_mesh(); int err = -1; iBase_EntityHandle* adj = 0; int* off = 0; int adj_alloc = 0, off_alloc = 0; int adj_size = -1, off_size = -1; iMesh_getEntArrAdj( mesh, NULL, 0, iBase_REGION, &adj, &adj_alloc, &adj_size, &off, &off_alloc, &off_size, &err ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK_EQUAL( 0, adj_alloc ); CHECK_EQUAL( 0, adj_size ); CHECK_EQUAL( 1, off_size ); CHECK( off_alloc >= 1 ); CHECK_EQUAL( 0, off[0] ); free(off); }
int main( int argc, char* argv[] ) { REGISTER_TEST( test_getEntArrAdj_conn ); REGISTER_TEST( test_getEntArrAdj_vertex ); REGISTER_TEST( test_getEntArrAdj_up ); REGISTER_TEST( test_getEntArrAdj_down ); REGISTER_TEST( test_getEntArrAdj_invalid_size ); REGISTER_TEST( test_getEntArrAdj_none ); REGISTER_TEST( test_existinterface ); #ifdef MOAB_HAVE_HDF5 REGISTER_TEST( test_tags_retrieval ); #endif int result = RUN_TESTS( argc, argv ); // Delete the static iMesh instance defined in create_mesh() iMesh_Instance mesh = create_mesh(); int err; iMesh_dtor(mesh, &err); CHECK_EQUAL(iBase_SUCCESS, err); return result; }
void test_getEntArrAdj_vertex() { iMesh_Instance mesh = create_mesh(); int err; // get hexes adjacent to row of vertices at x=0,y=0; iBase_EntityHandle *adj = 0; int *off = 0; int adj_alloc = 0, off_alloc = 0; int adj_size = -1, off_size = -1; iMesh_getEntArrAdj( mesh, VERTS[0][0], INTERVALS+1, iBase_REGION, &adj, &adj_alloc, &adj_size, &off, &off_alloc, &off_size, &err ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK( 0 != adj ); CHECK( 0 != off ); CHECK_EQUAL( 2*INTERVALS, adj_size ); // INTERVALS+1 verts, end ones with one hex, others with two CHECK_EQUAL( INTERVALS+2, off_size ); // one more than number of input handles CHECK( adj_alloc >= adj_size ); CHECK( off_alloc >= off_size ); // first and last vertices should have one adjacent hex CHECK_EQUAL( 1, off[1] - off[0] ); CHECK_EQUAL( HEXES[0][0][0], adj[off[0]] ); CHECK_EQUAL( 1, off[INTERVALS+1] - off[INTERVALS] ); CHECK_EQUAL( HEXES[0][0][INTERVALS-1], adj[off[INTERVALS]] ); // middle ones should have two adjacent hexes for (int i = 1; i < INTERVALS; ++i) { CHECK_EQUAL( 2, off[i+1] - off[i] ); CHECK_EQUAL( HEXES[0][0][i-1], adj[off[i] ] ); CHECK_EQUAL( HEXES[0][0][i ], adj[off[i]+1] ); } free(adj); free(off); }
static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Object& b_ob, BL::Mesh& b_mesh, PointerRNA *cmesh, const vector<Shader*>& used_shaders, float dicing_rate, int max_subdivisions) { Mesh basemesh; create_mesh(scene, &basemesh, b_mesh, used_shaders); SubdParams sdparams(mesh, 0, true, false); sdparams.dicing_rate = max(0.1f, RNA_float_get(cmesh, "dicing_rate") * dicing_rate); sdparams.max_level = max_subdivisions; scene->camera->update(); sdparams.camera = scene->camera; sdparams.objecttoworld = get_transform(b_ob.matrix_world()); /* tesselate */ DiagSplit dsplit(sdparams); basemesh.tessellate(&dsplit); }
static Mesh* process_mesh(struct aiMesh* mesh, struct aiScene* scene) { Vertex **vertices = malloc(sizeof(Vertex *) * mesh->mNumVertices); for (int i = 0; i < mesh->mNumVertices; i++) { vertices[i] = malloc(sizeof(Vertex)); } // Process vertices if (mesh->mVertices && mesh->mNumVertices > 0) { for (int i = 0; i < mesh->mNumVertices; i++) { struct aiVector3D position = mesh->mVertices[i]; vertices[i]->position = create_vec(position.x, position.y, position.z, 1.0); } } else { gl_log(INFO, "A mesh was processed with no vertices."); } // Process normals if (mesh->mNormals) { for (int i = 0; i < mesh->mNumVertices; i++) { struct aiVector3D normal = mesh->mNormals[i]; vertices[i]->normal = create_vec(normal.x, normal.y, normal.z, 1.0); } } else { gl_log(INFO, "A mesh was processed with no normals."); } // Process texture coords if (mesh->mTextureCoords[0]) { for (int i = 0; i < mesh->mNumVertices; i++) { struct aiVector3D texture = mesh->mTextureCoords[0][i]; vertices[i]->texture_coords = create_vec(texture.x, texture.y, texture.z, 1.0); } } else { for (int i = 0; i < mesh->mNumVertices; i++) { vertices[i]->texture_coords = 0; } gl_log(INFO, "A mesh was processed with no texture coordinates."); } // Process material Texture* mesh_texture = malloc(sizeof(Texture)); Material* mesh_material = malloc(sizeof(Material)); if (mesh->mMaterialIndex >= 0) { struct aiString path; struct aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; aiGetMaterialTexture(material, aiTextureType_DIFFUSE, 0, &path, 0, 0, 0, 0, 0, 0); mesh_texture->id = create_texture(path.data); struct aiColor4D color; aiGetMaterialColor(material, AI_MATKEY_COLOR_DIFFUSE, &color); mesh_material->diffuse_color = create_vec(color.r, color.g, color.b, color.a); aiGetMaterialColor(material, AI_MATKEY_COLOR_AMBIENT, &color); mesh_material->ambient_color = create_vec(color.r, color.g, color.b, color.a); aiGetMaterialColor(material, AI_MATKEY_COLOR_SPECULAR, &color); mesh_material->specular_color = create_vec(color.r, color.g, color.b, color.a); } else { gl_log(INFO, "A mesh was processed with no material."); } return create_mesh(vertices, mesh->mNumVertices, mesh_texture, mesh_material); }
int main(void) { GLuint pid; ALLEGRO_DISPLAY *d; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_EVENT event; int frames = 0; double start; if (!al_init()) { abort_example("Could not init Allegro.\n"); return 1; } al_set_new_display_flags(ALLEGRO_OPENGL); al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST); d = al_create_display(WINDOW_W, WINDOW_H); if (!d) { abort_example("Unable to open a OpenGL display.\n"); return -1; } if (al_get_display_option(ALLEGRO_SAMPLE_BUFFERS)) { printf("With multisampling, level %i\n", al_get_display_option(ALLEGRO_SAMPLES)); } else { printf("Without multisampling.\n"); } al_install_keyboard(); queue = al_create_event_queue(); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_display_event_source(d)); if (al_get_opengl_extension_list()->ALLEGRO_GL_ARB_multisample) { glEnable(GL_MULTISAMPLE_ARB); } if (!al_get_opengl_extension_list()->ALLEGRO_GL_ARB_vertex_program) { abort_example("This example requires a video card that supports " " the ARB_vertex_program extension.\n"); return -1; } glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); /* Setup projection and modelview matrices */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, WINDOW_W/(float)WINDOW_H, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Position the camera to look at our mesh from a distance */ gluLookAt(0.0f, 20.0f, -45.0f, 0.0f, 0.0f, 0.0f, 0, 1, 0); create_mesh(); /* Define the vertex program */ glEnable(GL_VERTEX_PROGRAM_ARB); glGenProgramsARB(1, &pid); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, pid); glGetError(); if (al_get_opengl_extension_list()->ALLEGRO_GL_NV_vertex_program2_option) { glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program_nv), program_nv); } else { glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program), program); } /* Check for errors */ if (glGetError()) { const char *pgm = al_get_opengl_extension_list()->ALLEGRO_GL_NV_vertex_program2_option ? program_nv : program; GLint error_pos; const GLubyte *error_str = glGetString(GL_PROGRAM_ERROR_STRING_ARB); glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); abort_example("Error compiling the vertex program:\n%s\n\nat " "character: %i\n%s\n", error_str, (int)error_pos, pgm + error_pos); return -1; } start = al_current_time(); while (1) { if (!al_event_queue_is_empty(queue)) { while (al_get_next_event(queue, &event)) { switch (event.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: goto done; case ALLEGRO_EVENT_KEY_DOWN: if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) goto done; break; } } } draw_mesh(); al_flip_display(); frames++; } done: printf("%.1f FPS\n", frames / (al_current_time() - start)); glDeleteProgramsARB(1, &pid); al_destroy_event_queue(queue); return 0; }
int main() { /* Really this is for testing purposes, in no way will this be the final usage */ GFXContext context; context.major = 0; context.minor = 0; if(!gfx_init(context, GFX_ERROR_MODE_DEBUG)) { GFXError error; if(gfx_errors_peek(&error)) print_error(error); return 0; } /* Setup 2 windows */ GFXColorDepth depth; depth.redBits = 8; depth.greenBits = 8; depth.blueBits = 8; GFXWindow* window1 = gfx_window_create(NULL, 0, &depth, "Window Unos", 100, 100, 800, 600, GFX_WINDOW_RESIZABLE); GFXWindow* window2 = gfx_window_create(NULL, 0, &depth, "Window Deux", 200, 200, 800, 600, GFX_WINDOW_RESIZABLE); /* Pipeline */ GFXPipeline* pipeline = gfx_pipeline_create(); char targets[] = { 0 }; GFXViewport viewport = { 0, 0, 800, 600 }; pipeline->viewport = viewport; gfx_pipeline_target(pipeline, 1, targets); GFXPipe* bucket = gfx_pipeline_push_bucket(pipeline, 0); gfx_pipe_get_state(bucket)->render.state = GFX_STATE_DEFAULT | GFX_CLEAR_COLOR; /* Texture */ GFXTextureFormat format; format.components = 3; format.type.unpacked = GFX_UNSIGNED_BYTE; format.interpret = GFX_INTERPRET_NORMALIZED; GFXTexture* tex = gfx_texture_create(GFX_TEXTURE_2D, format, 0, 800, 600, 1); GFXTextureImage image; image.texture = tex; image.mipmap = 0; image.layer = 0; gfx_pipeline_attach(pipeline, image, GFX_COLOR_ATTACHMENT, 0); /* Post processing */ const char* vertSrc = "in ivec4 data;" "out vec2 coord;" "void main() {" "gl_Position = vec4(data.xy, 0, 1);" "coord = data.zw;" "}"; const char* fragSrcA = "in vec2 coord;" "out vec3 color;" "uniform sampler2D tex;" "void main() {" "color = vec3(1.0f) - texture(tex, coord).rgb;" "}"; const char* fragSrcB = "in vec2 coord;" "out vec3 color;" "uniform sampler2D tex;" "void main() {" "color = texture(tex, coord).rgb;" "}"; GFXShader* vert = gfx_shader_create(GFX_VERTEX_SHADER); GFXShader* frag = gfx_shader_create(GFX_FRAGMENT_SHADER); gfx_shader_set_source(vert, 1, &vertSrc, NULL); gfx_shader_set_source(frag, 1, &fragSrcA, NULL); GFXShader* shaders[] = { vert, frag }; GFXPipe* pipeA = gfx_pipeline_push_process(pipeline, window1, 0); GFXProgram* programA = gfx_pipe_process_add(pipeA->process, GFX_ALL_SHADERS, 1); gfx_program_set_attribute(programA, 0, "data"); gfx_program_link(programA, 2, shaders, 0); gfx_shader_set_source(frag, 1, &fragSrcB, NULL); GFXPipe* pipeB = gfx_pipeline_push_process(pipeline, window2, 0); GFXProgram* programB = gfx_pipe_process_add(pipeB->process, GFX_ALL_SHADERS, 1); gfx_program_set_attribute(programB, 0, "data"); gfx_program_link(programB, 2, shaders, 0); gfx_shader_free(vert); gfx_shader_free(frag); /* Property map */ GFXSampler sampler = { .minFilter = GFX_FILTER_LINEAR, .mipFilter = GFX_FILTER_NEAREST, .magFilter = GFX_FILTER_LINEAR, .maxAnisotropy = 1.0f, .lodMin = 0, .lodMax = 0, .wrapS = GFX_WRAP_REPEAT, .wrapT = GFX_WRAP_REPEAT, .wrapR = GFX_WRAP_REPEAT }; GFXPropertyMap* mapA = gfx_pipe_process_get_map(pipeA->process, 1); GFXPropertyMap* mapB = gfx_pipe_process_get_map(pipeB->process, 1); gfx_property_map_forward_named(mapA, 0, 0, 0, GFX_FRAGMENT_SHADER, "tex"); gfx_property_map_set_sampler(mapA, 0, 0, sampler); gfx_property_map_set_texture(mapA, 0, 0, tex); gfx_property_map_forward_named(mapB, 0, 0, 0, GFX_FRAGMENT_SHADER, "tex"); gfx_property_map_set_sampler_share(mapB, 0, 0, mapA, 0, 0); gfx_property_map_set_texture(mapB, 0, 0, tex); /* Mesh and material */ GFXMaterial* material = create_material(); GFXMesh* mesh = create_mesh(); /* Batch */ GFXBatch* batch = gfx_batch_create( bucket->bucket, material, mesh, 0, 0, 1, 1); gfx_batch_set_level( batch, 0, 0, 0, 1); gfx_batch_set( batch, 0, 1, 1); /* Setup a loop */ while(gfx_poll_events() && gfx_get_num_windows()) { /* Execute pipeline & swap buffers */ gfx_pipeline_execute(pipeline, 0); /* Print time */ //double time = gfx_get_time(); //gfx_set_time(0.0); //printf("%f\n", 1.0 / time); /* Print all the errors! */ GFXError error; while(gfx_errors_peek(&error)) { print_error(error); gfx_errors_pop(); } } /* Free all the things */ gfx_batch_free(batch); gfx_mesh_free(mesh); gfx_material_free(material); gfx_program_map_free(programMap); gfx_texture_free(tex); gfx_pipeline_free(pipeline); gfx_window_free(window1); gfx_window_free(window2); gfx_terminate(); return 0; }
void test_getEntArrAdj_down() { iMesh_Instance mesh = create_mesh(); int err; // get quads adjacent to a edge-row of hexes iBase_EntityHandle *adj = 0; int *off = 0; int adj_alloc = 0, off_alloc = 0; int adj_size = -1, off_size = -1; iMesh_getEntArrAdj( mesh, HEXES[0][0], INTERVALS, iBase_FACE, &adj, &adj_alloc, &adj_size, &off, &off_alloc, &off_size, &err ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK( 0 != adj ); CHECK( 0 != off ); CHECK_EQUAL( 2*INTERVALS+2, adj_size ); // corner hexes adj to 3 faces, others adj to 2 CHECK_EQUAL( INTERVALS+1, off_size ); // one more than number of input handles CHECK( adj_alloc >= adj_size ); CHECK( off_alloc >= off_size ); // first (corner) hex should have three adjacent faces CHECK_EQUAL( 3, off[1] - off[0] ); iBase_EntityHandle exp[3] = { FACES[0][0][0], FACES[3][0][0], FACES[4][0][0] }; iBase_EntityHandle act[3]; std::copy( adj + off[0], adj+off[1], act ); std::sort( exp, exp+3 ); std::sort( act, act+3 ); CHECK_ARRAYS_EQUAL( exp, 3, act, 3 ); // last (corner) hex should have three adjacent faces CHECK_EQUAL( 3, off[INTERVALS] - off[INTERVALS-1] ); iBase_EntityHandle exp2[3] = { FACES[0][0][INTERVALS-1], FACES[3][0][INTERVALS-1], FACES[5][0][0] }; std::copy( adj + off[INTERVALS-1], adj+off[INTERVALS], act ); std::sort( exp2, exp2+3 ); std::sort( act, act+3 ); CHECK_ARRAYS_EQUAL( exp2, 3, act, 3 ); // all middle hexes should have two adjacent faces for (int i = 1; i < INTERVALS-1; ++i) { iBase_EntityHandle e1, e2, a1, a2; e1 = FACES[0][0][i]; e2 = FACES[3][0][i]; if (e1 > e2) std::swap(e1,e2); CHECK_EQUAL( 2, off[i+1] - off[i] ); a1 = adj[off[i] ]; a2 = adj[off[i]+1]; if (a1 > a2) std::swap(a1,a2); CHECK_EQUAL( e1, a1 ); CHECK_EQUAL( e2, a2 ); } free(adj); free(off); }
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris) { /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data; BL::Material material_override = render_layer.material_override; /* find shader indices */ vector<uint> used_shaders; BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { if(material_override) find_shader(material_override, used_shaders, scene->default_surface); else find_shader(slot->material(), used_shaders, scene->default_surface); } if(used_shaders.size() == 0) { if(material_override) find_shader(material_override, used_shaders, scene->default_surface); else used_shaders.push_back(scene->default_surface); } /* test if we need to sync */ Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh * does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ bool attribute_recalc = false; foreach(uint shader, mesh->used_shaders) if(scene->shaders[shader]->need_update_attributes) attribute_recalc = true; if(!attribute_recalc) return mesh; } } /* ensure we only sync instanced meshes once */ if(mesh_synced.find(mesh) != mesh_synced.end()) return mesh; mesh_synced.insert(mesh); /* create derived mesh */ PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles"); vector<Mesh::Triangle> oldtriangle = mesh->triangles; /* compares curve_keys rather than strands in order to handle quick hair * adjustsments in dynamic BVH - other methods could probably do this better*/ vector<float4> oldcurve_keys = mesh->curve_keys; mesh->clear(); mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); if(render_layer.use_surfaces || render_layer.use_hair) { if(preview) b_ob.update_from_editmode(); bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed); if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); create_mesh_volume_attributes(scene, b_ob, mesh); } if(render_layer.use_hair) sync_curves(mesh, b_mesh, b_ob, false); /* free derived mesh */ b_data.meshes.remove(b_mesh); } } /* displacement method */ if(cmesh.data) { const int method = RNA_enum_get(&cmesh, "displacement_method"); if(method == 0 || !experimental) mesh->displacement_method = Mesh::DISPLACE_BUMP; else if(method == 1) mesh->displacement_method = Mesh::DISPLACE_TRUE; else mesh->displacement_method = Mesh::DISPLACE_BOTH; } /* tag update */ bool rebuild = false; if(oldtriangle.size() != mesh->triangles.size()) rebuild = true; else if(oldtriangle.size()) { if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0) rebuild = true; } if(oldcurve_keys.size() != mesh->curve_keys.size()) rebuild = true; else if(oldcurve_keys.size()) { if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float4)*oldcurve_keys.size()) != 0) rebuild = true; } mesh->tag_update(scene, rebuild); return mesh; }
void test_getEntArrAdj_conn() { iMesh_Instance mesh = create_mesh(); int err; // test hex vertices for (int i = 0; i < INTERVALS; ++i) { for (int j = 0; j < INTERVALS; ++j) { iBase_EntityHandle adj[8*INTERVALS]; int off[INTERVALS+1]; int adj_alloc = sizeof(adj)/sizeof(adj[0]); int off_alloc = sizeof(off)/sizeof(off[0]); int adj_size = -1, off_size = -1; iBase_EntityHandle* adj_ptr = adj; int* off_ptr = off; iMesh_getEntArrAdj( mesh, HEXES[i][j], INTERVALS, iBase_VERTEX, &adj_ptr, &adj_alloc, &adj_size, &off_ptr, &off_alloc, &off_size, &err ); CHECK_EQUAL( &adj[0], adj_ptr ); CHECK_EQUAL( &off[0], off_ptr ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK_EQUAL( 8*INTERVALS, adj_size ); CHECK_EQUAL( 8*INTERVALS, adj_alloc ); CHECK_EQUAL( INTERVALS+1, off_size ); CHECK_EQUAL( INTERVALS+1, off_alloc ); for (int k = 0; k < INTERVALS; ++k) { CHECK_EQUAL( 8*k, off[k] ); iBase_EntityHandle conn[8]; HEX_VERTS( i, j, k, conn ); CHECK_ARRAYS_EQUAL( conn, 8, adj + off[k], off[k+1]-off[k] ); } } } // test quad vertices for one side of mesh const int f = 0; for (int i = 0; i < INTERVALS; ++i) { iBase_EntityHandle adj[4*INTERVALS]; int off[INTERVALS+1]; int adj_alloc = sizeof(adj)/sizeof(adj[0]); int off_alloc = sizeof(off)/sizeof(off[0]); int adj_size = -1, off_size = -1; iBase_EntityHandle* adj_ptr = adj; int* off_ptr = off; iMesh_getEntArrAdj( mesh, FACES[f][i], INTERVALS, iBase_VERTEX, &adj_ptr, &adj_alloc, &adj_size, &off_ptr, &off_alloc, &off_size, &err ); CHECK_EQUAL( &adj[0], adj_ptr ); CHECK_EQUAL( &off[0], off_ptr ); CHECK_EQUAL( iBase_SUCCESS, err ); CHECK_EQUAL( 4*INTERVALS, adj_size ); CHECK_EQUAL( 4*INTERVALS, adj_alloc ); CHECK_EQUAL( INTERVALS+1, off_size ); CHECK_EQUAL( INTERVALS+1, off_alloc ); for (int k = 0; k < INTERVALS; ++k) { CHECK_EQUAL( 4*k, off[k] ); iBase_EntityHandle conn[4]; QUAD_VERTS( f, i, k, conn ); CHECK_ARRAYS_EQUAL( conn, 4, adj + off[k], off[k+1]-off[k] ); } } }
void draw() { int mesh = 0, multi = 0, meshcolor = 0; switch (state) { case STATE_GRAY_SOURCE: parg_shader_bind(P_GRAY); parg_texture_bind(graytex, 0); parg_uniform1f(U_ZSCALE, 1); break; case STATE_COLOR_IH: mesh = 1; parg_shader_bind(P_GRAYMESH); parg_uniform1f(U_ZSCALE, 0.3); break; case STATE_COLOR_DHSCSI: mesh = multi = 1; parg_shader_bind(P_GRAYMESH); parg_uniform1f(U_ZSCALE, 0.3); break; case STATE_MULTI_RGBA: case STATE_MULTI_RGB: case STATE_MULTI_DIAGRAM: meshcolor = mesh = multi = 1; parg_shader_bind(P_GRAYMESH); parg_uniform1f(U_ZSCALE, 0.25); break; case STATE_COLOR_DEFAULT: case STATE_GRAY_DEFAULT: case STATE_GRAY_SIMPLIFY: case STATE_GRAY_INVERT: case STATE_GRAY_HEIGHTS: mesh = 1; parg_shader_bind(P_GRAYMESH); parg_uniform1f(U_ZSCALE, 1); break; case STATE_GRAY_MULTI: mesh = multi = 1; parg_shader_bind(P_GRAYMESH); parg_texture_bind(colortex, 0); parg_uniform1f(U_ZSCALE, 0.3); break; case STATE_GRAY_DUAL: mesh = multi = 1; parg_shader_bind(P_GRAYMESH); parg_texture_bind(colortex, 0); parg_uniform1f(U_ZSCALE, 1); break; case STATE_GRAY_DHS: case STATE_GRAY_DHSC: mesh = multi = 1; parg_shader_bind(P_GRAYMESH); parg_texture_bind(colortex, 0); parg_uniform1f(U_ZSCALE, 0.5); break; case STATE_COLOR_SOURCE: parg_texture_bind(colortex, 0); parg_shader_bind(P_COLOR); parg_uniform1f(U_ZSCALE, 1); break; default: break; } if (mesh) { for (int i = 0; i < sizeof(trimesh) / sizeof(trimesh[0]); i++) { parg_mesh_free(trimesh[i]); } memset(trimesh, 0, sizeof(trimesh)); create_mesh(); } Matrix4 model; if (mesh) { model = M4MakeScale(V3MakeFromElems(20, 20, 10)); model = M4Mul(M4MakeTranslation(V3MakeFromElems(-10, -10, 0)), model); } else { model = M4MakeIdentity(); } Matrix4 modelview = M4Mul(view, model); Matrix4 mvp = M4Mul(projection, modelview); parg_uniform_matrix4f(U_MVP, &mvp); parg_draw_clear(); if (mesh) { Vector4 colors[3]; colors[0] = (Vector4){0, 0.6, 0.9, 1}; colors[1] = (Vector4){0, 0.9, 0.6, 1}; colors[2] = (Vector4){0.9, 0.6, 0, 1}; Vector4 black = {0, 0, 0, 1.0}; for (int imesh = 0; imesh < nmeshes; imesh++) { parg_varray_enable(parg_mesh_coord(trimesh[imesh]), A_POSITION, 3, PARG_FLOAT, 0, 0); parg_varray_bind(parg_mesh_index(trimesh[imesh])); if (meshcolor) { unsigned int b = meshcolors[imesh] & 0xff; unsigned int g = (meshcolors[imesh] >> 8) & 0xff; unsigned int r = (meshcolors[imesh] >> 16) & 0xff; unsigned int a = (meshcolors[imesh] >> 24) & 0xff; Vector4 color; color.x = r / 255.0f; color.y = g / 255.0f; color.z = b / 255.0f; color.w = a / 255.0f; parg_uniform4f(U_COLOR, &color); } else { parg_uniform4f(U_COLOR, &colors[imesh]); } parg_draw_triangles_u16(0, parg_mesh_ntriangles(trimesh[imesh])); parg_uniform4f(U_COLOR, &black); parg_draw_wireframe_triangles_u16( 0, parg_mesh_ntriangles(trimesh[imesh])); } } else {
void recv_create_mesh(void) { int i = recv_index(); create_mesh(i); }
/** * メッシュ情報を読み込む * * @param mesh メッシュ情報 */ void FbxFileLoader::load_mesh( FbxMesh* mesh ) { if ( ! mesh ) { return; } if ( ! get_model()->get_mesh() ) { get_model()->set_mesh( create_mesh() ); } VertexIndexMap vertex_index_map; VertexList vertex_list; Mesh::PositionList position_list; Mesh::VertexWeightList vertex_weight_list; // load_mesh_vertex() for ( int n = 0; n < mesh->GetControlPointsCount(); n++ ) { FbxVector4 v = mesh->GetControlPointAt( n ); position_list.push_back( Mesh::Position( static_cast< float >( v[ 0 ] ), static_cast< float >( v[ 1 ] ), static_cast< float >( v[ 2 ] ) ) ); } // load_mesh_vertex_weight() { int skin_count = mesh->GetDeformerCount( FbxDeformer::eSkin ); if ( skin_count > 0 ) { assert( skin_count == 1 ); vertex_weight_list.resize( position_list.size() ); FbxSkin* skin = FbxCast< FbxSkin >( mesh->GetDeformer( 0, FbxDeformer::eSkin ) ); load_mesh_vertex_weight( skin, vertex_weight_list ); } } FbxLayerElementSmoothing* smoothing = 0; // load_mesh_smoothing_info() { FbxLayer* layer = mesh->GetLayer( 0 ); smoothing = layer->GetSmoothing(); } if ( ! smoothing ) { COMMON_THROW_EXCEPTION_MESSAGE( "this FBX format is not supported. ( no smoothing info )" ); } // load_mesh_plygon() FbxLayerElementArrayTemplate< int >* material_indices; mesh->GetMaterialIndices( & material_indices ); for ( int n = 0; n < mesh->GetPolygonCount(); n++ ) { Mesh::VertexGroup* vertex_group = get_model()->get_mesh()->get_vertex_group_at( material_indices->GetAt( n ) ); bool is_smooth = smoothing->GetDirectArray().GetAt( n ) != 0; FbxVector4 polygon_normal( 0.f, 0.f, 0.f ); if ( ! is_smooth ) { // ポリゴンの法線を計算する Mesh::Position p1( position_list.at( mesh->GetPolygonVertex( n, 0 ) ) ); Mesh::Position p2( position_list.at( mesh->GetPolygonVertex( n, 1 ) ) ); Mesh::Position p3( position_list.at( mesh->GetPolygonVertex( n, 2 ) ) ); FbxVector4 a = FbxVector4( p1.x(), p1.y(), p1.z() ); FbxVector4 b = FbxVector4( p2.x(), p2.y(), p2.z() ); FbxVector4 c = FbxVector4( p3.x(), p3.y(), p3.z() ); FbxVector4 ab( b - a ); FbxVector4 bc( c - b ); polygon_normal = ab.CrossProduct( bc ); polygon_normal.Normalize(); } for ( int m = 0; m < mesh->GetPolygonSize( n ); m++ ) { int position_index = mesh->GetPolygonVertex( n, m ); Mesh::Vertex v; v.Position = Mesh::Position( position_list.at( position_index ) ); FbxVector2 uv_vector; bool unmapped; if ( mesh->GetPolygonVertexUV( n, m, "UVMap", uv_vector, unmapped) ) { v.TexCoord = Mesh::TexCoord( static_cast< float >( uv_vector[ 0 ] ), 1.f - static_cast< float >( uv_vector[ 1 ] ) ); } if ( is_smooth ) { FbxVector4 normal_vector; // 頂点の法線 if ( mesh->GetPolygonVertexNormal( n, m, normal_vector ) ) { v.Normal = Mesh::Normal( static_cast< float >( normal_vector[ 0 ] ), static_cast< float >( normal_vector[ 1 ] ), static_cast< float >( normal_vector[ 2 ] ) ); } } else { // ポリゴンの法線 v.Normal = Mesh::Normal( static_cast< float >( polygon_normal[ 0 ] ), static_cast< float >( polygon_normal[ 1 ] ), static_cast< float >( polygon_normal[ 2 ] ) ); } // 頂点の一覧に追加 { VertexIndexMap::iterator i = vertex_index_map.find( v ); if ( i != vertex_index_map.end() ) { vertex_group->add_index( i->second ); } else { Mesh::Index vertex_index = static_cast< Mesh::Index >( get_model()->get_mesh()->get_vertex_count() ); get_model()->get_mesh()->add_vertex( v ); if ( ! vertex_weight_list.empty() ) { get_model()->get_mesh()->add_vertex_weight( vertex_weight_list.at( position_index ) ); } vertex_group->add_index( vertex_index ); vertex_index_map[ v ] = vertex_index; } } } } }
Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph, BL::Object &b_ob, BL::Object &b_ob_instance, bool object_updated, bool show_self, bool show_particles) { /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); BL::ID key = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; BL::Material material_override = view_layer.material_override; /* find shader indices */ vector<Shader *> used_shaders; BL::Object::material_slots_iterator slot; for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { if (material_override) { find_shader(material_override, used_shaders, scene->default_surface); } else { BL::ID b_material(slot->material()); find_shader(b_material, used_shaders, scene->default_surface); } } if (used_shaders.size() == 0) { if (material_override) find_shader(material_override, used_shaders, scene->default_surface); else used_shaders.push_back(scene->default_surface); } /* test if we need to sync */ int requested_geometry_flags = Mesh::GEOMETRY_NONE; if (view_layer.use_surfaces) { requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; } if (view_layer.use_hair) { requested_geometry_flags |= Mesh::GEOMETRY_CURVES; } Mesh *mesh; if (!mesh_map.sync(&mesh, key)) { /* if transform was applied to mesh, need full update */ if (object_updated && mesh->transform_applied) ; /* test if shaders changed, these can be object level so mesh * does not get tagged for recalc */ else if (mesh->used_shaders != used_shaders) ; else if (requested_geometry_flags != mesh->geometry_flags) ; else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ bool attribute_recalc = false; foreach (Shader *shader, mesh->used_shaders) if (shader->need_update_mesh) attribute_recalc = true; if (!attribute_recalc) return mesh; } } /* ensure we only sync instanced meshes once */ if (mesh_synced.find(mesh) != mesh_synced.end()) return mesh; progress.set_sync_status("Synchronizing object", b_ob.name()); mesh_synced.insert(mesh); /* create derived mesh */ array<int> oldtriangles; array<Mesh::SubdFace> oldsubd_faces; array<int> oldsubd_face_corners; oldtriangles.steal_data(mesh->triangles); oldsubd_faces.steal_data(mesh->subd_faces); oldsubd_face_corners.steal_data(mesh->subd_face_corners); /* compares curve_keys rather than strands in order to handle quick hair * adjustments in dynamic BVH - other methods could probably do this better*/ array<float3> oldcurve_keys; array<float> oldcurve_radius; oldcurve_keys.steal_data(mesh->curve_keys); oldcurve_radius.steal_data(mesh->curve_radius); mesh->clear(); mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); if (requested_geometry_flags != Mesh::GEOMETRY_NONE) { /* Adaptive subdivision setup. Not for baking since that requires * exact mapping to the Blender mesh. */ if (scene->bake_manager->get_baking()) { mesh->subdivision_type = Mesh::SUBDIVISION_NONE; } else { mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental); } /* For some reason, meshes do not need this... */ bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh( b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type); if (b_mesh) { /* Sync mesh itself. */ if (view_layer.use_surfaces && show_self) { if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions); else create_mesh(scene, mesh, b_mesh, used_shaders, false); create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); } /* Sync hair curves. */ if (view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { sync_curves(mesh, b_mesh, b_ob, false); } free_object_to_mesh(b_data, b_ob, b_mesh); } } mesh->geometry_flags = requested_geometry_flags; /* fluid motion */ sync_mesh_fluid_motion(b_ob, scene, mesh); /* tag update */ bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) || (oldsubd_face_corners != mesh->subd_face_corners) || (oldcurve_keys != mesh->curve_keys) || (oldcurve_radius != mesh->curve_radius); mesh->tag_update(scene, rebuild); return mesh; }
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) { /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); BL::ID key = (object_is_modified(b_ob))? b_ob: b_ob_data; /* find shader indices */ vector<uint> used_shaders; BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { BL::Material material_override = render_layers.front().material_override; if(material_override) find_shader(material_override, used_shaders, scene->default_surface); else find_shader(slot->material(), used_shaders, scene->default_surface); } if(used_shaders.size() == 0) used_shaders.push_back(scene->default_surface); /* test if we need to sync */ Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ bool attribute_recalc = false; foreach(uint shader, mesh->used_shaders) if(scene->shaders[shader]->need_update_attributes) attribute_recalc = true; if(!attribute_recalc) return mesh; } } /* ensure we only sync instanced meshes once */ if(mesh_synced.find(mesh) != mesh_synced.end()) return mesh; mesh_synced.insert(mesh); /* create derived mesh */ BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview); PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles"); vector<Mesh::Triangle> oldtriangle = mesh->triangles; mesh->clear(); mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); if(b_mesh) { if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); /* free derived mesh */ object_remove_mesh(b_data, b_mesh); } /* displacement method */ if(cmesh.data) { int method = RNA_enum_get(&cmesh, "displacement_method"); if(method == 0 || !experimental) mesh->displacement_method = Mesh::DISPLACE_BUMP; else if(method == 1) mesh->displacement_method = Mesh::DISPLACE_TRUE; else mesh->displacement_method = Mesh::DISPLACE_BOTH; } /* tag update */ bool rebuild = false; if(oldtriangle.size() != mesh->triangles.size()) rebuild = true; else if(oldtriangle.size()) { if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0) rebuild = true; } mesh->tag_update(scene, rebuild); return mesh; }
Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, bool object_updated, bool hide_tris) { /* When viewport display is not needed during render we can force some * caches to be releases from blender side in order to reduce peak memory * footprint during synchronization process. */ const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface(); const bool can_free_caches = BlenderSession::headless || is_interface_locked; /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data; BL::Material material_override = render_layer.material_override; /* find shader indices */ vector<uint> used_shaders; BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { if(material_override) { find_shader(material_override, used_shaders, scene->default_surface); } else { BL::ID b_material(slot->material()); find_shader(b_material, used_shaders, scene->default_surface); } } if(used_shaders.size() == 0) { if(material_override) find_shader(material_override, used_shaders, scene->default_surface); else used_shaders.push_back(scene->default_surface); } /* test if we need to sync */ int requested_geometry_flags = Mesh::GEOMETRY_NONE; if(render_layer.use_surfaces) { requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; } if(render_layer.use_hair) { requested_geometry_flags |= Mesh::GEOMETRY_CURVES; } Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh * does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); else if(requested_geometry_flags != mesh->geometry_flags); else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ bool attribute_recalc = false; foreach(uint shader, mesh->used_shaders) if(scene->shaders[shader]->need_update_attributes) attribute_recalc = true; if(!attribute_recalc) return mesh; } } /* ensure we only sync instanced meshes once */ if(mesh_synced.find(mesh) != mesh_synced.end()) return mesh; mesh_synced.insert(mesh); /* create derived mesh */ PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles"); vector<Mesh::Triangle> oldtriangle = mesh->triangles; /* compares curve_keys rather than strands in order to handle quick hair * adjustments in dynamic BVH - other methods could probably do this better*/ vector<float4> oldcurve_keys = mesh->curve_keys; mesh->clear(); mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); if(requested_geometry_flags != Mesh::GEOMETRY_NONE) { /* mesh objects does have special handle in the dependency graph, * they're ensured to have properly updated. * * updating meshes here will end up having derived mesh referencing * freed data from the blender side. */ if(preview && b_ob.type() != BL::Object::type_MESH) b_ob.update_from_editmode(); bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed); if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); } if(render_layer.use_hair) sync_curves(mesh, b_mesh, b_ob, false); if(can_free_caches) { b_ob.cache_release(); } /* free derived mesh */ b_data.meshes.remove(b_mesh); } } mesh->geometry_flags = requested_geometry_flags; /* displacement method */ if(cmesh.data) { const int method = get_enum(cmesh, "displacement_method"); if(method == 0 || !experimental) mesh->displacement_method = Mesh::DISPLACE_BUMP; else if(method == 1) mesh->displacement_method = Mesh::DISPLACE_TRUE; else mesh->displacement_method = Mesh::DISPLACE_BOTH; } /* tag update */ bool rebuild = false; if(oldtriangle.size() != mesh->triangles.size()) rebuild = true; else if(oldtriangle.size()) { if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0) rebuild = true; } if(oldcurve_keys.size() != mesh->curve_keys.size()) rebuild = true; else if(oldcurve_keys.size()) { if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float4)*oldcurve_keys.size()) != 0) rebuild = true; } mesh->tag_update(scene, rebuild); return mesh; }