// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #ifndef MAX_RELEASE #error "You must include 3ds Max before including frantic/max3d/mesh.hpp" #endif #include #include #include // forward declares namespace frantic { namespace geometry { class trimesh3; class raytraced_geometry_collection; } // namespace geometry } // namespace frantic namespace frantic { namespace logging { class progress_logger; } } // namespace frantic namespace frantic { namespace max3d { namespace geometry { /** * get_normal_from_face: * Gets a normal from a face and vertex taking into account * multiple normals at vertices and smoothing groups. * * @param mesh * @param face * @param vertex * @return */ Point3 get_normal_from_face( Mesh& mesh, Face& face, int vertex ); /** * This deallocates all the data in a 3ds Max mesh. This has evolved over * time as it has been discovered that there are more and more pieces of * the mesh to clear separately. * * @param mesh The 3ds Max mesh to clear. */ void clear_mesh( Mesh& mesh ); /** * Copies the input Frantic trimesh3 object into the output * 3ds Max Mesh object. It copies some of the named vertex channels in the input channel * to the numbered vertex channels in the 3ds Max mesh, based on a naming convention. This * includes normal information in the form of smoothing groups if they are present, and if not, * directly saved normal information in a 'Normals' channel which will override max's creation * of normals. A null progress logger is used. *

