> For the complete documentation index, see [llms.txt](https://on-premises.docs.hyper3d.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://on-premises.docs.hyper3d.ai/mesh-generation/rodin-mesh.md).

# Rodin Mesh

{% hint style="warning" %}
The request body should be wrapped in the **FormData** instead of plain JSON, while **settings** should be parsed to JSON.
{% endhint %}

{% hint style="info" %}
The image passed to the Rodin mesh endpoint must be segmented with an alpha channel. Otherwise, the image will need to be preprocessed with [image preprocessing API](/mesh-generation/rodin-mesh/image-preprocessing.md).
{% endhint %}

> 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 two `images` fields, each followed by the binary of one image.&#x20;
>
> Also, for settings, only params marked as `Mesh Generation Only` need to be passed through.

{% openapi src="/files/gJlKKDx0bj3wUm8btUfT" path="/api/task/rodin\_mesh" method="post" expanded="true" %}
[openapi3\_0 (5).json](https://4246159311-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJc2Olnfmy17B0BpCm82C%2Fuploads%2Fgit-blob-5050e1639ebc3dccc8449cfb5488b2a8e5510689%2Fopenapi3_0%20\(5\).json?alt=media)
{% endopenapi %}

### Examples

{% tabs %}
{% tab title="Go" %}

```python
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)
}

```

{% endtab %}
{% endtabs %}
