[Bf-blender-cvs] [0ea70ab8e54] soc-2020-io-performance: Add faster fprintf writer, remove unused headers
Ankit Meel
noreply at git.blender.org
Thu Jun 11 17:46:38 CEST 2020
Commit: 0ea70ab8e54cf284af12badb4341bd7f31b7fccd
Author: Ankit Meel
Date: Tue Jun 9 00:20:07 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rB0ea70ab8e54cf284af12badb4341bd7f31b7fccd
Add faster fprintf writer, remove unused headers
Changes here:
Reverted temporarily to std::vector to keep working, instead of
waiting for D7931 to get committed in master.
Adds an forced inline function for calculation of face/ polygon normals
by averaging vertex normals. I will look for an existing method.
This way, the allocated memory in `data_to_export->mvert[i].no` is
actually used.
Also, `BLI::Vector<uint> face_normal_index` is not needed anymore since
we loop over the same polygon list while writing normals, so
their indices will be the same.
Adds a writer method option, `fprintf`, which is faster than `fstream`.
With fstream, 478 MB of an ico-sphere with 8 subsurf takes 22 seconds.
with fprintf, the same takes 13 seconds.
With fstream, a 44 MB of cube with 8 subsurf take 2.3 seconds.
with fprintf, the same takes 1.4 seconds.
Adds timing info of the full export directly in console.
Removed unused and repeated headers from `wavefront_obj.cc`.
Differential Revision: https://developer.blender.org/D7959
===================================================================
M source/blender/io/wavefront_obj/IO_wavefront_obj.h
M source/blender/io/wavefront_obj/intern/wavefront_obj.cc
M source/blender/io/wavefront_obj/intern/wavefront_obj.hh
M source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
M source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
M source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.hh
===================================================================
diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
index b2f03c6714a..6af50635565 100644
--- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h
+++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
@@ -22,7 +22,7 @@
#define __IO_WAVEFRONT_OBJ_H__
#include "BKE_context.h"
-#include <stdio.h>
+#include <stdio.h> /* For FILENAME_MAX. */
#ifdef __cplusplus
extern "C" {
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj.cc
index 25f56582e68..c26bd020535 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj.cc
@@ -22,6 +22,7 @@
*/
#include "IO_wavefront_obj.h"
+#include <chrono>
#include "wavefront_obj.hh"
#include "wavefront_obj_exporter.hh"
@@ -32,7 +33,12 @@
*/
void OBJ_export(bContext *C, const OBJExportParams *export_params)
{
+ std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
io::obj::exporter_main(C, export_params);
+ std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
+ std::cout << "-------- \n Time difference = "
+ << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[us]"
+ << std::endl;
}
/**
* Called from io_obj.c. Currently not implemented.
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj.hh b/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
index c9be522c189..0ad0279b6c4 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
@@ -21,10 +21,15 @@
#ifndef __WAVEFRONT_OBJ_HH__
#define __WAVEFRONT_OBJ_HH__
+#include <stdio.h>
+
#include "BKE_context.h"
+#include "BKE_object.h"
#include "BLI_array.hh"
#include "BLI_vector.hh"
+
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
namespace io {
@@ -41,12 +46,7 @@ struct Polygon {
* Vertex indices of this polygon. v1, v2 .. above.
* The index corresponds to the pre-defined vertex list.
*/
- BLI::Vector<uint> vertex_index;
- /**
- * Face normal indices of this polygon. vn1, vn2 .. above.
- * The index corresponds to the pre-defined face normal list.
- */
- BLI::Vector<uint> face_normal_index;
+ std::vector<uint> vertex_index;
};
/**
@@ -56,6 +56,7 @@ struct Polygon {
struct OBJ_data_to_export {
bContext *C;
Depsgraph *depsgraph;
+ Object *ob_eval;
/** Vertices in a mesh to export. */
MVert *mvert;
@@ -63,9 +64,10 @@ struct OBJ_data_to_export {
uint tot_vertices;
/** Polygons in a mesh to export. */
- BLI::Vector<Polygon> polygon_list;
+ /* TODO (ankitm): Replace vector with BLI::Vector. See D7931 */
+ std::vector<Polygon> polygon_list;
/** Number of polygons in a mesh to export. */
- uint tot_faces;
+ uint tot_poly;
};
} // namespace obj
} // namespace io
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
index b985d44bed1..588c8d9d280 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
@@ -24,24 +24,18 @@
#include "MEM_guardedalloc.h"
#include <stdio.h>
+#include <vector>
-#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
-#include "BKE_object.h"
#include "BKE_scene.h"
-#include "BLI_iterator.h"
-#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_vector.hh"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-
#include "IO_wavefront_obj.h"
#include "wavefront_obj.hh"
@@ -73,39 +67,39 @@ static void get_transformed_mesh_vertices(Mesh *me_eval,
/**
* Store the mesh vertex normals in data_to_export, in world coordinates.
*/
-static void get_transformed_vertex_normals(Mesh *me_eval, OBJ_data_to_export *data_to_export)
+static void get_transformed_vertex_normals(Mesh *me_eval,
+ Object *ob_eval,
+ OBJ_data_to_export *data_to_export)
{
+ BKE_mesh_ensure_normals(me_eval);
float transformed_normal[3];
- const MLoop *mloop;
- const MPoly *mpoly = me_eval->mpoly;
- const MVert *mvert = me_eval->mvert;
-
- for (uint i = 0; i < me_eval->totpoly; i++, mpoly++) {
- mloop = &me_eval->mloop[mpoly->loopstart];
- BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, transformed_normal);
+ for (uint i = 0; i < me_eval->totvert; i++) {
+ normal_short_to_float_v3(transformed_normal, me_eval->mvert[i].no);
+ mul_mat3_m4_v3(ob_eval->obmat, transformed_normal);
normal_float_to_short_v3(data_to_export->mvert[i].no, transformed_normal);
}
}
/**
- * Store a polygon's vertex indices and normal indices, indexing into the pre-defined
- * vertex coordinates and vertex normals list.
+ * Store a polygon's vertex indices, indexing into the pre-defined
+ * vertex coordinates list.
*/
static void get_polygon_vert_indices(Mesh *me_eval, OBJ_data_to_export *data_to_export)
{
const MLoop *mloop;
const MPoly *mpoly = me_eval->mpoly;
- data_to_export->tot_faces = me_eval->totpoly;
- data_to_export->polygon_list.increase_size_unchecked(me_eval->totpoly);
+ data_to_export->tot_poly = me_eval->totpoly;
+ data_to_export->polygon_list.resize(me_eval->totpoly);
for (uint i = 0; i < me_eval->totpoly; i++, mpoly++) {
mloop = &me_eval->mloop[mpoly->loopstart];
data_to_export->polygon_list[i].total_vertices_per_poly = mpoly->totloop;
+ data_to_export->polygon_list[i].vertex_index.resize(mpoly->totloop);
+
for (int j = 0; j < mpoly->totloop; j++) {
- data_to_export->polygon_list[i].vertex_index.append((mloop + j)->v + 1);
- data_to_export->polygon_list[i].face_normal_index.append(i + 1);
+ data_to_export->polygon_list[i].vertex_index[j] = (mloop + j)->v + 1;
}
}
}
@@ -115,11 +109,11 @@ static void get_geometry_per_object(const OBJExportParams *export_params,
{
Depsgraph *depsgraph = data_to_export->depsgraph;
Object *ob = CTX_data_active_object(data_to_export->C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Object *ob_eval = data_to_export->ob_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
get_transformed_mesh_vertices(me_eval, ob_eval, data_to_export);
- get_transformed_vertex_normals(me_eval, data_to_export);
+ get_transformed_vertex_normals(me_eval, ob_eval, data_to_export);
get_polygon_vert_indices(me_eval, data_to_export);
}
@@ -135,7 +129,9 @@ void exporter_main(bContext *C, const OBJExportParams *export_params)
get_geometry_per_object(export_params, &data_to_export);
+ /* Comment out either one of the following. */
write_obj_data(filepath, &data_to_export);
+ // write_obj_data_in_fprintf(filepath, &data_to_export);
MEM_freeN(data_to_export.mvert);
}
} // namespace obj
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
index 54cac5a266b..6d4b3be8e32 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
@@ -24,45 +24,117 @@
#include <fstream>
#include <iostream>
+#include "DNA_object_types.h"
+
#include "wavefront_obj.hh"
#include "wavefront_obj_file_handler.hh"
namespace io {
namespace obj {
+/**
+ * Calculate a face normal's axis component by averaging over its vertex normals.
+ */
+MALWAYS_INLINE short face_normal_axis_component(const Polygon &poly_to_write,
+ int axis,
+ MVert *vertex_list)
+{
+ float sum = 0;
+ for (int i = 0; i < poly_to_write.total_vertices_per_poly; i++) {
+ sum += vertex_list[poly_to_write.vertex_index[i] - 1].no[axis];
+ }
+ return short(sum / poly_to_write.total_vertices_per_poly);
+}
+
/**
* Low level writer to the OBJ file at filepath.
- * data_to_export is filled in obj_exporter.cc.
*/
void write_obj_data(const char *filepath, OBJ_data_to_export *data_to_export)
{
- std::ofstream outfile(filepath, std::ios::binary);
+ std::ofstream outfile(filepath, std::ios::binary | std::ios::trunc);
+ if (outfile.is_open() == false) {
+ printf("Error opening file.");
+ return;
+ }
+
outfile << "# Blender 2.90 \n";
+ /** Write object name, as seen in outliner. First two characters are ID code, so skipped. */
+ outfile << "o " << data_to_export->ob_eval->id.name + 2 << "\n";
+
/** Write v x y z for all vertices. */
for (int i = 0; i < data_to_export->tot_vertices; i++) {
MVert *vertex = &data_to_export->mvert[i];
outfile << "v ";
- outfile << vertex[i].co[0] << " " << vertex[i].co[1] << " " << vertex[i].co[2] << "\n";
+ outfile << vertex->co[0] << " " << vertex->co[1] << " " << vertex->co[2] << "\n";
}
/** Write vn nx ny nz for all face normals. */
- for (int i = 0; i < data_to_export->tot_faces; i++) {
- MVert *vertex = &data_to_export->mvert[i];
- outfile << "vn ";
- outfile << vertex[i].no[0] << " " << vertex[i].no[1] << " " << vertex[i].no[2] << "\n";
+ for (int i = 0; i < data_to_export->tot_poly; i++) {
+ MVert *vertex_list = data_to_export->mvert;
+ const Polygon &polygon = data_to_export->polygon_list[i];
+ outfile << "vn " << face_normal_axis_component(polygon, 0, vertex_list) << " "
+ << face_normal_axis_component(polygon, 1, vertex_list) << " "
+ << face_normal_axis_component(polygon, 2, vertex_list) << "\n";
}
- /** Write f v1/vt1/vn1 .. total_vertices_per_poly , for all polygons. */
- for (int i = 0; i < data_to_export->tot_faces; i++) {
+ /**
+ * Write f v1/vt1/vn1 .. total_vertices_per_poly , for all polygons.
+ * i-th vn is always i + 1, guaranteed by face normal loop above.
+ * Both loop over the same polygon list.
+ */
+ for (int i = 0; i < d
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list