* \todo We need to add support for additional channels, such as the vertex selection. * * @param dest The output 3ds Max Mesh class where the result is placed. * @param source The input trimesh3. */ void mesh_copy( Mesh& dest, const frantic::geometry::trimesh3& source ); /** * Copies the input Frantic trimesh3 object into the output * 3ds Max Mesh object. It copies some of the named vertex channels in the input channel * to the numbered vertex channels in the 3ds Max mesh, based on a naming convention. This * includes normal information in the form of smoothing groups if they are present, and if not, * directly saved normal information in a 'Normals' channel which will override max's creation * of normals. A progress logger is updated during vertex and face copying and vertex and face channel * copying. *

* \todo We need to add support for additional channels, such as the vertex selection. * * @param dest The output 3ds Max Mesh class where the result is placed. * @param source The input trimesh3. * @param progressLogger The object that accepts progress on this function */ void mesh_copy( Mesh& dest, const frantic::geometry::trimesh3& source, frantic::logging::progress_logger& progressLogger ); /** * Copies the input Frantic trimesh3 object into the output * 3ds Max Mesh object, using a time offset in seconds to move the * vertices based on the Velocity channel. This is used for getting * motion blur on meshes which change topology per frame, for example * when generated by marching cubes from a level set or a particle system. * A null progress logger is passed to the regular copy_mesh call. * * @param dest The output 3ds Max Mesh class where the result is placed. * @param source The input trimesh3. * @param timeOffset The time offset, used to move the vertices relative to their current * position, based on the Velocity channel of the input mesh. */ void mesh_copy_time_offset( Mesh& dest, const frantic::geometry::trimesh3& source, float timeOffset ); /** * Copies the input Frantic trimesh3 object into the output * 3ds Max Mesh object, using a time offset in seconds to move the * vertices based on the Velocity channel. This is used for getting * motion blur on meshes which change topology per frame, for example * when generated by marching cubes from a level set or a particle system. * A progress logger is passed to the regular copy_mesh call. * * @param dest The output 3ds Max Mesh class where the result is placed. * @param source The input trimesh3. * @param timeOffset The time offset, used to move the vertices relative to their current * position, based on the Velocity channel of the input mesh. */ void mesh_copy_time_offset( Mesh& dest, const frantic::geometry::trimesh3& source, float timeOffset, frantic::logging::progress_logger& progressLogger ); /** * append_inode_to_mesh: * TODO: make this support the various mesh map channels. Maybe ask if the TM should be used? * We should deprecate this function and delete it. The prefered method is to use mesh_copy followed by * trimesh3.combine. * * @param node * @param t * @param outValidity * @param mesh */ void append_inode_to_mesh( INode* node, TimeValue t, Interval& outValidity, frantic::geometry::trimesh3& mesh ); /** * append_inode_to_mesh * * @param node * @param t * @param mesh */ void append_inode_to_mesh( INode* node, TimeValue t, frantic::geometry::trimesh3& mesh ); /** * append_inodes_to_mesh * * @param begin * @param end * @param t * @param mesh */ template void append_inodes_to_mesh( Iterator begin, Iterator end, TimeValue t, frantic::geometry::trimesh3& mesh ) { for( Iterator it = begin; it != end; ++it ) append_inode_to_mesh( *it, t, mesh ); } /** * mesh_copy * Unfortunately, max isn't const-correct, so we can't use "const Mesh" * * @param dest * @param source * @param geometryOnly */ void mesh_copy( frantic::geometry::trimesh3& dest, Mesh& source, bool geometryOnly = false ); /** * mesh_copy * Unfortunately, max isn't const-correct, so we can't use "const Mesh" * * @param dest * @param source * @param cpp specify the mesh channels to copy */ void mesh_copy( frantic::geometry::trimesh3& dest, Mesh& source, const frantic::channels::channel_propagation_policy& cpp ); /** * mesh_copy: Copies a mesh with a transform applied * * @param dest * @param sourceXform * @param source * @param geometryOnly */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXform, Mesh& source, bool geometryOnly = false ); /** * mesh_copy: Copies a mesh with a transform applied * * @param dest * @param sourceXform * @param source * @param cpp specify the mesh channels to copy */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXform, Mesh& source, const frantic::channels::channel_propagation_policy& cpp ); /** * Copies a mesh, using the vertex motion caused by the two transforms to create a velocity channel. * * @param dest * @param sourceXformFirst * @param sourceXformSecond * @param source * @param timeStep * @param geometryOnly */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXformFirst, const frantic::graphics::transform4f& sourceXformSecond, Mesh& source, float timeStep, bool geometryOnly = false ); /** * Copies a mesh, using the vertex motion caused by the two transforms to create a velocity channel. * * @param dest * @param sourceXformFirst * @param sourceXformSecond * @param source * @param timeStep * @param cpp specify the mesh channels to copy */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXformFirst, const frantic::graphics::transform4f& sourceXformSecond, Mesh& source, float timeStep, const frantic::channels::channel_propagation_policy& cpp ); /** * This function takes two meshes and checks for consistent topology. Consistent topology, in this case, * is defined as equal vert and face counts, as well as corresponding faces in each mesh pointing to the * same verts, regardless of order. That means that this test is actually more strict about topology as it * doesn't account for rearranging of faces, which could happen and you could still get a mesh of equal * topology. * * @param sourceFirst the first mesh in the pair to be compared * @return sourceSecond the second mesh in the pair to be compared */ bool equal_topology( const Mesh& sourceFirst, const Mesh& sourceSecond ); bool equal_topology( const MNMesh& sourceFirst, const MNMesh& sourceSecond ); /** * Copies a mesh, using the vertex motion between the two transform/mesh pairs to create a velocity channel. * * @param dest * @param sourceXformFirst * @param sourceXformSecond * @param sourceFirst * @param sourceSecond * @param timeStep * @param geometryOnly */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXformFirst, const frantic::graphics::transform4f& sourceXformSecond, Mesh& sourceFirst, Mesh& sourceSecond, float timeStep, bool geometryOnly = false ); /** * Copies a mesh, using the vertex motion between the two transform/mesh pairs to create a velocity channel. * * @param dest * @param sourceXformFirst * @param sourceXformSecond * @param sourceFirst * @param sourceSecond * @param timeStep * @param cpp specify the mesh channels to copy */ void mesh_copy( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXformFirst, const frantic::graphics::transform4f& sourceXformSecond, Mesh& sourceFirst, Mesh& sourceSecond, float timeStep, const frantic::channels::channel_propagation_policy& cpp ); /** * Copies one of the 3ds Max map channels into the destination mesh. This * is primarily used for the texture baking, where a kd-tree is * then used to create a mapping from uv space into barycentric coordinates on the mesh. * * @param dest * @param source * @param sourceMapChannel */ void mesh_copy_mapchannel_to_mesh( frantic::geometry::trimesh3& dest, Mesh& source, int sourceMapChannel ); /** * Constructs a velocity channel by using a second sample of the 3ds Max mesh. Topology must match the existing mesh. * * @param dest The mesh to fill the velocity channel for * @param sourceXform The transform matrix that moves data from the source mesh into the same space as the destination * mesh. * @param source The mesh to use as a second time sample for finite differences. * @param timeStepSeconds The timestep between samples in units of seconds. * @return False if velocity could not be created because the topology of the two meshes does not match. */ bool mesh_copy_velocity_to_mesh( frantic::geometry::trimesh3& dest, const frantic::graphics::transform4f& sourceXform, Mesh& source, float timeStepSeconds ); /** * scale_mesh_verts * TODO: Deprecate and delete. * * @param mesh * @param scale */ void scale_mesh_verts( Mesh& mesh, float scale ); /** * write_mesh * TODO: Deprecate and delete. * * @param out * @param m */ void write_mesh( std::ostream& out, Mesh& m ); /** * interpolate_mesh * TODO: Deprecate and delete. Should do this in the world of trimesh3. * * @param dest * @param source1 * @param source2 * @param alpha */ void interpolate_mesh( Mesh& dest, Mesh& source1, Mesh& source2, float alpha ); /** * This function gets the u, v and w for a given map channel at a given vertex. * * @param mesh The mesh from which to get the UVW. * @param vert The vertex index for the UVW. * @param mapChannel The map channel from which to get the UVW. * @param outU The output U. * @param outV The output V. * @param outW The output W. */ void get_uvw( MNMesh& mesh, int vert, int mapChannel, float& outU, float& outV, float& outW ); /** * This function gets the u and v for a given vertex over all the channels supplied in the BitArray * Assumes the uvwArray is large enough to fit all channels supplied by mappingsRequired * * @param mesh * @param vert * @param mappingsRequired * @param uvwArray */ void get_multimap_uvws( MNMesh& mesh, int vert, BitArray& mappingsRequired, UVVert* uvwArray ); /** * This function estimates the derivatives dP/du and dP/dv for a given map channel at a given vertex. * * @param mesh * @param vert * @param mapChannel * @param outU * @param outV * @param outW * @param outdPdu * @param outdPdv */ void get_uvw_and_uv_derivatives( MNMesh& mesh, int vert, int mapChannel, float& outU, float& outV, float& outW, frantic::graphics::vector3f& outdPdu, frantic::graphics::vector3f& outdPdv ); /** * build_geometry_from_visible_inodes * * @param geometry * @param renderNodes * @param t * @param motionBlurInterval * @param shutterBias * @param geometryOnly * @param view * @param progress */ void build_geometry_from_visible_inodes( frantic::geometry::raytraced_geometry_collection& geometry, std::vector& renderNodes, TimeValue t, float motionBlurInterval, float shutterBias, bool geometryOnly, View& view, frantic::logging::progress_logger& progress ); /** * Takes a vector of INodes and returns a vector of INodes that are renderable. * The function is able to collect all the Events that have meshes from particle systems. * * @param inNodes * @param t * @param outRenderNodes */ void filter_renderable_inodes( const std::vector& inNodes, TimeValue t, std::vector& outRenderNodes ); /** * This gets the vertex angle and normal, given 3 points. The corner being computed is B. * * @param A * @param B * @param C * @param Nout * @return */ float get_face_corner_normal_and_angle( frantic::graphics::vector3f A, frantic::graphics::vector3f B, frantic::graphics::vector3f C, frantic::graphics::vector3f& Nout ); /** * This gets the normal and angle of a face corner in an MNMesh, expanding to using the triangle * until the angle is small enough to ensure we don't have a * bad localized normal. It's intended for use in computing smoothed normals of a mesh. * * @param mesh * @param mnface * @param corner * @param Nout * @return */ float get_mnmesh_face_corner_normal_and_angle( MNMesh* mesh, MNFace* mnface, int corner, frantic::graphics::vector3f& Nout ); /** * This finds a vertex in the given face which is convex in the polygon. This means * That the angle the "inside" part of the polygon makes at the vertex is at most 180 * degrees. * * @param mesh * @param mnface * @return */ int get_convex_vertex_index( MNMesh* mesh, MNFace* mnface ); /** * This fills a vector with smoothed normals for each vertex of the given mesh. * * @param mesh * @param outNormals */ void get_mnmesh_smoothed_normals( MNMesh* mesh, std::vector& outNormals ); /** * check_for_multiple_vertex_normals * For each face's vertex, check its number of normals and smoothing group * to see if there are any "folds" in the mesh which would require us to store * multiple normals per vertex. This info can be used for optimizations. * * @param mesh * @return */ bool check_for_multiple_vertex_normals( Mesh& mesh ); /** * check_for_differing_mapchannel_and_geom_verts * Given a Mesh object, Checks to see if the geometric vertices differ from * the givenmap channel vertices. This info can be used for optimization. * * @param mesh * @param channel * @return */ bool check_for_differing_mapchannel_and_geom_verts( Mesh& mesh, int channel ); /** * check_for_differing_mapchannel_and_geom_verts * Given a MNMesh object, Checks to see if the geometric vertices differ from * the givenmap channel vertices. This info can be used for optimization. * * @param mesh * @param channel * @return */ bool check_for_differing_mapchannel_and_geom_verts( MNMesh& mesh, int channel ); /** * build_mnmesh_normals * Given a reference to a Max MNMesh object and mesh name, this method sets the three output parameters listed below * * @param normals A vector of length numVerts. Vector contains maps that map the smoothing group to the * computed normal value for that group. * @param multiNormals Set to true if there are any verticies in the mesh that have multiple normals of * different smoothing groups (can be used to optimize mesh exports). * @param anySmoothing Set to false if the mesh is to be rendered completely faceted and without normals. */ void build_mnmesh_normals( MNMesh& mesh, std::vector>& normals, bool& multiNormals, bool& anySmoothing, bool alwaysExport = false ); /** * @return true if the VDATA_CREASE vertex data channel is supported in this * version of 3ds Max. * @note this is a workaround, to allow us to support a 3ds Max 2016 feature * in our combined 3ds Max 2015 + 2016 plugin build. */ bool is_vdata_crease_supported(); /** * @return the VDATA_CREASE channel number, if it is supported in this version * of 3ds Max. Otherwise throws an exception. */ int get_vdata_crease_channel(); /** * @param mapChannel 3ds Max map channel number. * @return the name we use internally for the mapChannel. For example, * 0 is "Color", and 1 is "TextureCoord". */ frantic::tstring get_map_channel_name( int mapChannel ); } // namespace geometry } // namespace max3d } // namespace frantic