// (c) 2025 ANSYS, Inc. Unauthorized use, distribution, or duplication is prohibited. ANSYS Confidential Information
syntax = "proto3";
import "ansys/api/speos/results/v1/ray_path.proto";

package ansys.api.speos.scene.v2;

// Optical scene definition made of parts, optical properties, sources, sensors and simulations
message Scene
{
	// Geometry path of object that will include the specific property (can be sub-scene/part/body/face). 
	// geo_path in the format : "<sub-scene name>/<part name>/<body name>/<face name>" (no name by default for root scene and root part).
	// "body0" -> body0 of the root part in the root scene
	// "body0/face0" -> face0 in body0 of the root part in the root scene
	// "part1" -> part1 of the root part in the root scene
	// "part1/body1/face1" -> face1 in body1 in part1 of the root part in the root scene
	// "subScene1" -> root part in the sub scene subScene1
	// "subScene1/part2" -> part2 of the sub scene subScene1
	// Particularities:
	// If the object GeoPaths is defined and geo_paths left empty, this means "All geometry selected".
	// If the object GeoPaths is NOT defined, this means "No geometry selected".
	message GeoPaths
	{
		repeated string geo_paths = 1; // list of geo paths
	}

	message GeoPath {
		string geo_path = 1; // Geometry that will be used ("<body name>" for a whole body, or "<body name>/<face name>" for a specific face) 
		optional bool reverse_normal = 2; // optional - if not set or false : normal is not reversed.
	}

	// Instance of a Material to apply on geometries of the scene
	message MaterialInstance
	{
		message NonHomogeneousProperties {
			repeated double axis_system = 1; // Position of the non homogeneous vop (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
		}

		string name = 1;
		string description = 2;
		map<string, string> metadata = 3; // User defined metadata
		optional string vop_guid = 10; // optional - Guid of the volume optical property to instantiate
		oneof vop_properties {
			NonHomogeneousProperties non_homogeneous_properties = 15; // To be filled if the vop_guid corresponds to a VOPTemplate of type NonHomogeneous
		}
		repeated string sop_guids = 11; // Guid(s) of the surface optical property(ies) to instantiate
		GeoPaths geometries = 12; // Geometries that will use this material
	}

	// Instance of a source to add in the scene
	message SourceInstance
	{
		message IntensityProperties {
			message LibraryProperties {
				message AxisSystem {
					repeated double values = 1; // orientation (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz)
				}
				// Define the intensity distribution as normal to the selected surface.
				message NormalToSurface {}
				// Define the intensity distribution as normal to the selected emissive surface and its orientation on the emissive surface.
				message NormalToUVMap {}

				GeoPaths exit_geometries = 1; // Exit Geometries that will use this surface source 
				// Orientation of the source intensity distribution
				oneof orientation {
					AxisSystem axis_system = 2; // orientation (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
					NormalToSurface normal_to_surface = 3; // Define the intensity distribution as normal to the selected surface.
					NormalToUVMap normal_to_uv_map = 4; // Define the intensity distribution as normal to the selected emissive surface and its orientation on the emissive surface.
				}
			}

			message GaussianProperties {
			    repeated double axis_system = 1; // optional - orientation of the intensity distribution (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz) - if not filled : normal to surface map. If the coordinate system is not orthonormal, it will be automatically orthonormalized
			}

			oneof properties {
				LibraryProperties library_properties = 1; // To be filled if the intensity_guid of the source template corresponds to an IntensityTemplate of type Library
				GaussianProperties gaussian_properties = 2; // To be filled if the intensity_guid of the source template corresponds to an IntensityTemplate of type Gaussian
			}
		}
		message LuminaireProperties{
			repeated double axis_system = 1; // Position of the source (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
		}
		message SurfaceProperties{
			message ExitanceConstantProperties {
				repeated GeoPath geo_paths = 1;
			}
			message ExitanceVariableProperties {
				repeated double axis_plane = 1; // Position of the exitance map (Ox Oy Oz Xx Xy Xz Yx Yy Yz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			}

			oneof exitanceProperties {
				ExitanceConstantProperties exitance_constant_properties = 1; // To be filled if the Surface SourceTemplate has ExitanceConstant 
				ExitanceVariableProperties exitance_variable_properties = 2; // To be filled if the Surface SourceTemplate has ExitanceVariable 
			}
			IntensityProperties intensity_properties = 3;
		}
	message ThermicProperties{
			oneof exitanceProperties{
				EmissiveFacesProperties emissive_faces_properties = 1; // source emits from faces
				TemperatureFieldProperties temperature_field_properties = 2; // a specific OPTTemperature file is required (mesh + triangle temperature in Kelvin)
			}

			message EmissiveFacesProperties{
				repeated GeoPath geo_paths = 1; // the list of emitting faces of the source 
			}

			message TemperatureFieldProperties{
				repeated double axis_plane = 1; // Position of the exitance map (Ox Oy Oz Xx Xy Xz Yx Yy Yz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			}
		}
		message RayFileProperties{
			repeated double axis_system = 1; // Position of the source (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz)
			GeoPaths exit_geometries = 2; // Exit Geometries that will use this rayfile source 
		}
		message DisplayProperties{
			repeated double axis_system = 1; // Position of the source (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			IntensityProperties intensity_properties = 3;
		}

		message AmbientProperties {
			repeated double zenith_direction = 1; // line normal to the ground or Z direction
			bool reverse_zenith = 2;  // optional - if not set or false : normal is not reversed
			oneof source_properties { // Type of Ambient Sources
				UniformAmbientProperties uniform_ambient_properties = 10;
				CieOvercastProperties cie_overcast_properties = 11;
				CieGeneralProperties cie_general_properties = 12;
				NaturalLightProperties natural_light_properties = 13;
				UsStandardProperties us_standard_properties = 14;
				EnvironmentMapProperties environment_map_properties = 15;
			}

			message ManualSun {
				repeated double sun_direction = 1; // (X Y Z) direction to the sun
				bool reverse_sun = 2;  // optional - if not set or false : normal is not reversed
			}
			
			message SunAxisSystem {
				oneof sun_type {
					AutomaticSun automatic_sun = 1; // calculates the sun position according to the north direction and time zone location set
					ManualSun manual_sun = 2; // sets the sun position and direction from scene
				}
				message AutomaticSun {
					string time_zone_uri = 1; 
					int32 year = 2; 
					int32 month = 3;
					int32 day = 4;
					int32 hour = 5;
					int32 minute = 6;
					float longitude = 7;
					float latitude = 8;
				}
			}
			message UniformAmbientProperties {
				ManualSun manual_sun = 1; // sets the sun position and direction from scene
			}
			message CieOvercastProperties {}
			message CieGeneralProperties {
				repeated double north_direction = 1; // (X Y Z) Direction to the North
				bool reverse_north = 2;  // optional - if not set or false : normal is not reversed
				SunAxisSystem sun_axis_system = 3; // Set the Sun direction
			}
			message NaturalLightProperties {
				repeated double north_direction = 1; // (X Y Z) Direction to the North
				bool reverse_north = 2;  // optional - if not set or false : normal is not reversed
				SunAxisSystem sun_axis_system = 3; // Set the Sun direction
			}
			message UsStandardProperties {
				repeated double north_direction = 1; // (X Y Z) Direction to the North
				bool reverse_north = 2;  // optional - if not set or false : normal is not reversed
				SunAxisSystem sun_axis_system = 3; // Set the Sun direction
			}
			message EnvironmentMapProperties {
				repeated double north_direction = 1; // (X Y Z) Direction to the North
				bool reverse_north = 2;  // optional - if not set or false : normal is not reversed
			}
		}

		string name = 1;
		string description = 2;
		map<string, string> metadata = 3; // User defined metadata
		string source_guid = 10; // Guid of the SourceTemplate in SourceTemplatesManager to instantiate
		oneof properties {
			LuminaireProperties luminaire_properties = 11; // To be filled if the source_guid corresponds to a SourceTemplate of type Luminaire
			SurfaceProperties surface_properties = 12; // To be filled if the source_guid corresponds to a SourceTemplate of type Surface
			RayFileProperties rayfile_properties = 13; // To be filled if the source_guid corresponds to a SourceTemplate of type RayFile
			ThermicProperties thermic_properties = 14; // To be filled if the source_guid corresponds to a SourceTemplate of type Thermic Source
			DisplayProperties display_properties = 15; // To be filled if the source_guid corresponds to a SourceTemplate of type Display
			AmbientProperties ambient_properties = 16; // To be filled if the source_guid corresponds to a SourceTemplate of type Ambient
		}
	}

	// Instance of a sensor to add in the scene
	message SensorInstance
	{
		// Ray file types available
		enum EnumRayFileType {
			RayFileNone = 0; // Generates no ray file.
			RayFileClassic = 1; // Generates a ray file without polarization data.
			RayFilePolarization = 2; // Generates a ray file with the polarization data for each ray.
			RayFileTM25 = 3; // Generates a .tm25ray file with polarization data for each ray.
			RayFileTM25NoPolarization = 4; // Generates a .tm25ray file without polarization data.
		}

		// Includes the simulation's results in one layer.
		message LayerTypeNone {}
		// Includes one layer per active source in the result.
		message LayerTypeSource {}
		// Includes one layer per surface selected in the result.
		message LayerTypeFace {
			enum EnumSCAFilteringType {
				LastImpact = 0;
				IntersectedOneTime = 1;
			}
			message Layer {
				string name = 1; // Name of the layer 
				GeoPaths geometries = 2; // Surface selected.
			}

			EnumSCAFilteringType sca_filtering_mode = 1;
			repeated Layer layers = 2; // Layers that will be taken into account in the result.
		}
		// Includes one layer per sequence in the result.
		message LayerTypeSequence {
			enum EnumSequenceType {
				Geometries = 0;
				Faces = 1;
			}

			uint32 maximum_nb_of_sequence = 1;
			EnumSequenceType define_sequence_per = 2;
		}
		// Includes one layer per Stokes parameter using the polarization parameter.
		message LayerTypePolarization {}
		// Includes one layer per range of incident angles.
		message LayerTypeIncidenceAngle {
			uint32 sampling = 1;
		}

		message CameraProperties {
			repeated double axis_system = 1; // Position of the sensor (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			string trajectory_file_uri = 2; // Trajectory file, used to define the positions and orientations of the Camera sensor in time.
			oneof layer_type {
				LayerTypeNone layer_type_none = 3; // Layer type : None
				LayerTypeSource layer_type_source = 4; // Layer type : Source
			}
		}
		message IrradianceProperties {
			repeated double axis_system = 1; // Position of the sensor (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			EnumRayFileType ray_file_type = 2; // Choose type of ray file generated after the simulation.
			oneof layer_type {
				LayerTypeNone layer_type_none = 3; // Layer type : None
				LayerTypeSource layer_type_source = 4; // Layer type : Source
				LayerTypeFace layer_type_face = 5; // Layer type : Face
				LayerTypeSequence layer_type_sequence = 6; // Layer type : Sequence
				LayerTypePolarization layer_type_polarization = 7; // Layer type : Polarization
				LayerTypeIncidenceAngle layer_type_incidence_angle = 8; // Layer type : Incidence angle
			}
			repeated double integration_direction = 9; // Sensor global integration direction [x,y,z], optional (default direction is Z axis of axis_system). Note: Contrary to any visualization of integration directions within Speos Software or its documentation the integration direction must be set in the anti-rays direction to integrate their signal. Integration direction is only settable for sensor template with IlluminanceTypePlanar or IlluminanceTypeSemiCylindrical as illuminance_type.
			GeoPaths output_face_geometries = 10; // List of output faces for inverse simulation optimization
		}
		message RadianceProperties {
			repeated double axis_system = 1; // Position of the sensor (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			repeated double observer_point = 2; // Position of the observer point (Ox Oy Oz), optional (default: focal length is used)
			oneof layer_type {
				LayerTypeNone layer_type_none = 3; // Layer type : None
				LayerTypeSource layer_type_source = 4; // Layer type : Source
				LayerTypeFace layer_type_face = 5; // Layer type : Face
				LayerTypeSequence layer_type_sequence = 6; // Layer type : Sequence								
			}
		}
		message LXPProperties {
			uint32 nb_max_paths = 1; // The Maximum paths corresponds to the maximum number of rays the Light Expert file (*.lpf or *.lp3) can contain.
		}
		
		message IntensityProperties {
			repeated double axis_system = 1; // Position of the sensor (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
			oneof layer_type {
				LayerTypeNone layer_type_none = 3; // Layer type: None
				LayerTypeSource layer_type_source = 4; // Layer type: Source
				LayerTypeFace layer_type_face = 5; // Layer type: Face
				LayerTypeSequence layer_type_sequence = 6; // Layer type: Sequence
			}			
		}
		message PolarIntensityProperties {
			repeated double axis_system = 1; // Position of the sensor (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized					
		}

		message Irradiance3DProperties {
			EnumRayFileType ray_file_type = 1; // Choose type of ray file generated after the simulation.
			oneof layer_type {
				LayerTypeNone layer_type_none = 2; // Layer type : None
				LayerTypeSource layer_type_source = 3; // Layer type : Source
			}
			GeoPaths geometries = 4; // Geometries that will use this sensor
		}

		string name = 1;
		string description = 2;
		map<string, string> metadata = 3; // User defined metadata
		string sensor_guid = 10; // Guid of the SensorTemplate in SensorTemplatesManager to instantiate
		string result_file_name = 11; // Result file name without extention. Result files of the sensor will be based on this name.
		oneof properties {
			CameraProperties camera_properties = 12; // To be filled if the sensor_guid corresponds to a SensorTemplate of type CameraSensorTemplate
			IrradianceProperties irradiance_properties = 13; // To be filled if the sensor_guid corresponds to a SensorTemplate of type IrradianceSensorTemplate
			RadianceProperties radiance_properties = 14; // To be filled if the sensor_guid corresponds to a SensorTemplate of type SensorTemplate::Radiance
			IntensityProperties intensity_properties = 15; // To be filled if the sensor_guid corresponds to a SensorTemplate of type IntensitySensorTemplate
			PolarIntensityProperties polar_intensity_properties = 16; // To be filled if the sensor_guid corresponds to a SensorTemplate of type PolarIntensitySensorTemplate	
			Irradiance3DProperties irradiance_3d_properties = 17; // To be filled if the sensor_guid corresponds to a SensorTemplate of type SensorTemplate::Irradiance3D
		}
		LXPProperties lxp_properties = 30; // To activate lxp feature, we must fill this field
	}

	// Instance of a simulation to add in the scene
	message SimulationInstance
	{
		string name = 1;
		string description = 2;
		map<string, string> metadata = 3; // User defined metadata
		string simulation_guid = 10; // Guid of the element to instantiate
		repeated string sensor_paths = 11; // Sensors that this simulation will include (empty for no sensor, [""] for all sensors, "<sensor name>" for a specific sensor in the current scene, or "<scene name>/<sensor name>" for a specific sensor in a specific sub scene)
		repeated string source_paths = 12; // Sources that this simulation will include (empty for no source, [""] for all sources, "<source name>" for a specific source in the current scene, or "<scene name>/<source name>" for a specific source in a specific sub scene)
		GeoPaths geometries = 13; // Geometries that this simulation will include - Not yet functional (All geometries are included by default in each simulation)
	}

	message SceneInstance
	{
		string name = 1;
		string description = 2;
		map<string, string> metadata = 3; // User defined metadata
		string scene_guid = 10; // Guid of the element to instantiate
		repeated double axis_system = 11; // Scene position relative to parent PartTemplate reference (Ox Oy Oz Xx Xy Xz Yx Yy Yz Zx Zy Zz). If the coordinate system is not orthonormal, it will be automatically orthonormalized
	}

	message GroundPlane
	{
		repeated double ground_origin = 1; // 3D point in the geometry. HDR image is displayed on the ground plane
		repeated double zenith_direction = 2; // line normal to the ground or Z direction
		double ground_height = 3; // height of the environment shooting (unit mm)
	}

	string name = 1;
	string description = 2;
	map<string, string> metadata = 3; // User defined metadata

	string part_guid = 10; // Guid from PartsManager of the geometrical part included inside the scene
	
	repeated SourceInstance sources = 13; // The sources added in the scene
	repeated SensorInstance sensors = 14; // The sensors added in the scene
	repeated SimulationInstance simulations = 15; // The simulations added in the scene
	repeated MaterialInstance materials = 16; // The materials (volume + surface) applied on geometries
	repeated SceneInstance scenes = 20; // Sub scenes
	GroundPlane ground = 21; // Optional - Only usable when there is at least one Ambient Environment Source Template that has selected a HDR image file. 
}

// Manager for Scenes
service ScenesManager {
	// Create a Scene
	rpc Create(Create_Request) returns (Create_Response) {}
	// Read a Scene
	rpc Read(Read_Request) returns (Read_Response) {}
	// Update a Scene
	rpc Update(Update_Request) returns (Update_Response) {}
	// Delete a Scene
	rpc Delete(Delete_Request) returns (Delete_Response) {}
	// List all Scenes in manager
	rpc List(List_Request) returns (List_Response) {}
}

// Request to create a Scene in ScenesManager
message Create_Request {
	Scene scene = 1;
}
message Create_Response {
	string guid = 1; // Guid of the Scene created in ScenesManager
}

// Request to read a Scene in ScenesManager
message Read_Request {
	string guid = 1; // Guid of the Scene to be read
}
message Read_Response {
	Scene scene = 1; // Scene corresponding to the guid given in Read_Request
}

// Request to update a Scene in ScenesManager
message Update_Request {
	string guid = 1; // Guid of the Scene to be updated
	Scene scene = 2; // Scene that will be used for the update
}
message Update_Response {}

// Request to delete a Scene in ScenesManager
message Delete_Request {
	string guid = 1; // Guid of the Scene to be deleted
}
message Delete_Response {}

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

// Actions available on a Scene
service SceneActions {
	// Load .speos file
	rpc LoadFile(LoadFile_Request) returns (LoadFile_Response) {} 
	// Save .speos file
	rpc SaveFile(SaveFile_Request) returns (SaveFile_Response) {} 
	// Get RayPaths generated by a source
	rpc GetSourceRayPaths(GetSourceRayPaths_Request) returns (stream ansys.api.speos.results.v1.RayPath) {}
}

// Request to LoadFile service
message LoadFile_Request {
	string guid = 1; // Guid of a ScenesManager element to update
    string file_uri = 2; // File uri (path or guid from FileTransferService) 
}
// Response to LoadFile service
message LoadFile_Response {
}

// Request to SaveFile service
message SaveFile_Request {
    string guid = 1; // Guid of a ScenesManager element to save
    string file_uri = 2; // File uri (path or guid from FileTransferService) 
}
// Response to SaveFile service
message SaveFile_Response {
}

message GetSourceRayPaths_Request {
	string guid = 1; // Guid of a ScenesManager element
	string source_path = 2; // path to the source in the Scene : "<source name>" for a specific source in the current scene, or "<scene name>/<source name>" for a specific source in a specific sub scene
	optional uint32 rays_nb = 3; // Number of rays sent by the source. Default 100
	optional bool raw_data = 4; // Boolean to get the wavelengths in response stream
	optional bool display_data = 5; // Boolean to get the colors (RGB24 format) in response stream
}