t_mat4 mat4_inverse(t_mat4 m) { int i; float coefs[18]; t_vec4 lenny[6][6]; t_mat4 inverse; float det; mat_invcoef(m, coefs); make_faces(coefs, lenny[0]); make_vecs(m, lenny[1]); make_inv(lenny[2], lenny[1], lenny[0], lenny[3]); i = -1; while (++i < 4) { inverse.s.v[i] = vec4_mul(lenny[2][i], lenny[3][i % 2]).s; lenny[5][0].v[i] = lenny[2][i].v[0]; } lenny[4][0] = vec4_mul(m.s.v[0], lenny[5][0]); det = lenny[4][0].s.x + lenny[4][0].s.y + lenny[4][0].s.z + lenny[4][0].s.w; return (mat4_muls(inverse, 1.0f / det)); }
namespace details { // I don't use glm vectors here because they're not constexpr, // but we don't need to do anything with them anyway, other // than printing, so it's not a problem. // Note that these are returned in the same order as the // voxel::direction enum constexpr std::array<std::array<int, 3>, 6> make_normals() { return { -1, 0, 0, // Left 1, 0, 0, // Right 0, -1, 0, // Down 0, 1, 0, // Up 0, 0, -1, // Back 0, 0, 1 // Front }; } struct face { size_t normal; std::array<size_t, 6> vertices; }; constexpr std::array<face, 6> make_faces() { return { // Left face: First triangle voxel::left, voxel::right_bottom_front, voxel::right_top_front , voxel::left_top_front , // Second triangle voxel::right_bottom_front, voxel::left_top_front , voxel::left_bottom_front , // Right face: First triangle voxel::right, voxel::left_bottom_back , voxel::left_top_back , voxel::right_top_back , // Second triangle voxel::left_bottom_back , voxel::right_top_back , voxel::right_bottom_back , // Bottom face: First triangle voxel::bottom, voxel::right_bottom_back , voxel::right_bottom_front, voxel::left_bottom_front , // Second triangle voxel::right_bottom_back , voxel::left_bottom_front , voxel::left_bottom_back , // Top face: First triangle voxel::top, voxel::right_top_front , voxel::right_top_back , voxel::left_top_back , // Second triangle voxel::right_top_front , voxel::left_top_back , voxel::left_top_front , // Back face: First triangle voxel::back, voxel::left_bottom_front , voxel::left_top_front , voxel::left_top_back , // Second triangle voxel::left_bottom_front , voxel::left_top_back , voxel::left_bottom_back , // Front face: First triangle voxel::front, voxel::right_bottom_back , voxel::right_top_back , voxel::right_top_front , // Second triangle voxel::right_bottom_back , voxel::right_top_front , voxel::right_bottom_front }; } constexpr auto normals = make_normals(); constexpr auto faces = make_faces(); class obj { public: void cube(voxel v) { auto c = v.corners<glm::vec3>(); _indexes.push_back(_vertices.size()); _vertices.insert(_vertices.end(), begin(c), end(c)); } void write(std::ostream &os) const { for(auto v : _vertices) { os << "v " << v.x << " " << v.y << " " << v.z << "\n"; } os << "\n"; for(auto n : normals) { os << "vn " << n[0] << " " << n[1] << " " << n[2] << "\n"; } for (size_t i : _indexes) { for(face f : faces) { for(size_t v = 0; v < f.vertices.size(); ++v) { if(v % 3 == 0) os << "\nf "; os << (f.vertices[v] + i + 1) << "//" << (f.normal + 1) << " "; } } } } private: std::vector<glm::vec3> _vertices; std::vector<size_t> _indexes; }; void obj_mesh(octree const&oc, std::ostream &out) { obj o; for(voxel v : oc) { assert(v.material() != voxel::unknown_material); if(v.material() != voxel::void_material) o.cube(v); } o.write(out); } void octree::mesh(mesh_t mesh_type, std::ostream &out) const { switch (mesh_type) { case obj: obj_mesh(*this, out); return; } assert(!"Unimplemented mesh type"); } } // namespace details
ErrorCode ReadCCMIO::read_faces(CCMIOID faceID, CCMIOEntity bdy_or_int, TupleList &vert_map, TupleList &face_map #ifndef TUPLE_LIST ,SenseList &sense_map #endif , Range *new_faces) { if (kCCMIOInternalFaces != bdy_or_int && kCCMIOBoundaryFaces != bdy_or_int) CHKERR(MB_FAILURE, "Face type isn't boundary or internal."); CCMIOSize_t dum_faces; CCMIOError error = kCCMIONoErr; CCMIOEntitySize(&error, faceID, &dum_faces, NULL); int num_faces = GETINT32(dum_faces); // get the size of the face connectivity array (not really a straight connect // array, has n, connect(n), ...) CCMIOSize_t farray_size = CCMIOSIZEC(0); CCMIOReadFaces(&error, faceID, bdy_or_int, NULL, &farray_size, NULL, CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); CHKCCMERR(error, "Trouble reading face connectivity length."); // allocate vectors for holding farray and cells for each face; use new for finer // control of de-allocation int num_sides = (kCCMIOInternalFaces == bdy_or_int ? 2 : 1); int *farray = new int[GETINT32(farray_size)]; // read farray and make the faces CCMIOID mapID; CCMIOReadFaces(&error, faceID, bdy_or_int, &mapID, NULL, farray, CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); CHKCCMERR(error, "Trouble reading face connectivity."); std::vector<EntityHandle> face_handles; ErrorCode rval = make_faces(farray, vert_map, face_handles, num_faces); CHKERR(rval, NULL); // read face cells and make tuples int *face_cells; if (num_sides*num_faces < farray_size) face_cells = new int[num_sides*num_faces]; else face_cells = farray; CCMIOReadFaceCells(&error, faceID, bdy_or_int, face_cells, CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); CHKCCMERR(error, "Trouble reading face cells."); int *tmp_ptr = face_cells; for (unsigned int i = 0; i < face_handles.size(); i++) { #ifdef TUPLE_LIST short forward = 1, reverse = -1; face_map.push_back(&forward, tmp_ptr++, &face_handles[i], NULL); if (2 == num_sides) face_map.push_back(&reverse, tmp_ptr++, &face_handles[i], NULL); #else face_map[*tmp_ptr].push_back(face_handles[i]); sense_map[*tmp_ptr++].push_back(1); if (2 == num_sides) { face_map[*tmp_ptr].push_back(face_handles[i]); sense_map[*tmp_ptr++].push_back(-1); } #endif } // now read & set face gids, reuse face_cells 'cuz we know it's big enough CCMIOReadMap(&error, mapID, face_cells, CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); CHKCCMERR(error, "Trouble reading face gids."); rval = mbImpl->tag_set_data(mGlobalIdTag, &face_handles[0], face_handles.size(), face_cells); CHKERR(rval, "Couldn't set face global ids."); // make a neumann set for these faces if they're all in a boundary face set if (kCCMIOBoundaryFaces == bdy_or_int) { EntityHandle neuset; rval = mbImpl->create_meshset(MESHSET_SET, neuset); CHKERR(rval, "Failed to create neumann set."); // don't trust entity index passed in int index; CCMIOGetEntityIndex(&error, faceID, &index); newNeusets[index] = neuset; rval = mbImpl->add_entities(neuset, &face_handles[0], face_handles.size()); CHKERR(rval, "Failed to add faces to neumann set."); // now tag as neumann set; will add id later int dum_val = 0; rval = mbImpl->tag_set_data(mNeumannSetTag, &neuset, 1, &dum_val); CHKERR(rval, "Failed to tag neumann set."); } if (new_faces) { std::sort(face_handles.begin(), face_handles.end()); std::copy(face_handles.rbegin(), face_handles.rend(), range_inserter(*new_faces)); } return MB_SUCCESS; }