Rodin Mesh
The Rodin mesh function is designed to create 3D meshes from images based on specific prompts and settings.
The request body should be wrapped in the FormData instead of plain JSON, while settings should be parsed to JSON.
For the initial generation, images should also be wrapped in the FormData with each image binary appended under the field name
images
. For example, if there are two images, there should be twoimages
fields, each followed by the binary of one image.Also, for settings, only params marked as
Mesh Generation Only
need to be passed through.
Authorizations
Body
promptstring · max: 1024Required
group_uuidstring · uuidOptional
imagesstring · binary[]Required
Responses
201Success
application/json
post
POST /api/task/rodin_mesh HTTP/1.1
Host:
Authorization: Bearer JWT
Content-Type: multipart/form-data
Accept: */*
Content-Length: 1495
{
"prompt": "text",
"group_uuid": "123e4567-e89b-12d3-a456-426614174000",
"settings": [
{
"bbox_condition": [
1
],
"bbox_condition_cfg": true,
"bbox_condition_weight": 1,
"voxel_condition": "text",
"voxel_condition_cfg": true,
"voxel_condition_weight": 1,
"pcd_condition": [
[
1
]
],
"pcd_condition_cfg": true,
"pcd_condition_weight": 1,
"pcd_condition_uncertainty": 1,
"skeleton_condition": [
{
"name": "text",
"parent": 1,
"position": [
1
]
}
],
"skeleton_condition_cfg": true,
"skeleton_condition_weight": 1,
"view_weights": [
1
],
"image_label": [
"F"
],
"condition_mode": [
"fuse"
],
"generation_mode": [
"Fast"
],
"escore": 1,
"seed": 1,
"reference_scale": 1,
"fast_texture": true,
"inference_steps": 50,
"guidance_scale": 7.5,
"negative_prompt": "text",
"rest_bias": 0,
"sharp_bias": 0,
"image_mode": "recon",
"enable_advance_option": true,
"height": 1,
"face_enhance": true,
"allow_face_enhance": true,
"default_face_enhance": true,
"align_ground": true,
"mesh_export_type": "Quad",
"mesh_smooth": true,
"mesh_simplify": true,
"lineart_enable": true,
"lineart_weight": 1,
"quality_override": 1,
"resolution": "Basic",
"geometry": "Base",
"geometry_file_format": "glb",
"material": "PBR"
}
],
"conditions": [
{
"bbox_condition": [
1
],
"bbox_condition_cfg": true,
"bbox_condition_weight": 1,
"voxel_condition": "text",
"voxel_condition_cfg": true,
"voxel_condition_weight": 1,
"pcd_condition": [
[
1
]
],
"pcd_condition_cfg": true,
"pcd_condition_weight": 1,
"pcd_condition_uncertainty": 1,
"skeleton_condition": [
{
"name": "text",
"parent": 1,
"position": [
1
]
}
],
"skeleton_condition_cfg": true,
"skeleton_condition_weight": 1
}
],
"images": [
"binary"
]
}
201Success
{
"error": "NO_IMAGE_UPLOADED",
"uuid": "text",
"job": {
"uuids": [
[]
],
"subscription_key": "text"
}
}
Examples
package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"net/textproto"
"os"
)
const BASE_URL = "http://localhost:3005/api"
func rodinPreprocessImage(generatePrompt bool, image io.Reader, name string, token string) map[string]interface{} {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
generatePromptValue := "false"
if generatePrompt {
generatePromptValue = "true"
}
if err := writer.WriteField("generate_prompt", generatePromptValue); err != nil {
log.Fatal("Error writing field 'generate_prompt':", err)
}
part, err := writer.CreateFormFile("images", name)
if err != nil {
log.Fatal("Error creating form file:", err)
}
if _, err := io.Copy(part, image); err != nil {
log.Fatal("Error copying image data:", err)
}
if err := writer.Close(); err != nil {
log.Fatal("Error closing writer:", err)
}
req, err := http.NewRequest("POST", BASE_URL+"/task/rodin_mesh_image_process", body)
if err != nil {
log.Fatal("Error creating request:", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
response, err := client.Do(req)
if err != nil {
log.Fatal("Error sending request:", err)
}
defer response.Body.Close()
respBody, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal("Error reading response body:", err)
}
log.Println("Response Body:", string(respBody))
var result map[string]interface{}
if err := json.Unmarshal(respBody, &result); err != nil {
log.Fatal("Error unmarshaling response:", err)
}
return result
}
func rodinMesh(prompt string, groupUUID string, settings map[string]interface{}, images []io.Reader, name string, token string) map[string]interface{} {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("prompt", prompt)
writer.WriteField("group_uuid", groupUUID)
writer.WriteField("settings", toJSON(settings))
for _, img := range images {
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="images"; filename="%s"`, name))
h.Set("Content-Type", "image/png")
part, err := writer.CreatePart(h)
if err != nil {
log.Fatal("Error creating form part with MIME type:", err)
}
if _, err := io.Copy(part, img); err != nil {
log.Fatal("Error copying image data:", err)
}
}
if err := writer.Close(); err != nil {
log.Fatal("Error closing writer:", err)
}
req, err := http.NewRequest("POST", BASE_URL+"/task/rodin_mesh", body)
if err != nil {
log.Fatal("Error creating request:", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
response, err := client.Do(req)
if err != nil {
log.Fatal("Error sending request:", err)
}
defer response.Body.Close()
respBody, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal("Error reading response body:", err)
}
var result map[string]interface{}
if err := json.Unmarshal(respBody, &result); err != nil {
log.Fatal("Error unmarshaling response:", err)
}
return result
}
func convertBase64ToBinary(base64String string) *bytes.Reader {
data, err := base64.StdEncoding.DecodeString(base64String)
if err != nil {
log.Fatal("Error decoding base64 string:", err)
}
return bytes.NewReader(data)
}
func toJSON(data interface{}) string {
bytes, _ := json.Marshal(data)
return string(bytes)
}
func main() {
token := "eyJhbGciOiJIUzI1NiJ9.MSA1NDc1.J-zXs6y3aKS40eWB-iebtFiTUvG2M6ez3pREmTvjIXo"
imageName := "images.jpeg"
imageFile, err := os.Open(imageName)
if err != nil {
log.Fatal("Invalid image file.")
}
defer imageFile.Close()
preprocessResponse := rodinPreprocessImage(true, imageFile, imageName, token)
if errorVal, exists := preprocessResponse["error"]; exists && errorVal != nil {
log.Println("Error in image preprocessing:", errorVal)
return
}
prompt, ok := preprocessResponse["prompt"].(string)
if !ok {
prompt = "Default prompt if none returned"
}
processedImageBase64, ok := preprocessResponse["processed_image"].(string)
if !ok {
log.Println("Processed image is missing or not a string", prompt, preprocessResponse)
return
}
processedImage := processedImageBase64
log.Println("Data length:", len(processedImage))
settings := map[string]interface{}{"view_weights": []float64{1}}
log.Println(processedImage)
images := []io.Reader{convertBase64ToBinary(processedImage)}
for _, img := range images {
if byteReader, ok := img.(*bytes.Reader); ok {
log.Println("Image data length:", byteReader.Len())
if byteReader.Len() < 10 {
log.Println("Warning: Image data is too small, likely incorrect.")
}
}
}
log.Println("Images:", images)
meshResponse := rodinMesh(prompt, "", settings, images, imageName, token)
if errorVal, exists := meshResponse["error"]; exists && errorVal != nil {
log.Println("Error in Rodin mesh generation:", errorVal)
return
}
log.Println(meshResponse)
}
Last updated