This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/alembic/intern/abc_util.h
Brecht Van Lommel fbb03f67ec Fix T63528: Alembic export always showing error on macOS, even on success
tellp() is not valid to check if the string stream is empty. Just get the
string directly as there is no obvious efficient method to check otherwise.
2019-04-25 03:46:11 +02:00

237 lines
6.8 KiB
C++

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup balembic
*/
#ifndef __ABC_UTIL_H__
#define __ABC_UTIL_H__
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
#ifdef _MSC_VER
# define ABC_INLINE static __forceinline
#else
# define ABC_INLINE static inline
#endif
/**
* \brief The CacheReader struct is only used for anonymous pointers,
* to interface between C and C++ code. This library only creates
* pointers to AbcObjectReader (or subclasses thereof).
*/
struct CacheReader {
int unused;
};
using Alembic::Abc::chrono_t;
class AbcObjectReader;
struct ImportSettings;
struct Base;
struct ID;
struct Object;
std::string get_id_name(const ID *const id);
std::string get_id_name(const Object *const ob);
std::string get_object_dag_path_name(const Object *const ob, Object *dupli_parent);
Imath::M44d convert_matrix(float mat[4][4]);
typedef enum {
ABC_MATRIX_WORLD = 1,
ABC_MATRIX_LOCAL = 2,
} AbcMatrixMode;
void create_transform_matrix(Object *obj,
float r_transform_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from);
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
template<class TContainer> bool begins_with(const TContainer &input, const TContainer &match)
{
return input.size() >= match.size() && std::equal(match.begin(), match.end(), input.begin());
}
void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]);
template<typename Schema>
void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max)
{
const Alembic::Abc::TimeSamplingPtr &time_samp = schema.getTimeSampling();
if (!schema.isConstant()) {
const size_t num_samps = schema.getNumSamples();
if (num_samps > 0) {
const chrono_t min_time = time_samp->getSampleTime(0);
min = std::min(min, min_time);
const chrono_t max_time = time_samp->getSampleTime(num_samps - 1);
max = std::max(max, max_time);
}
}
}
template<typename Schema>
void get_min_max_time(const Alembic::AbcGeom::IObject &object,
const Schema &schema,
chrono_t &min,
chrono_t &max)
{
get_min_max_time_ex(schema, min, max);
const Alembic::AbcGeom::IObject &parent = object.getParent();
if (parent.valid() && Alembic::AbcGeom::IXform::matches(parent.getMetaData())) {
Alembic::AbcGeom::IXform xform(parent, Alembic::AbcGeom::kWrapExisting);
get_min_max_time_ex(xform.getSchema(), min, max);
}
}
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name);
float get_weight_and_index(float time,
const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling,
int samples_number,
Alembic::AbcGeom::index_t &i0,
Alembic::AbcGeom::index_t &i1);
AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings);
/* ************************** */
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
* everything works properly, and also because Alembic is almost exclusively
* used in Y-up software, but eventually they'll be set by the user in the UI
* like other importers/exporters do, to support other axis. */
/* Copy from Y-up to Z-up. */
ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
const float old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
const short old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
/* Copy from Z-up to Y-up. */
ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
const float old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
const short old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
/* Names are given in (dst, src) order, just like
* the parameters of copy_m44_axis_swap() */
typedef enum {
ABC_ZUP_FROM_YUP = 1,
ABC_YUP_FROM_ZUP = 2,
} AbcAxisSwapMode;
/* Create a rotation matrix for each axis from euler angles.
* Euler angles are swapped to change coordinate system. */
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
float rot_z_mat[3][3],
const float euler[3],
AbcAxisSwapMode mode);
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode);
/* *************************** */
#undef ABC_DEBUG_TIME
class ScopeTimer {
const char *m_message;
double m_start;
public:
ScopeTimer(const char *message);
~ScopeTimer();
};
#ifdef ABC_DEBUG_TIME
# define SCOPE_TIMER(message) ScopeTimer prof(message)
#else
# define SCOPE_TIMER(message)
#endif
/* *************************** */
/**
* Utility class whose purpose is to more easily log related information. An
* instance of the SimpleLogger can be created in any context, and will hold a
* copy of all the strings passed to its output stream.
*
* Different instances of the class may be accessed from different threads,
* although accessing the same instance from different threads will lead to race
* conditions.
*/
class SimpleLogger {
std::ostringstream m_stream;
public:
/**
* Return a copy of the string contained in the SimpleLogger's stream.
*/
std::string str() const;
/**
* Remove the bits set on the SimpleLogger's stream and clear its string.
*/
void clear();
/**
* Return a reference to the SimpleLogger's stream, in order to e.g. push
* content into it.
*/
std::ostringstream &stream();
};
#define ABC_LOG(logger) logger.stream()
/**
* Pass the content of the logger's stream to the specified std::ostream.
*/
std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger);
#endif /* __ABC_UTIL_H__ */