// (c) 2026 ANSYS, Inc. Unauthorized use, distribution, or duplication is prohibited.
syntax = "proto3";

package ansys.api.speos.simulation.v1.templates;

import "ansys/api/speos/sensor/v1/common.proto";

// The Weight represents the ray energy. In real life, a ray looses some energy (power) when it interacts with an object.
// Activating weight means that the Weight message is present.
// When weight is not activated, rays' energy stays constant and probability laws dictate if rays continue or stop propagating.
// When weight is activated, rays' energy evolves with interactions until rays reach the sensors.
// It is highly recommended to activate Weight, except in Interactive simulation.
// Not activating Weight is useful to understand certain phenomena as absorption.
message Weight {
	double minimum_energy_percentage = 1; // The Minimum energy percentage parameter defines the minimum energy ratio to continue to propagate a ray with weight. 1 = 100%.
}

// Default Colorimetric Standard
enum EnumColorimetricStandard {
	CIE_1931 = 0; // 2 degrees CIE Standard Colorimetric Observer Data.
	CIE_1964 = 1; // 10 degrees CIE Standard Colorimetric Observer Data.
}

// If texture has been applied in the scene, fill Texture message.
message Texture {
	TextureNormalization texture_normalization = 1; // Rendering of the texture.
	bool normal_map = 2; // To activate normal map.

	enum TextureNormalization {
		TEXTURE_NORMALIZATION_UNSPECIFIED = 0;
		TEXTURE_NORMALIZATION_NONE = 1; // The simulation result uses both the image texture and the texture mapping optical properties.
		TEXTURE_NORMALIZATION_COLOR_FROM_TEXTURE = 2; // The simulation result uses the color and the color lightness of the image texture.
		TEXTURE_NORMALIZATION_COLOR_FROM_BSDF = 3; // The simulation result uses the BSDF information of the texture mapping optical properties.
	}
}

message DirectMCSimulationTemplate {
	double geom_distance_tolerance = 2; // Maximum distance in mm to consider two faces as tangent
	int32 max_impact = 3; // To define a value to determine the maximum number of ray impacts during propagation. When a ray has interacted N times with the geometry, the propagation of the ray stops.
	Weight weight = 4; // To activate Weight. The Weight represents the ray energy. In real life, a ray looses some energy (power) when it interacts with an object.
	EnumColorimetricStandard colorimetric_standard = 5; // To define the Colorimetric Standard
	bool dispersion = 6; // To activate the dispersion calculation. 
	bool fast_transmission_gathering = 7; // To accelerate the simulation by neglecting the light refraction that occurs when the light is being transmitted through a transparent surface. 
	string ambient_material_uri = 8; // To select an ambient material *.material  
	Texture texture = 9; // To activate texture.
}

message InverseMCSimulationTemplate {
	double geom_distance_tolerance = 2; // Maximum distance in mm to consider two faces as tangent.
	int32 max_impact = 3; // To define a value to determine the maximum number of ray impacts during propagation. When a ray has interacted N times with the geometry, the propagation of the ray stops. 
	Weight weight = 4; // To activate Weight. The Weight represents the ray energy. In real life, a ray looses some energy (power) when it interacts with an object.
	EnumColorimetricStandard colorimetric_standard = 5; // To define the Colorimetric Standard 
	bool dispersion = 6; // To activate the dispersion calculation. 
	bool splitting = 7; // To split each propagated ray into several paths at their first impact after leaving the observer point.
	uint32 number_of_gathering_rays_per_source = 8; // This number pilots the number of shadow rays to target at each source.
	uint32 maximum_gathering_error = 9; // Deprecated - Better use maximum_gathering_error_percentage.
	double maximum_gathering_error_percentage = 12; // This value defines the level below which a source can be neglected. 0, the default value means that no approximation will be done. 
	bool fast_transmission_gathering = 10; // To accelerate the simulation by neglecting the light refraction that occurs when the light is being transmitted through a transparent surface.
	string ambient_material_uri = 11; // To select an ambient material *.material
	Texture texture = 13; // To activate texture.
}

