# 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://on-premises.docs.hyper3d.ai/mesh-generation/rodin-mesh.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
