syntax = "proto3";

package mujoco_js;

// A point or scalar value in 3d space.
message Vector3 {
  float x = 1;
  float y = 2;
  float z = 3;
}

// Prevents motion or rotation along specifed axes.
message Frozen {
  // Freeze motion along the x, y, or z axes.
  Vector3 position = 1;
  // Freeze rotation around the x, y, or z axes.
  Vector3 rotation = 2;
  // Override all the position and rotation fields, setting them to 1.
  bool all = 3;
}

// Bodies have a rigid shape, mass, and rotational inertia. Bodies may connect
// to other bodies via joints, forming a kinematic tree.
message Body {
  // Unique name for this body
  string name = 1;
  // Geometric primitives that define the shape of the body
  repeated Collider colliders = 2;
  // Prevents motion or rotation along specified axes for this body.
  Frozen frozen = 3;
}

// Primitive shape that composes the collision surface of a body.
message Collider {
  // A 6-sided rectangular prism
  message Box {
    // Half the size of the box in each dimension.
    Vector3 halfsize = 1;
  }
  // An infinite plane with normal vector (0, 0, 1)
  message Plane {}
  // A sphere
  message Sphere {
    float radius = 1;
  }
  // A cylinder with rounded ends.
  message Capsule {
    // Radius of the sphere at each rounded end
    float radius = 1;
    // End-to-end length of the capsule
    float length = 2;
    // Capsule end (0: both ends, 1: top end, -1: bottom end)
    int32 end = 3;
  }
  // A height map aligned with the x-y plane
  message HeightMap {
    // The width and length of the square height map.
    float size = 1;
    // A flattened square matrix of the height data in row major order where
    // the row index is the x-position and the column index is the y-position.
    repeated float data = 2;
  }
  // A mesh. Currently, only mesh-plane and mesh-capsule collisions are
  // supported.
  message Mesh {
    // Name of the mesh geometry defined in the config.
    string name = 1;
    // Scaling for the mesh.
    float scale = 2;
  }
  // Position relative to parent body
  Vector3 position = 1;
  // Rotation relative to parent body
  Vector3 rotation = 2;
  // A collider may only be one type
  oneof type {
    Box box = 3;
    Plane plane = 4;
    Sphere sphere = 5;
    Capsule capsule = 6;
    HeightMap heightMap = 7;
    Mesh mesh = 8;
  }
  // Color of the collider in css notation (e.g. '#ff0000' or 'red')
  string color = 9;
  // A hidden collider is not visualized
  bool hidden = 10;
}

// Geometry of a mesh.
message MeshGeometry {
  // Name of the mesh geometry. This is used in mesh colliders to refer to the
  // geometry.
  string name = 1;
  // Path of the mesh file. See https://trimsh.org/ for the supported formats.
  // If the path is specified, then the {vertices, faces, vertex_normals}
  // fields below will be ignored and populated from the mesh defined in the
  // file.
  string path = 2;
  // Vertices of the mesh.
  repeated Vector3 vertices = 3;
  // Triangular faces. This will be a flattened array of triples that contain
  // the indices of the vertices in the `vertices` field above. For example,
  //
  // vertices { x: -0.5 y: -0.5 z: 0 }
  // vertices { x: +0.5 y: -0.5 z: 0 }
  // vertices { x: +0.5 y: +0.5 z: 0 }
  // vertices { x: -0.5 y: +0.5 z: 0 }
  // vertices { x: 0 y: 0 z: 1.0 }
  // faces: [0, 2, 1, 0, 3, 2, 0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 3, 4]
  //
  // defines a pyramid with 6 faces (two for the bottom and four for the
  // sides).
  repeated int32 faces = 4;
  // Unit normal vectors for each vertex.
  repeated Vector3 vertex_normals = 5;
  // Unit normal vectors for each face.
  repeated Vector3 face_normals = 6;
}

// The configuration of a system.
message Config {
  // All of the bodies in the system
  repeated Body bodies = 1;
  // Amount of time to simulate each step, in seconds
  float dt = 2;
  // Prevents motion or rotation along specified axes for the entire system
  Frozen frozen = 3;
  // All of the mesh geometries in the system.
  repeated MeshGeometry mesh_geometries = 4;
}