// Simulation template with its basic characteristics
message SimulationTemplate {
	string name = 3; // Simulation name
	string description = 4; // Simulation description
	map<string, string> metadata = 7; // User defined metadata
	oneof simulation_template {
		DirectMCSimulationTemplate direct_mc_simulation_template = 1;
		InverseMCSimulationTemplate inverse_mc_simulation_template = 2;
		Interactive interactive_simulation_template = 5;
		VirtualBSDFBench virtual_bsdf_bench_simulation_template = 6;
	}

	message Interactive {
		double geom_distance_tolerance = 1; // Maximum distance in mm to consider two faces as tangent.
		int32 max_impact = 2; // Defines a value to determine the maximum number of ray impacts during propagation. When a ray has interacted N times with the geometry, the propagation of the ray stops.
		Weight weight = 3; // Activates Weight. Highly recommended to fill
		EnumColorimetricStandard colorimetric_standard = 4; // Default Colorimetric Standard
		string ambient_material_uri = 5; // To define the environment in which the light will propagate (water, fog, smoke etc.). It is expressed in a .material file
		Texture texture = 6; // To activate texture.
	}

	// Virtual BSDF Bench
	message VirtualBSDFBench {
		double geom_distance_tolerance = 2; // Maximum distance in mm to consider two faces as tangent.
		int32 max_impact = 3; // Defines a value to determine the maximum number of ray impacts during propagation. When a ray has interacted N times with the geometry, the propagation of the ray stops.
		Weight weight = 4; // Activates Weight. It is highly recommended to activate.
		EnumColorimetricStandard colorimetric_standard = 5; // Default Colorimetric Standard
		Texture texture = 6; // Activates texture.
		
		oneof mode {
			RoughnessOnly roughness_only = 9; // BSDF depends on surface roughness only
			AllCharacteristics all_characteristics = 10; // BSDF depends on all properties
		}

		ansys.api.speos.sensor.v1.WavelengthsRange wavelengths_range = 11; // 
		Sensor sensor = 12; // Sensor definition

		message SourceSamplingUniformIsotropic{
			uint32 theta_sampling = 1; // Number of samples created along the polar angle Theta (around the normal Z-axis) in the range [0,90] degrees, with a minimum value of 2 degrees. Each sample represents the position of the source on Theta.
		}
		message SourceSamplingUniformAnisotropic{
			uint32 theta_sampling = 1; // Number of samples created along the polar angle Theta (around the normal Z-axis) in the range [0,90] degrees, with a minimum value of 2 degrees. Each sample represents the position of the source on Theta.
			uint32 phi_sampling = 2; // Number of samples created along the azimuthal angle Phi (around the X-axis). Each sample represents the position of the source on Phi.
			PhiSymmetry symmetry_type = 3; // Define symmetry type. Not needed if there is no symmetry in measure.

			enum PhiSymmetry {
				PHI_SYMMETRY_UNSPECIFIED = 0;
				PHI_SYMMETRY_NONE = 1;
				PHI_SYMMETRY_1_PLANE = 2; // Symmetry to plane 0 - 180
				PHI_SYMMETRY_2_PLANES = 3; // Symmetry to planes 0 - 180 and 90 - 270 
			}
		}
		message SourceSamplingAdaptive{
			string file_uri = 1; // uri of incident sampling file
		}

		message Sensor{
			double integration_angle = 1;
			oneof sampling_mode{
				SensorSamplingUniform uniform = 2;
				SensorSamplingAutomatic automatic = 3;
			}

			message SensorSamplingUniform{
				uint32 theta_sampling = 1; // Number of samples created along the polar angle Theta (around the normal Z-axis) in the range [0,90] degrees. Each sample represents the position of the sensor on Theta.
				uint32 phi_sampling = 2; // Number of samples created along the azimuthal angle Phi (around the X-axis). Each sample represents the position of the sensor on Phi.
			}

			message SensorSamplingAutomatic{
			}
		}

		message RoughnessOnly{
			oneof source_sampling{
				SourceSamplingUniformIsotropic uniform_isotropic = 1; // oneof with adaptive
				SourceSamplingAdaptive adaptive = 2;
			}
		} 

		message AllCharacteristics{	
			bool is_bsdf180 = 1; // Corresponds to the parameter "BSDF depends on light incidence side". When set to true, the Theta sampling for the source is defined on [0,180] instead of [0,90].
			oneof iridescence_mode{
				Iridescence iridescence = 2; // Color depends on viewing direction
				NoIridescence no_iridescence = 3; // Color does not depend on viewing direction
			}
			bool sensor_reflection_and_transmission = 4; // When set to true, it measures the reflection and transmission (theta in [0,180]). When set to false, it measures the reflection only (theta in [0,90]).
			message Iridescence{
				oneof source_sampling {
					SourceSamplingUniformIsotropic uniform_isotropic = 1;
					SourceSamplingAdaptive adaptive = 2;
				}
			}

			message NoIridescence{
				oneof surface_type{
					Isotropic isotropic = 1;
					Anisotropic anisotropic = 2;
				}

				message Isotropic{
					oneof source_sampling {
						SourceSamplingUniformIsotropic uniform_isotropic = 1;
						SourceSamplingAdaptive adaptive = 2;
					}
				}

				message Anisotropic{
					oneof source_sampling {
						SourceSamplingUniformAnisotropic uniform_anisotropic = 1;
						SourceSamplingAdaptive adaptive = 2;
					}
				}
			}
		}
	}
}

service SimulationTemplatesManager {
	// Create a SimulationTemplate
	rpc Create(Create_Request) returns (Create_Response) {}
	// Read a SimulationTemplate
	rpc Read(Read_Request) returns (Read_Response) {}
	// Update a SimulationTemplate
	rpc Update(Update_Request) returns (Update_Response) {}
	// Delete a SimulationTemplate
	rpc Delete(Delete_Request) returns (Delete_Response) {}
	// List all SimulationTemplates in manager
	rpc List(List_Request) returns (List_Response) {}
}

// Request to create a SimulationTemplate in SimulationTemplatesManager
message Create_Request {
	SimulationTemplate simulation_template = 1; // SimulationTemplate containing its basic characteristics
	optional string guid = 2; // Optional field to specify the guid used in the database. If not set, a unique guid will be generated for that entry and sent back in the Create_Response.
}
message Create_Response {
	string guid = 1; // Guid of the SimulationTemplate created in SimulationTemplatesManager
}
// Request to read a SimulationTemplate in SimulationTemplatesManager
message Read_Request {
	string guid = 1; // Guid of the SimulationTemplate to be read
}
message Read_Response {
	SimulationTemplate simulation_template = 1; // SimulationTemplate corresponding to the guid given in Read_Request
}
// Request to update a SimulationTemplate in SimulationTemplatesManager
message Update_Request {
	string guid = 1; // Guid of the SimulationTemplate to be updated
	SimulationTemplate simulation_template = 2; // SimulationTemplate that will be used for the update
}
message Update_Response {
}
// Request to delete a SimulationTemplate in SimulationTemplatesManager
message Delete_Request {
	string guid = 1; // Guid of the SimulationTemplate to be deleted
}
message Delete_Response {}

message List_Request {
}
message List_Response {
	repeated string guids = 1; // Guids of the SimulationTemplates in SimulationTemplatesManager
}
