// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "stdafx.h" #include #include #include namespace magma { template class simple_operator_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser& parser, std::vector& outExpr ) = 0; }; template class simple_operator_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser&, std::vector& outExpr ) { outExpr.push_back( new NodeType( node.id, node.get_connection( 0 ) ) ); } }; template class simple_operator_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser&, std::vector& outExpr ) { outExpr.push_back( new NodeType( node.id, node.get_connection( 0 ), node.get_connection( 1 ) ) ); } }; template class simple_operator_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser&, std::vector& outExpr ) { outExpr.push_back( new NodeType( node.id, node.get_connection( 0 ), node.get_connection( 1 ), node.get_connection( 2 ) ) ); } }; class curve_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser&, std::vector& outExpr ) { using namespace frantic::math; int inputs[] = { node.get_connection( 0 ) }; Value* pCurvePointsVal = node.get_property( 1 ); if( !is_array( pCurvePointsVal ) ) throw channel_compiler_error( node.id, "Invalid curve array" ); Array* pCurvePoints = static_cast( pCurvePointsVal ); if( pCurvePoints->size < 2 ) throw channel_compiler_error( node.id, "Expected at least two elements in curve array" ); std::vector> points; for( int i = 0; i < pCurvePoints->size; ++i ) { Value* pPointVal = pCurvePoints->get( 1 + i ); if( !is_array( pPointVal ) || static_cast( pPointVal )->size < 3 ) throw channel_compiler_error( node.id, "Invalid element " + boost::lexical_cast( i + 1 ) + " in curve array" ); Array* pPoint = static_cast( pPointVal ); bezier_curve_point cp; cp.position = frantic::max3d::from_max_t( pPoint->get( 1 + 0 )->to_point2() ); cp.inTan = frantic::max3d::from_max_t( pPoint->get( 1 + 1 )->to_point2() ); cp.outTan = frantic::max3d::from_max_t( pPoint->get( 1 + 2 )->to_point2() ); points.push_back( cp ); } outExpr.push_back( new frantic::channels::bezier_x_to_y_node( node.id, inputs[0], points ) ); } }; class transform_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser& parser, std::vector& outExpr ) { TimeValue t = SecToTicks( parser.get_scene_context().get_time() ); int inputs[] = { node.get_connection( 0 ) }; std::string operatorType = node.get_property( 0 ); std::string operandType = node.get_property( 1 ); frantic::graphics::transform4f tm; if( operatorType == "ToSpace" || operatorType == "FromSpace" ) { std::string transformNodeName = node.get_property( 2 ); // TODO: The scene context should probably expose a way to get at named objects, instead of going this // route. INode* pTMNode = GetCOREInterface()->GetINodeByName( frantic::strings::to_tstring( transformNodeName ).c_str() ); if( !pTMNode ) throw channel_compiler_error( node.id, "Could not find node by name: \"" + transformNodeName + "\"" ); tm = frantic::max3d::from_max_t( pTMNode->GetNodeTM( t ) ); if( operatorType.compare( 0, 2, "To" ) == 0 ) tm = tm.to_inverse(); } else if( operatorType == "ToWorld" || operatorType == "FromWorld" ) { INode* pBoundNode = parser.get_bound_inode(); if( !pBoundNode ) throw channel_compiler_error( node.id, "This operation is not supported in this context, since there is no node" ); tm = frantic::max3d::from_max_t( pBoundNode->GetNodeTM( t ) ); if( operatorType.compare( 0, 4, "From" ) == 0 ) tm = tm.to_inverse(); } else if( operatorType == "ToView" ) { tm = parser.get_scene_context().get_camera().world_transform_inverse(); } else if( operatorType == "FromView" ) { tm = parser.get_scene_context().get_camera().world_transform(); } if( operandType == "Point" ) { outExpr.push_back( new frantic::channels::transform_point_node( node.id, inputs[0], tm ) ); } else if( operandType == "Vector" ) { outExpr.push_back( new frantic::channels::transform_vector_node( node.id, inputs[0], tm ) ); } else if( operandType == "Normal" ) { outExpr.push_back( new frantic::channels::transform_normal_node( node.id, inputs[0], tm ) ); } else throw channel_compiler_error( node.id, "Unexpected transformation operand type: " + operandType ); } }; class surfacedata_factory : public parser_interface { public: virtual void apply( const base_node& node, magma_mxs_parser&, std::vector& outExpr ) { using frantic::channels::surf_data_value_node; int srcIndex[] = { node.get_connection( 0 ) }; std::string type = node.get_property( 1 ); surf_data_value_node::target_result rTarget = surf_data_value_node::RESULT_INVALID; if( type == "Position" ) { rTarget = surf_data_value_node::RESULT_POSITION; } else if( type == "SignedDistance" ) { rTarget = surf_data_value_node::RESULT_SIGNED_DIST; } else if( type == "FaceNormal" ) { rTarget = surf_data_value_node::RESULT_FACE_NORMAL; } else if( type == "SmoothNormal" ) { rTarget = surf_data_value_node::RESULT_SMOOTH_NORMAL; } else if( type == "MeshIndex" ) { rTarget = surf_data_value_node::RESULT_MESH_INDEX; } else if( type == "FaceIndex" ) { rTarget = surf_data_value_node::RESULT_FACE_INDEX; } else if( type == "FaceNormal" ) { rTarget = surf_data_value_node::RESULT_FACE_NORMAL; } else if( type == "FaceMatID" ) { rTarget = surf_data_value_node::RESULT_FACE_MAT_ID; } else if( type == "SmoothGroup" ) { rTarget = surf_data_value_node::RESULT_SMOOTH_GROUP; } else if( type == "BaryCoords" ) { rTarget = surf_data_value_node::RESULT_BARY_COORDS; } else if( type == "TextureCoord" ) { rTarget = surf_data_value_node::RESULT_TEXTURE_COORD; } else if( type == "Valid" ) { rTarget = surf_data_value_node::RESULT_INTERSECTED; } else throw channel_compiler_error( node.id, "Invalid surface data value target: \"" + type + "\"" ); outExpr.push_back( new surf_data_value_node( node.id, srcIndex[0], rTarget ) ); } }; void register_operator_parsers( std::map& outFactories ) { // Arithmetic Nodes outFactories["Add"] = new simple_operator_factory; outFactories["Subtract"] = new simple_operator_factory; outFactories["Multiply"] = new simple_operator_factory; outFactories["Divide"] = new simple_operator_factory; outFactories["Power"] = new simple_operator_factory; outFactories["SquareRoot"] = new simple_operator_factory; outFactories["Modulo"] = new simple_operator_factory; outFactories["AbsoluteValue"] = new simple_operator_factory; outFactories["Floor"] = new simple_operator_factory; outFactories["Ceil"] = new simple_operator_factory; outFactories["Negate"] = new simple_operator_factory; outFactories["Logarithm"] = new simple_operator_factory; // Function Nodes outFactories["Blend"] = new simple_operator_factory; outFactories["Clamp"] = new simple_operator_factory; outFactories["Curve"] = new curve_factory; outFactories["Noise"] = new simple_operator_factory; outFactories["DNoise"] = new simple_operator_factory; // Vector op Nodes outFactories["Normalize"] = new simple_operator_factory; outFactories["Magnitude"] = new simple_operator_factory; outFactories["ComponentSum"] = new simple_operator_factory; outFactories["DotProduct"] = new simple_operator_factory; outFactories["CrossProduct"] = new simple_operator_factory; // Trig Nodes outFactories["Sin"] = new simple_operator_factory; outFactories["Cos"] = new simple_operator_factory; outFactories["Tan"] = new simple_operator_factory; outFactories["ASin"] = new simple_operator_factory; outFactories["ACos"] = new simple_operator_factory; outFactories["ATan"] = new simple_operator_factory; outFactories["ATan2"] = new simple_operator_factory; // Convert Nodes outFactories["FromQuat"] = new simple_operator_factory; outFactories["ToQuat"] = new simple_operator_factory; outFactories["ToVector"] = new simple_operator_factory; outFactories["ToFloat"] = new simple_operator_factory, 1>; outFactories["ToInteger"] = new simple_operator_factory, 1>; outFactories["ToScalar"] = new simple_operator_factory; // Transformation Nodes outFactories["ToWorld"] = outFactories["FromWorld"] = outFactories["ToSpace"] = outFactories["FromSpace"] = outFactories["ToView"] = outFactories["FromView"] = new transform_factory; outFactories["TransformByQuat"] = new simple_operator_factory; // Surface Query Nodes outFactories["SurfDataValue"] = new surfacedata_factory; outFactories["RayIntersect"] = new simple_operator_factory; outFactories["NearestPoint"] = new simple_operator_factory; // Logic Nodes outFactories["Less"] = new simple_operator_factory; outFactories["LessOrEqual"] = new simple_operator_factory; outFactories["Greater"] = new simple_operator_factory; outFactories["GreaterOrEqual"] = new simple_operator_factory; outFactories["Equal"] = new simple_operator_factory; outFactories["LogicalAnd"] = new simple_operator_factory; outFactories["LogicalOr"] = new simple_operator_factory; outFactories["LogicalNot"] = new simple_operator_factory; outFactories["Switch"] = new simple_operator_factory; } } // namespace magma