tripo_api/tasks/
multiview_to_model.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::compress::CompressionMode;
9use crate::enums::{GeometryQuality, Orientation, TextureAlignment, TextureQuality};
10use crate::error::Result;
11use crate::image::ImageInput;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
16#[serde(deny_unknown_fields)]
17pub struct MultiviewToModelRequest {
18 #[serde(
20 rename = "files",
21 serialize_with = "serialize_files",
22 deserialize_with = "deserialize_files"
23 )]
24 pub images: Vec<Option<ImageInput>>,
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub model_version: Option<String>,
28 #[serde(skip_serializing_if = "Option::is_none")]
30 pub face_limit: Option<i32>,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub texture: Option<bool>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub pbr: Option<bool>,
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub model_seed: Option<i32>,
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub texture_seed: Option<i32>,
43 #[serde(skip_serializing_if = "Option::is_none")]
45 pub texture_quality: Option<TextureQuality>,
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub geometry_quality: Option<GeometryQuality>,
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub texture_alignment: Option<TextureAlignment>,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub auto_size: Option<bool>,
55 #[serde(skip_serializing_if = "Option::is_none")]
57 pub orientation: Option<Orientation>,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub quad: Option<bool>,
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub compress: Option<CompressionMode>,
64 #[serde(skip_serializing_if = "Option::is_none")]
66 pub generate_parts: Option<bool>,
67 #[serde(skip_serializing_if = "Option::is_none")]
69 pub smart_low_poly: Option<bool>,
70}
71
72impl MultiviewToModelRequest {
73 pub(crate) fn validate(&self) -> Result<()> {
74 super::validate_p1_params(
75 self.model_version.as_deref(),
76 self.quad,
77 self.smart_low_poly,
78 self.generate_parts,
79 self.geometry_quality.as_ref(),
80 )
81 }
82}
83
84fn serialize_files<S: Serializer>(v: &[Option<ImageInput>], s: S) -> Result<S::Ok, S::Error> {
85 use serde::ser::SerializeSeq;
86 let mut seq = s.serialize_seq(Some(v.len()))?;
87 for entry in v {
88 match entry {
89 Some(img) => seq.serialize_element(img)?,
90 None => seq.serialize_element(&serde_json::Value::Object(serde_json::Map::new()))?,
91 }
92 }
93 seq.end()
94}
95
96fn deserialize_files<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<Option<ImageInput>>, D::Error> {
97 let entries: Vec<serde_json::Value> = Vec::deserialize(d)?;
98 let mut out = Vec::with_capacity(entries.len());
99 for v in entries {
100 match &v {
101 serde_json::Value::Object(m) if m.is_empty() => out.push(None),
102 serde_json::Value::Null => out.push(None),
103 _ => {
104 let img: ImageInput =
105 serde_json::from_value(v).map_err(serde::de::Error::custom)?;
106 out.push(Some(img));
107 }
108 }
109 }
110 Ok(out)
111}