From eb11231e78be040102ab3548b4054fb50617fbb7 Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Mon, 23 Dec 2019 09:07:35 +1300
Subject: [PATCH] Graphics API JSDoc

---
 .../src/graphics-scripting/Forward.h          |  60 ++---
 .../GraphicsScriptingInterface.cpp            | 129 ++++++++-
 .../GraphicsScriptingInterface.h              |  84 ++++--
 .../GraphicsScriptingUtil.cpp                 |  18 ++
 .../src/graphics-scripting/ScriptableMesh.cpp |  28 +-
 .../src/graphics-scripting/ScriptableMesh.h   | 173 ++++++++++++-
 .../graphics-scripting/ScriptableMeshPart.h   | 244 ++++++++++++++++--
 .../src/graphics-scripting/ScriptableModel.h  |  51 +++-
 .../src/graphics/BufferViewHelpers.cpp        |  44 ++++
 libraries/graphics/src/graphics/Geometry.h    |  17 --
 .../graphics/src/graphics/GpuHelpers.cpp      |  18 ++
 11 files changed, 751 insertions(+), 115 deletions(-)

diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h
index acef5a5bd4..29f8079422 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h
@@ -36,39 +36,6 @@ namespace scriptable {
     using ModelProviderPointer = std::shared_ptr<scriptable::ModelProvider>;
     using WeakModelProviderPointer = std::weak_ptr<scriptable::ModelProvider>;
 
-    /**jsdoc
-     * @typedef {object} Graphics.Material
-     * @property {string} name
-     * @property {string} model
-     * @property {number|string} opacity
-     * @property {number|string} roughness
-     * @property {number|string} metallic
-     * @property {number|string} scattering
-     * @property {boolean|string} unlit
-     * @propety {Vec3|string} emissive
-     * @propety {Vec3|string} albedo
-     * @property {string} emissiveMap
-     * @property {string} albedoMap
-     * @property {string} opacityMap
-     * @property {string} opacityMapMode
-     * @property {number|string} opacityCutoff
-     * @property {string} metallicMap
-     * @property {string} specularMap
-     * @property {string} roughnessMap
-     * @property {string} glossMap
-     * @property {string} normalMap
-     * @property {string} bumpMap
-     * @property {string} occlusionMap
-     * @property {string} lightMap
-     * @property {string} scatteringMap
-     * @property {Mat4|string} texCoordTransform0
-     * @property {Mat4|string} texCoordTransform1
-     * @property {string} lightmapParams
-     * @property {string} materialParams
-     * @property {string} cullFaceMode
-     * @property {boolean} defaultFallthrough
-     * @property {string} procedural
-     */
     class ScriptableMaterial {
     public:
         ScriptableMaterial() {}
@@ -110,9 +77,11 @@ namespace scriptable {
     };
 
     /**jsdoc
+     * A material layer.
      * @typedef {object} Graphics.MaterialLayer
-     * @property {Graphics.Material} material - This layer's material.
-     * @property {number} priority - The priority of this layer.  If multiple materials are applied to a mesh part, only the highest priority layer is used.
+     * @property {Graphics.Material} material - The layer's material.
+     * @property {number} priority - The priority of the layer. If multiple materials are applied to a mesh part, only the 
+     *     layer with the highest priority is applied, with materials of the same priority randomly assigned.
      */
     class ScriptableMaterialLayer {
     public:
@@ -138,8 +107,29 @@ namespace scriptable {
         ScriptableMeshBase(const ScriptableMeshBase& other, QObject* parent = nullptr) : QObject(parent) { *this = other; }
         ScriptableMeshBase& operator=(const ScriptableMeshBase& view);
         virtual ~ScriptableMeshBase();
+
+        /**jsdoc
+         * @function GraphicsMesh.getMeshPointer
+         * @deprecated This method is deprecated and will be removed.
+         * @returns {undefined}
+         */
+        // scriptable::MeshPointer is not registered as a JavaScript type.
         Q_INVOKABLE const scriptable::MeshPointer getMeshPointer() const { return weakMesh.lock(); }
+
+        /**jsdoc
+         * @function GraphicsMesh.getModelProviderPointer
+         * @deprecated This method is deprecated and will be removed.
+         * @returns {undefined}
+         */
+        // scriptable::ModelProviderPointer is not registered as a JavaScript type.
         Q_INVOKABLE const scriptable::ModelProviderPointer getModelProviderPointer() const { return provider.lock(); }
+
+        /**jsdoc
+         * @function GraphicsMesh.getModelBasePointer
+         * @deprecated This method is deprecated and will be removed.
+         * @returns {undefined}
+         */
+        // scriptable::ScriptableModelBasePointer is not registered as a JavaScript type.
         Q_INVOKABLE const scriptable::ScriptableModelBasePointer getModelBasePointer() const { return model; }
     };
     
diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp
index 62614ea6e8..9d36cfd91a 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp
+++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp
@@ -168,14 +168,15 @@ scriptable::ScriptableMeshPointer GraphicsScriptingInterface::newMesh(const QVar
     //  in the future we want to support a formal C++ structure data type here instead
 
     /**jsdoc
+     * IFS (Indexed-Face Set) data defining a mesh.
      * @typedef {object} Graphics.IFSData
-     * @property {string} [name=""] - mesh name (useful for debugging / debug prints).
-     * @property {string} [topology=""]
-     * @property {number[]} indices - vertex indices to use for the mesh faces.
-     * @property {Vec3[]} vertices - vertex positions (model space)
-     * @property {Vec3[]} [normals=[]] - vertex normals (normalized)
-     * @property {Vec3[]} [colors=[]] - vertex colors (normalized)
-     * @property {Vec2[]} [texCoords0=[]] - vertex texture coordinates (normalized)
+     * @property {string} [name=""] - Mesh name. (Useful for debugging.)
+     * @property {Graphics.MeshTopology} topology - Element interpretation. <em>Currently only triangles is supported.</em>
+     * @property {number[]} indices - Vertex indices to use for the mesh faces, in tuples per the <code>topology</code>.
+     * @property {Vec3[]} positions - Vertex positions, in model coordinates.
+     * @property {Vec3[]} [normals=[]] - Vertex normals (normalized).
+     * @property {Vec3[]} [colors=[]] - Vertex colors (normalized).
+     * @property {Vec2[]} [texCoords0=[]] - Vertex texture coordinates (normalized).
      */
     QString meshName = ifsMeshData.value("name").toString();
     QString topologyName = ifsMeshData.value("topology").toString();
@@ -354,6 +355,120 @@ namespace scriptable {
         qScriptValueToSequence(array, result);
     }
 
+    /**jsdoc
+     * A material in a {@link GraphicsModel}.
+     * @typedef {object} Graphics.Material
+     * @property {string} name - The name of the material.
+     * @property {string} model - Different material models support different properties and rendering modes. Supported models 
+     *     are: <code>"hifi_pbr"</code> and <code>"hifi_shader_simple"</code>.
+     * @property {Vec3|string} [albedo] - The albedo color. Component values are in the range <code>0.0</code> &ndash;
+     *     <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     * @property {number|string} [opacity] - The opacity, range <code>0.0</code> &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *
+     * @property {number|string} [opacityCutoff] - The opacity cutoff threshold used to determine the opaque texels of the
+     *     <code>opacityMap</code> when <code>opacityMapMode</code> is <code>"OPACITY_MAP_MASK"</code>. Range <code>0.0</code>
+     *     &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {number|string} [roughness] - The roughness, range <code>0.0</code> &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {number|string} [metallic] - The metallicness, range <code>0.0</code> &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {number|string} [scattering] - The scattering, range <code>0.0</code> &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {boolean|string} [unlit] - <code>true</code> if the material is unaffected by lighting, <code>false</code> if it
+     *     it is lit by the key light and local lights.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {Vec3|string} [emissive] - The emissive color, i.e., the color that the material emits. Component values are
+     *     in the range <code>0.0</code> &ndash; <code>1.0</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [albedoMap] - The URL of the albedo texture image.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [opacityMap] - The URL of the opacity texture image.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [opacityMapMode] - The mode defining the interpretation of the opacity map. Values can be:
+     *     <ul>
+     *         <li><code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information.</li>
+     *         <li><code>"OPACITY_MAP_MASK"</code> for using the <code>opacityMap</code> as a mask, where only the texel greater
+     *         than <code>opacityCutoff</code> are visible and rendered opaque.</li>
+     *         <li><code>"OPACITY_MAP_BLEND"</code> for using the <code>opacityMap</code> for alpha blending the material surface
+     *         with the background.</li>
+     *     </ul>
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [occlusionMap] - The URL of the occlusion texture image.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [lightMap] - The URL of the light map texture image.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [lightmapParams] - Parameters for controlling how <code>lightMap</code> is used.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     *     <p><em>Currently not used.</em></p>
+     * @property {string} [scatteringMap] - The URL of the scattering texture image.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [emissiveMap] - The URL of the emissive texture image.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [metallicMap] - The URL of the metallic texture image.
+     *     If <code>"fallthrough"</code> then it and <code>specularMap</code> fall through to the material below.
+     *     Only use one of <code>metallicMap</code> and <code>specularMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [specularMap] - The URL of the specular texture image.
+     *     Only use one of <code>metallicMap</code> and <code>specularMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [roughnessMap] - The URL of the roughness texture image.
+     *     If <code>"fallthrough"</code> then it and <code>glossMap</code> fall through to the material below.
+     *     Only use one of <code>roughnessMap</code> and <code>glossMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [glossMap] - The URL of the gloss texture image.
+     *     Only use one of <code>roughnessMap</code> and <code>glossMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [normalMa]p - The URL of the normal texture image.
+     *     If <code>"fallthrough"</code> then it and <code>bumpMap</code> fall through to the material below.
+     *     Only use one of <code>normalMap</code> and <code>bumpMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [bumpMap] - The URL of the bump texture image.
+     *     Only use one of <code>normalMap</code> and <code>bumpMap</code>.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {string} [materialParams] - Parameters for controlling the material projection and repetition.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     *     <p><em>Currently not used.</em></p>
+     * @property {string} [cullFaceMode="CULL_BACK"] - Specifies Which faces of the geometry to render. Values can be:
+     *     <ul>
+     *         <li><code>"CULL_NONE"</code> to render both sides of the geometry.</li>
+     *         <li><code>"CULL_FRONT"</code> to cull the front faces of the geometry.</li>
+     *         <li><code>"CULL_BACK"</code> (the default) to cull the back faces of the geometry.</li>
+     *     </ul>
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {Mat4|string} [texCoordTransform0] - The transform to use for all of the maps apart from
+     *     <code>occlusionMap</code> and <code>lightMap</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     * @property {Mat4|string} [texCoordTransform1] - The transform to use for <code>occlusionMap</code> and
+     *     <code>lightMap</code>.
+     *     If <code>"fallthrough"</code> then it falls through to the material below.
+     *     <code>"hifi_pbr"</code> model only.
+     *
+     * @property {string} procedural - The definition of a procedural shader material.
+     *     <code>"hifi_shader_simple"</code> model only.
+     *     <p><em>Currently not used.</em></p>
+     *
+     * @property {boolean} defaultFallthrough - <code>true</code> if all properties fall through to the material below unless 
+     *     they are set, <code>false</code> if properties respect their individual fall-through settings.
+     */
     QScriptValue scriptableMaterialToScriptValue(QScriptEngine* engine, const scriptable::ScriptableMaterial &material) {
         QScriptValue obj = engine->newObject();
         obj.setProperty("name", material.name);
diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
index c1f3be2b3d..9b56433bf6 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
@@ -23,7 +23,10 @@
 
 
 /**jsdoc
- * The experimental Graphics API <em>(experimental)</em> lets you query and manage certain graphics-related structures (like underlying meshes and textures) from scripting.
+ * The <code>Graphics</code> API enables you to access and manipulate avatar, entity, and overlay models in the rendered scene. 
+ * This includes getting mesh and material information for applying {@link Entities.EntityProperties-Material|Material} 
+ * entities.
+ *
  * @namespace Graphics
  *
  * @hifi-interface
@@ -40,44 +43,83 @@ public:
 
 public slots:
     /**jsdoc
-     * Returns a model reference object associated with the specified UUID ({@link EntityID} or {@link AvatarID}).
-     *
+     * Gets a handle to the model data used for displaying an avatar, 3D entity, or 3D overlay.
+     * <p>Note: The model data may be used for more than one instance of the item displayed in the scene.</p>
      * @function Graphics.getModel
-     * @param {UUID} entityID - The objectID of the model whose meshes are to be retrieved.
-     * @returns {Graphics.Model} the resulting Model object
+     * @param {UUID} id - The ID of the avatar, 3D entity, or 3D overlay.
+     * @returns {GraphicsModel} The model data for the avatar, entity, or overlay, as displayed. This includes the results of 
+     *     applying any {@link Entities.EntityProperties-Material|Material} entities to the item.
+     * @example <caption>Report some details of your avatar's model.</caption>
+     * var model = Graphics.getModel(MyAvatar.sessionUUID);
+     * var meshes = model.meshes;
+     * var numMeshparts = 0;
+     * for (var i = 0; i < meshes.length; i++) {
+     *     numMeshparts += meshes[i].numParts;
+     * }
+     * 
+     * print("Avatar:", MyAvatar.skeletonModelURL);
+     * print("Number of meshes:", model.numMeshes);
+     * print("Number of mesh parts:", numMeshparts);
+     * print("Material names: ", model.materialNames);
+     * print("Material layers:", Object.keys(model.materialLayers));
      */
     scriptable::ScriptableModelPointer getModel(const QUuid& uuid);
 
     /**jsdoc
+     * Updates the model for an avatar, 3D entity, or 3D overlay in the rendered scene.
      * @function Graphics.updateModel
-     * @param {Uuid} id
-     * @param {Graphics.Model} model
-     * @returns {boolean}
+     * @param {Uuid} id - The ID of the avatar, 3D entity, or 3D overlay to update.
+     * @param {GraphicsModel} model - The model to update the avatar, 3D entity, or 3D overlay with.
+     * @returns {boolean} <code>true</code> if the update was completed successfully, <code>false</code> if it wasn't.
      */
     bool updateModel(const QUuid& uuid, const scriptable::ScriptableModelPointer& model);
 
     /**jsdoc
+     * Checks whether the model for an avatar, entity, or overlay can be updated in the rendered scene. Only avatars, 
+     * <code>"Model"</code> entities and <code>"model"</code> overlays can have their meshes updated.
      * @function Graphics.canUpdateModel
-     * @param {Uuid} id
-     * @param {number} [meshIndex=-1]
-     * @param {number} [partNumber=-1]
-     * @returns {boolean}
+     * @param {Uuid} id - The ID of the avatar, entity, or overlay.
+     * @param {number} [meshIndex=-1] - <em>Not used.</em>
+     * @param {number} [partNumber=-1] - <em>Not used.</em>
+     * @returns {boolean} <code>true</code> if the model can be updated, <code>false</code> if it can't.
+     * @example <caption>Test whether different types of items can be updated.</caption>
+     * var modelEntityID = Entities.addEntity({
+     *     type: "Model",
+     *     position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5, y: 0, z: -3 })),
+     *     rotation: MyAvatar.orientation,
+     *     modelURL: "http://content.highfidelity.com/seefo/production/puck-attach/vive_tracker_puck.obj",
+     *     dimensions: { x: 0.945, y: 0.921, z: 0.423 },
+     *     lifetime: 300  // Delete after 5 minutes.
+     * });
+     * var shapeEntityID = Entities.addEntity({
+     *     type: "Shape",
+     *     shape: "Cylinder",
+     *     position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(Camera.orientation, { x: 0.5, y: 0, z: -3 })),
+     *     dimensions: { x: 0.4, y: 0.6, z: 0.4 },
+     *     lifetime: 300  // Delete after 5 minutes.
+     * });
+     * 
+     * Script.setTimeout(function () {
+     *     print("Can update avatar:", Graphics.canUpdateModel(MyAvatar.sessionUUID));  // true
+     *     print("Can update model entity:", Graphics.canUpdateModel(modelEntityID));  // true
+     *     print("Can update shape entity:", Graphics.canUpdateModel(shapeEntityID));  // false
+     * }, 1000);  // Wait for the entities to rez.
      */
     bool canUpdateModel(const QUuid& uuid, int meshIndex = -1, int partNumber = -1);
 
     /**jsdoc
+     * Creates a new graphics model from meshes.
      * @function Graphics.newModel
-     * @param {Graphics.Mesh[]} meshes
-     * @returns {Graphics.Model}
+     * @param {GraphicsMesh[]} meshes - The meshes to include in the model.
+     * @returns {GraphicsModel} The new graphics model.
      */
     scriptable::ScriptableModelPointer newModel(const scriptable::ScriptableMeshes& meshes);
 
     /**jsdoc
-     * Create a new Mesh / Mesh Part with the specified data buffers.
-     *
+     * Creates a new graphics mesh.
      * @function Graphics.newMesh
-     * @param {Graphics.IFSData} ifsMeshData Index-Faced Set (IFS) arrays used to create the new mesh.
-     * @returns {Graphics.Mesh} the resulting Mesh / Mesh Part object
+     * @param {Graphics.IFSData} ifsMeshData - Index-Faced Set (IFS) data defining the mesh.
+     * @returns {GraphicsMesh} The new graphics mesh.
      */
     scriptable::ScriptableMeshPointer newMesh(const QVariantMap& ifsMeshData);
 
@@ -89,10 +131,12 @@ public slots:
 #endif
 
     /**jsdoc
+     * Exports a model to OBJ format.
      * @function Graphics.exportModelToOBJ
-     * @param {Graphics.Model} model
-     * @returns {string}
+     * @param {GraphicsModel} model - The model to export.
+     * @returns {string} The OBJ format representation of the model.
      */
+    // FIXME: If you put the OBJ on the Asset Server and rez it, Interface keeps crashing until the model is removed.
     QString exportModelToOBJ(const scriptable::ScriptableModelPointer& model);
 
 private:
diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp
index da582b2d21..d1f419728a 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp
+++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp
@@ -37,6 +37,14 @@ QVariant toVariant(const Extents& box) {
     };
 }
 
+/**jsdoc
+ * The extents of a mesh.
+ * @typedef {object} Graphics.MeshExtents
+ * @property {Vec3} brn - The bottom right near (minimum axes values) corner of the enclosing box.
+ * @property {Vec3} tfl - The top far left (maximum axes values) corner of the enclosing box.
+ * @property {Vec3} center - The center of the enclosing box.
+ * @property {Vec3} dimensions - The dimensions of the enclosing box.
+ */
 QVariant toVariant(const AABox& box) {
     return QVariantMap{
         { "brn", glmVecToVariant(box.getCorner()) },
@@ -48,6 +56,16 @@ QVariant toVariant(const AABox& box) {
     };
 }
 
+/**jsdoc
+ * Details of a buffer element's format.
+ * @typedef {object} Graphics.BufferElementFormat
+ * @property {string} type
+ * @property {string} semantic
+ * @property {string} dimension
+ * @property {number} scalarCount
+ * @property {number} byteSize
+ * @property {number} BYTES_PER_ELEMENT
+ */
 QVariant toVariant(const gpu::Element& element) {
     return QVariantMap{
         { "type", gpu::toString(element.getType()) },
diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp
index 72d2adb48f..5f81e2daf7 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp
+++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp
@@ -127,6 +127,16 @@ int scriptable::ScriptableMesh::getSlotNumber(const QString& attributeName) cons
     return -1;
 }
 
+/**jsdoc
+ * Details of buffer's format.
+ * @typedef {object} Graphics.BufferFormat
+ * @property {number} slot
+ * @property {number} length
+ * @property {number} byteLength
+ * @property {number} offset
+ * @property {number} stride
+ * @property {Graphics.BufferElementFormat} element
+ */
 QVariantMap scriptable::ScriptableMesh::getBufferFormats() const {
     QVariantMap result;
     for (const auto& a : buffer_helpers::ATTRIBUTES.toStdMap()) {
@@ -247,6 +257,13 @@ bool scriptable::ScriptableMesh::setVertexProperty(glm::uint32 vertexIndex, cons
     return buffer_helpers::setValue(bufferView, vertexIndex, value);
 }
 
+/**jsdoc
+ * Called for each vertex when {@link GraphicsMesh.updateVertexAttributes} is called.
+ * @callback GraphicsMesh~forEachVertextCallback
+ * @param {Object<Graphics.BufferTypeName, Graphics.BufferType>} attributes - The attributes  of the vertex.
+ * @param {number} index - The vertex index.
+ * @param {object} properties - The properties of the mesh, per {@link GraphicsMesh}.
+ */
 glm::uint32 scriptable::ScriptableMesh::forEachVertex(QScriptValue _callback) {
     auto mesh = getMeshPointer();
     if (!mesh) {
@@ -275,7 +292,16 @@ glm::uint32 scriptable::ScriptableMesh::forEachVertex(QScriptValue _callback) {
     return numProcessed;
 }
 
-
+/**jsdoc
+ * Called for each vertex when {@link GraphicsMesh.updateVertexAttributes} is called. The value returned by the script function 
+ * should be the modified attributes to update the vertex with, or <code>false</code> to not update the particular vertex.
+ * @callback GraphicsMesh~updateVertexAttributesCallback
+ * @param {Object<Graphics.BufferTypeName, Graphics.BufferType>} attributes - The attributes  of the vertex.
+ * @param {number} index - The vertex index.
+ * @param {object} properties - The properties of the mesh, per {@link GraphicsMesh}.
+ * @returns {Object<Graphics.BufferTypeName, Graphics.BufferType>|boolean} The attribute values to update the vertex with, or 
+ *     <code>false</code> to not update the vertex.
+ */
 glm::uint32 scriptable::ScriptableMesh::updateVertexAttributes(QScriptValue _callback) {
     auto mesh = getMeshPointer();
     if (!mesh) {
diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h
index dcb1c53759..98f496cd9e 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h
@@ -1,4 +1,3 @@
-//
 //  Copyright 2018 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -29,17 +28,40 @@
 
 namespace scriptable {
     /**jsdoc
-     * @typedef {object} Graphics.Mesh
-     * @property {Graphics.MeshPart[]} parts - Array of submesh part references.
-     * @property {string[]} attributeNames - Vertex attribute names (color, normal, etc.)
-     * @property {number} numParts - The number of parts contained in the mesh.
-     * @property {number} numIndices - Total number of vertex indices in the mesh.
-     * @property {number} numVertices - Total number of vertices in the Mesh.
-     * @property {number} numAttributes - Number of currently defined vertex attributes.
-     * @property {boolean} valid
-     * @property {boolean} strong
-     * @property {object} extents
-     * @property {object} bufferFormats
+     * A handle to in-memory mesh data in a {@link GraphicsModel}.
+     * 
+     * <p>Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.</p>
+     *
+     * @class GraphicsMesh
+     *
+     * @hifi-interface
+     * @hifi-client-entity
+     * @hifi-avatar
+     *
+     * @property {number} numParts - The number of mesh parts.
+     *     <em>Read-only.</em>
+     * @property {GraphicsMeshPart[]} parts - The mesh parts.
+     *     <em>Read-only.</em>
+     * @property {number} numIndices - The total number of vertex indices in the mesh.
+     *     <em>Read-only.</em>
+     * @property {number} numVertices - The total number of vertices in the mesh.
+     *     <em>Read-only.</em>
+     * @property {number} numAttributes - The number of vertex attributes.
+     *     <em>Read-only.</em>
+     * @property {Graphics.BufferTypeName[]} attributeNames - The names of the vertex attributes.
+     *     <em>Read-only.</em>
+     * @property {boolean} valid - <code>true</code> if the mesh is valid, <code>false</code> if it isn't.
+     *     <em>Read-only.</em>
+     * @property {boolean} strong - <code>true</code> if the mesh is valid and able to be used, <code>false</code> if it isn't.
+     *     <em>Read-only.</em>
+     * @property {Graphics.MeshExtents} extents - The mesh extents, in model coordinates.
+     *     <em>Read-only.</em>
+     * @property {Object<Graphics.BufferTypeName, Graphics.BufferFormat>} bufferFormats - Details of the buffers used for the 
+     *     mesh.
+     *     <em>Read-only.</em>
+     *
+     * @borrows GraphicsMesh.getVertextAttributes as getVertextAttributes
+     * @borrows GraphicsMesh.setVertextAttributes as setVertextAttributes
      */
     class ScriptableMesh : public ScriptableMeshBase, QScriptable {
         Q_OBJECT
@@ -82,26 +104,153 @@ namespace scriptable {
         int getSlotNumber(const QString& attributeName) const;
 
     public slots:
+        
+        /**jsdoc
+         * Gets the model the mesh is part of.
+         * <p><em>Currently doesn't work.</em></p>
+         * @function GraphicsMesh.getParentModel
+         * @returns {GraphicsModel} The model the mesh is part of, <code>null</code> if it isn't part of a model.
+         */
         const scriptable::ScriptableModelPointer getParentModel() const { return qobject_cast<scriptable::ScriptableModel*>(model); }
+        
+        /**jsdoc
+         * Gets the vertex indices.
+         * @function GraphicsMesh.getIndices
+         * @returns {number[]} The vertex indices.
+         */
         QVector<glm::uint32> getIndices() const;
+
+        /**jsdoc
+         * Gets the indices of nearby vertices.
+         * @function GraphicsMesh.findNearbyVertexIndices
+         * @param {Vec3} origin - The search position, in model coordinates.
+         * @param {number} [epsilon=1e-6] - The search distance. If a vertex is within this distance from the 
+         *    <code>origin</code> it is considered to be "nearby".
+         * @returns {number[]} The indices of nearby vertices.
+         */
         QVector<glm::uint32> findNearbyVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const;
 
+        /**jsdoc
+         * Adds an attribute to the (whole) mesh's vertices.
+         * @function GraphicsMesh.addAttribute
+         * @param {Graphics.BufferTypeName} name - The name of the attribute.
+         * @param {Graphics.BufferType} [defaultValue] - The value to give the attributes added to the vertices.
+         * @returns {number} The number of vertices the attribute was added to, <code>0</code> if the <code>name</code> was 
+         *     invalid or all vertices already had the attribute.
+         */
         glm::uint32 addAttribute(const QString& attributeName, const QVariant& defaultValue = QVariant());
+
+        /**jsdoc
+         * Sets the value of an attribute for all vertices.
+         * @function GraphicsMesh.fillAttribute
+         * @param {Graphics.BufferTypeName} name - The name of the attribute. The attribute is added to the vertices if not 
+         *     already present.
+         * @param {Graphics.BufferType} value - The value to give the attributes.
+         * @returns {number} <code>1</code> if the attribute name was valid and the attribute values were set, <code>0</code> 
+         *     otherwise.
+         */
         glm::uint32 fillAttribute(const QString& attributeName, const QVariant& value);
+
+        /**jsdoc
+         * Removes an attribute from all vertices.
+         * <p>Note: The <code>"position"</code> attribute cannot be removed.</p>
+         * @function GraphicsMesh.removeAttribute
+         * @param {Graphics.BufferTypeName} name - The name of the attribute to remove. 
+         * @returns {boolean} <code>true</code> if the attribute existed and was removed, <code>false</code> otherwise.
+         */
         bool removeAttribute(const QString& attributeName);
 
+        /**jsdoc
+         * Gets the value of an attribute for all vertices.
+         * @function GraphicsMesh.queryVertexAttributes
+         * @param {Graphics.BufferTypeName} name - The name of the attribute to get the vertex values of.
+         * @throws Throws an error if the <code>name</code> is invalid or isn't used in the mesh.
+         * @returns {Graphics.BufferType[]} The attribute values for all vertices.
+         */
         QVariantList queryVertexAttributes(QVariant selector) const;
+
+        /**jsdoc
+         * Gets the attributes and attribute values of a vertex.
+         * @function GraphicsMesh.getVertexAttributes
+         * @param {number} index - The vertex to get the attributes for.
+         * @returns {Object<Graphics.BufferTypeName,Graphics.BufferType>} The attribute names and values for the vertex.
+         * @throws Throws an error if the <code>index</code> is invalid.
+         */
         QVariantMap getVertexAttributes(glm::uint32 vertexIndex) const;
+
+        /**jsdoc
+         * Updates attribute values of a vertex.
+         * @function GraphicsMesh.setVertexAttributes
+         * @param {number} index - The vertex to set the attributes for.
+         * @param {Object<Graphics.BufferTypeNAme,Graphics.BufferType>} values - The attribute names and values. Need not 
+         *     specify unchanged values.
+         * @returns {boolean} <code>true</code> if the index and the attribute names and values were valid and the vertex was 
+         *     updated, <code>false</code> otherwise.
+         * @throws Throws an error if the <code>index</code> is invalid or one of the attribute names is invalid or isn't used 
+         *     in the mesh.
+         */
+        // @borrows jsdoc from GraphicsMesh
         bool setVertexAttributes(glm::uint32 vertexIndex, const QVariantMap& attributeValues);
 
+        /**jsdoc
+         * Gets the value of a vertex's attribute.
+         * @function GraphicsMesh.getVertexProperty
+         * @param {number} index - The vertex index.
+         * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to get.
+         * @returns {Graphics.BufferType} The value of the vertex attribute.
+         * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the 
+         *     mesh.
+         */
         QVariant getVertexProperty(glm::uint32 vertexIndex, const QString& attributeName) const;
+
+        /**jsdoc
+         * Sets the value of a vertex's attribute.
+         * @function GraphicsMesh.setVertexProperty
+         * @param {number} index - The vertex index.
+         * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to set.
+         * @param {Graphics.BufferType} value - The vertex attribute value to set.
+         * @returns {boolean} <code>true</code> if the vertex attribute value was set, <code>false</code> if it wasn't.
+         * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the
+         *     mesh.
+         */
         bool setVertexProperty(glm::uint32 vertexIndex, const QString& attributeName, const QVariant& value);
 
+        /**jsdoc
+         * Makes a copy of the mesh.
+         * @function GraphicsMesh.cloneMesh
+         * @returns {GraphicsMesh} A copy of the mesh.
+         */
         scriptable::ScriptableMeshPointer cloneMesh();
 
         // QScriptEngine-specific wrappers
+
+        /**jsdoc
+         * Updates vertex attributes by calling a function for each vertex. The function can return modified attributes to 
+         * update the vertex with.
+         * @function GraphicsMesh.updateVertexAttributes
+         * @param {GraphicsMesh~updateVertexAttributesCallback} callback - The function to call for each vertex.
+         * @returns {number} The number of vertices the callback was called for.
+         */
         glm::uint32 updateVertexAttributes(QScriptValue callback);
+
+        /**jsdoc
+         * Calls a function for each vertex.
+         * @function GraphicsMesh.forEachVertex
+         * @param {GraphicsMesh~forEachVertexCallback} callback - The function to call for each vertex.
+         * @returns {number} The number of vertices the callback was called for.
+         */
         glm::uint32 forEachVertex(QScriptValue callback);
+
+        /**jsdoc
+         * Checks if an index is valid and, optionally, that vertex has a particular attribute.
+         * @function GraphicsMesh.isValidIndex
+         * @param {number} index - The index to check.
+         * @param {Graphics.BufferTypeName} [attribute] - The attribute to check.
+         * @returns {boolean} <code>true</code> if the index is valid and that vertex has the attribute if specified.
+         * @throws Throws an error if the <code>index</code> if invalid or <code>name</code> is invalid or isn't used in the 
+         *     mesh.
+         */
+        // FIXME: Should return false rather than throw an error.
         bool isValidIndex(glm::uint32 vertexIndex, const QString& attributeName = QString()) const;
     };
 
diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h
index 7352fcd0f6..00645145c5 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h
@@ -11,23 +11,49 @@
 
 namespace scriptable {
     /**jsdoc
-     * @typedef {object} Graphics.MeshPart
-     * @property {boolean} valid
-     * @property {number} partIndex - The part index (within the containing Mesh).
-     * @property {number} firstVertexIndex
-     * @property {number} baseVertexIndex
-     * @property {number} lastVertexIndex
-     * @property {Graphics.Topology} topology - element interpretation (currently only 'triangles' is supported).
-     * @property {string[]} attributeNames - Vertex attribute names (color, normal, etc.)
-     * @property {number} numIndices - Number of vertex indices that this mesh part refers to.
-     * @property {number} numVerticesPerFace - Number of vertices per face (eg: 3 when topology is 'triangles').
-     * @property {number} numFaces - Number of faces represented by the mesh part (numIndices / numVerticesPerFace).
-     * @property {number} numVertices - Total number of vertices in the containing Mesh.
-     * @property {number} numAttributes - Number of currently defined vertex attributes.
-     * @property {object} extents
-     * @property {object} bufferFormats
-     */
+     * A handle to in-memory mesh part data in a {@link GraphicsModel}.
+     *
+     * <p>Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or 
+     * {@link GraphicsMeshPart.cloneMeshPart}.</p>
+     *
+     * @class GraphicsMeshPart
+     *
+     * @hifi-interface
+     * @hifi-client-entity
+     * @hifi-avatar
+     *
+     * @property {boolean} valid - <code>true</code> if the mesh part is valid, <code>false</code> if it isn't.
+     *     <em>Read-only.</em>
+     * @property {number} partIndex - The index of the part within the <em>whole</em> mesh (i.e., parent and mesh parts).
+     *     <em>Read-only.</em>
+     * @property {number} firstVertexIndex - The index of the first vertex.
+     * @property {number} baseVertexIndex - The index of the base vertex.
+     * @property {number} lastVertexIndex - The index of the last vertex.
+     * @property {Graphics.MeshTopology} topology - The element interpretation. <em>Currently only triangles is supported.</em>
+     * @property {number} numIndices - The number of vertex indices in the mesh part.
+     * @property {number} numVertices - The number of vertices in the <em>whole</em> mesh  (i.e., parent and mesh parts).
+     *     <em>Read-only.</em>
+     * @property {number} numVerticesPerFace - The number of vertices per face, per the <code>topology</code> (e.g., 3 for 
+     *     triangles).
+     *     <em>Read-only.</em>
+     * @property {number} numFaces - The number of faces represented by the mesh part.
+     *     <em>Read-only.</em>
+     * @property {number} numAttributes - The number of vertex attributes in the <em>whole</em> mesh  (i.e., parent and mesh 
+     *     parts).
+     *     <em>Read-only.</em>
+     * @property {Graphics.BufferTypeName[]} attributeNames - The names of the vertex attributes in the <em>whole</em> mesh 
+     *     (i.e., parent and mesh parts).
+     *     <em>Read-only.</em>
+     * @property {Graphics.MeshExtents} extents - The mesh part extents, in model coordinates.
+     *     <em>Read-only.</em>
+     * @property {Object<Graphics.BufferTypeName, Graphics.BufferFormat>} bufferFormats - Details of the buffers used for the 
+     *     <em>whole</em> mesh (i.e., parent and mesh parts).
+     *     <em>Read-only.</em>
 
+     * @borrows GraphicsMesh.addAttribute as addAttribute
+     * @borrows GraphicsMesh.getVertexAttributes as getVertextAttributes
+     * @borrows GraphicsMesh.setVertexAttributes as setVertextAttributes
+     */
     class ScriptableMeshPart : public QObject, QScriptable {
         Q_OBJECT
         Q_PROPERTY(bool valid READ isValid)
@@ -55,42 +81,228 @@ namespace scriptable {
         bool isValid() const { auto mesh = getMeshPointer(); return mesh && partIndex < mesh->getNumParts(); }
 
     public slots:
+
+        /**jsdoc
+         * Gets the vertex indices.
+         * @function GraphicsMeshPart.getIndices
+         * @returns {number[]} The vertex indices.
+         */
         QVector<glm::uint32> getIndices() const;
+        
+        /**jsdoc
+         * Sets the vertex indices.
+         * @function GraphicsMeshPart.setIndices
+         * @param {number[]} indices - The vertex indices.
+         * @returns {boolean} <code>true</code> if successful, <code>false</code> if not.
+         * @throws Throws an error if the number of indices isn't the same, or an index is invalid.
+         */
         bool setIndices(const QVector<glm::uint32>& indices);
+
+        /**jsdoc
+         * Gets the indices of nearby vertices in the mesh part.
+         * @function GraphicsMeshPart.findNearbyPartVertexIndices
+         * @param {Vec3} origin - The search position, in model coordinates.
+         * @param {number} [epsilon=1e-6] - The search distance. If a vertex is within this distance from the
+         *    <code>origin</code> it is considered to be "nearby".
+         * @returns {number[]} The indices of nearby vertices.
+         */
         QVector<glm::uint32> findNearbyPartVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const;
+
+        /**jsdoc
+         * Gets the value of an attribute for all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
+         * @function GraphicsMeshPArt.queryVertexAttributes
+         * @param {Graphics.BufferTypeName} name - The name of the attribute to get the vertex values of.
+         * @throws Throws an error if the <code>name</code> is invalid or isn't used in the mesh.
+         * @returns {Graphics.BufferType[]} The attribute values for all vertices.
+         */
         QVariantList queryVertexAttributes(QVariant selector) const;
+
+        // @borrows jsdoc from GraphicsMesh.
         QVariantMap getVertexAttributes(glm::uint32 vertexIndex) const;
+
+        // @borrows jsdoc from GraphicsMesh.
         bool setVertexAttributes(glm::uint32 vertexIndex, const QVariantMap& attributeValues);
 
+        /**jsdoc
+         * Gets the value of a vertex's attribute.
+         * @function GraphicsMeshPart.getVertexProperty
+         * @param {number} index - The vertex index.
+         * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to get.
+         * @returns {Graphics.BufferType} The value of the vertex attribute.
+         * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the
+         *     mesh.
+         */
         QVariant getVertexProperty(glm::uint32 vertexIndex, const QString& attributeName) const;
+
+        /**jsdoc
+         * Sets the value of a vertex's attribute.
+         * @function GraphicsMeshPart.setVertexProperty
+         * @param {number} index - The vertex index.
+         * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to set.
+         * @param {Graphics.BufferType} value - The vertex attribute value to set.
+         * @returns {boolean} <code>true</code> if the vertex attribute value was set, <code>false</code> if it wasn't.
+         * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the
+         *     mesh.
+         */
         bool setVertexProperty(glm::uint32 vertexIndex, const QString& attributeName, const QVariant& attributeValues);
 
+        /**jsdoc
+         * Gets the vertex indices that make up a face.
+         * @function GraphicsMeshPart.getFace
+         * @param {number} index - The index of the face.
+         * @returns {number[]} The vertex indices that make up the face, of number per the mesh <code>topology</code>.
+         */
         QVector<glm::uint32> getFace(glm::uint32 faceIndex) const;
 
+        /**jsdoc
+         * Scales the mesh to so that it's maximum model coordinate dimension is a specified length.
+         * @function GraphicsMeshPart.scaleToFit
+         * @param {number} scale - The target dimension.
+         * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
+         */
         QVariantMap scaleToFit(float unitScale);
+
+        /**jsdoc
+         * Translates the mesh part.
+         * @function GraphicsMeshPart.translate
+         * @param {Vec3} translation - The translation to apply, in model coordinates.
+         * @returns {Graphics.MeshExtents} The rseulting mesh extents, in model coordinates.
+         */
         QVariantMap translate(const glm::vec3& translation);
+
+        /**jsdoc
+         * Scales the mesh part.
+         * @function GraphicsMeshPart.scale
+         * @param {Vec3} scale - The scale to apply in each model coordinate direction.
+         * @param {Vec3} [origin] - The origin to scale about. If not specified, the center of the mesh part is used.
+         * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
+         */
         QVariantMap scale(const glm::vec3& scale, const glm::vec3& origin = glm::vec3(NAN));
+
+        /**jsdoc
+         * Rotates the mesh part, using Euler angles.
+         * @function GraphicsMeshPart.rotateDegrees
+         * @param {Vec3} eulerAngles - The rotation to perform, in mesh coordinates, as Euler angles in degrees.
+         * @param {Vec3} [origin] - The point about which to rotate, in model coordinates.
+         *     <p><strong>Warning:</strong> Currently doesn't work as expected.</p>
+         * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
+         */
         QVariantMap rotateDegrees(const glm::vec3& eulerAngles, const glm::vec3& origin = glm::vec3(NAN));
+
+        /**jsdoc
+         * Rotates the mesh part, using a quaternion.
+         * @function GraphicsMeshPart.rotate
+         * @param {Quat} rotation - The rotation to perform, in model coordinates.
+         * @param {Vec3} [origin] - The point about which to rotate, in model coordinates.
+         *     <p><strong>Warning:</strong> Currently doesn't work as expected.</p>
+         * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
+         */
         QVariantMap rotate(const glm::quat& rotation, const glm::vec3& origin = glm::vec3(NAN));
+
+        /**jsdoc
+         * Scales, rotates, and translates the mesh.
+         * @function GraphicsMeshPart.transform
+         * @param {Mat4} transform - The scale, rotate, and translate transform to apply.
+         * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
+         */
         QVariantMap transform(const glm::mat4& transform);
 
+        // @borrows jsdoc from GraphicsMesh.
         glm::uint32 addAttribute(const QString& attributeName, const QVariant& defaultValue = QVariant());
+
+        /**jsdoc
+         * Sets the value of an attribute for all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
+         * @function GraphicsMeshPart.fillAttribute
+         * @param {Graphics.BufferTypeName} name - The name of the attribute. The attribute is added to the vertices if not
+         *     already present.
+         * @param {Graphics.BufferType} value - The value to give the attributes.
+         * @returns {number} <code>1</code> if the attribute name was valid and the attribute values were set, <code>0</code>
+         *     otherwise.
+         */
         glm::uint32 fillAttribute(const QString& attributeName, const QVariant& value);
+
+        /**jsdoc
+         * Removes an attribute from all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
+         * <p>Note: The <code>"position"</code> attribute cannot be removed.</p>
+         * @function GraphicsMeshPArt.removeAttribute
+         * @param {Graphics.BufferTypeName} name - The name of the attribute to remove.
+         * @returns {boolean} <code>true</code> if the attribute existed and was removed, <code>false</code> otherwise.
+         */
         bool removeAttribute(const QString& attributeName);
+
+        /**jsdoc
+         * Deduplicates vertices.
+         * @function GraphicsMeshPart.dedupeVertices
+         * @param {number} [epsilon=1e-6] - The deduplicadtion distance. If a pair of vertices is within this distance of each 
+         *    other they are combined into a single vertex.
+         * @returns {boolean} <code>true</code> if the deduplication succeeded, <code>false</code> if it didn't.
+         */
         bool dedupeVertices(float epsilon = 1e-6);
 
+        /**jsdoc
+         * Gets the parent mesh.
+         * @function GraphicsMeshPart.getParentMesh
+         * @returns {GraphicsMesh} The parent mesh.
+         */
         scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; }
 
+        /**jsdoc
+         * Replaces a mesh part with a copy of another mesh part.
+         * @function GraphicsMeshPart.replaceMeshPartData
+         * @param {GrphicsMeshPart} source - The mesh part to copy.
+         * @param {Graphics.BufferTypeName[]} [attributes] - The attributes to copy. If not specified, all attributes are 
+         *     copied from the source.
+         * @throws Throws an error if the mesh part of source mesh part aren't valid.
+         * @returns {boolean} <code>true</code> if the mesh part was successfully replaced, <code>false</code> if it wasn't.
+         */
         bool replaceMeshPartData(scriptable::ScriptableMeshPartPointer source, const QVector<QString>& attributeNames = QVector<QString>());
+        
+        /**jsdoc
+         * Makes a copy of the mesh part.
+         * @function GraphicsMeshPart.cloneMeshPart
+         * @returns {GraphicsMeshPart} A copy of the mesh part.
+         */
         scriptable::ScriptableMeshPartPointer cloneMeshPart();
 
+        /**jsdoc
+         * Exports the mesh part to OBJ format.
+         * @function GraphicsMeshPart.toOBJ
+         * @returns {string} The OBJ format representation of the mesh part.
+         */
         QString toOBJ();
 
+
         // QScriptEngine-specific wrappers
+
+        /**jsdoc
+         * Updates vertex attributes by calling a function for each vertex in the <em>whole</em> mesh (i.e., the parent and 
+         * mesh parts). The function can return modified attributes to update the vertex with.
+         * @function GraphicsMeshPart.updateVertexAttributes
+         * @param {GraphicsMesh~updateVertexAttributesCallback} callback - The function to call for each vertex.
+         * @returns {number} The number of vertices the callback was called for.
+         */
         glm::uint32 updateVertexAttributes(QScriptValue callback);
+
+        /**jsdoc
+         * Calls a function for each vertex in the <em>whole</em> mesh (i.e., parent and mesh parts).
+         * @function GraphicsMeshPArt.forEachVertex
+         * @param {GraphicsMesh~forEachVertexCallback} callback - The function to call for each vertex.
+         * @returns {number} The number of vertices the callback was called for.
+         */
         glm::uint32 forEachVertex(QScriptValue callback);
 
+        /**jsdoc
+         * Checks if an index is valid and, optionally, that vertex has a particular attribute.
+         * @function GraphicsMeshPart.isValidIndex
+         * @param {number} index - The index to check.
+         * @param {Graphics.BufferTypeName} [attribute] - The attribute to check.
+         * @returns {boolean} <code>true</code> if the index is valid and that vertex has the attribute if specified.
+         * @throws Throws an error if the <code>index</code> if invalid or <code>name</code> is invalid or isn't used in the
+         *     mesh.
+         */
+        // FIXME: Should return false rather than throw an error.
         bool isValidIndex(glm::uint32 vertexIndex, const QString& attributeName = QString()) const;
+
     public:
         scriptable::ScriptableMeshPointer parentMesh;
         glm::uint32 partIndex;
diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h
index 7d1ca5f560..faa65f8bf6 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h
@@ -17,14 +17,35 @@ namespace scriptable {
     using ScriptableMeshes = QVector<scriptable::ScriptableMeshPointer>;
 
     /**jsdoc
-     * @typedef {object} Graphics.Model
-     * @property {Uuid} objectID - UUID of corresponding inworld object (if model is associated)
-     * @property {number} numMeshes - The number of submeshes contained in the model.
-     * @property {Graphics.Mesh[]} meshes - Array of submesh references.
-     * @property {Object.<string,Graphics.MaterialLayer[]>} materialLayers - Map of materials layer lists.  You can look up a material layer list by mesh part number or by material name.
-     * @property {string[]} materialNames - Array of all the material names used by the mesh parts of this model, in order (e.g. materialNames[0] is the name of the first mesh part's material).
+     * A handle to in-memory model data such as may be used in displaying avatars, 3D entities, or 3D overlays in the rendered 
+     * scene. Changes made to the model are visible only to yourself; they are not persisted.
+     * <p>Note: The model may be used for more than one instance of an item displayed in the scene. Modifying the model updates 
+     * all instances displayed.</p>
+     *
+     * <p>Created using the {@link Graphics} API or {@link GraphicsModel.cloneModel}.</p>
+     *
+     * @class GraphicsModel
+     *
+     * @hifi-interface
+     * @hifi-client-entity
+     * @hifi-avatar
+     *
+     * @property {Uuid} objectID - The ID of the entity or avatar that the model is associated with, if any; <code>null</code> 
+     *     if the model is not associated with an entity or avatar.
+     *     <em>Read-only.</em>
+     * @property {number} numMeshes - The number of meshes contained in the model.
+     *     <em>Read-only.</em>
+     * @property {GraphicsMesh[]} meshes - The meshes in the model. Each mesh may have more than one mesh part.
+     *     <em>Read-only.</em>
+     * @property {string[]} materialNames - The names of the materials used by each mesh part in the model. The names are in
+     *     the order of the <code>meshes</code> and their mesh parts.
+     *     <em>Read-only.</em>
+     * @property {Object.<string,Graphics.MaterialLayer[]>} materialLayers - The mapping from mesh parts and material
+     *     names to material layers. The mesh parts are numbered from <code>"0"</code> per the array indexes of 
+     *     <code>materialNames</code>. The material names are those used in <code>materialNames</code>. (You can look up a 
+     *     material layer by mesh part number or by material name.)
+     *     <em>Read-only.</em>
      */
-
     class ScriptableModel : public ScriptableModelBase {
         Q_OBJECT
         Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT)
@@ -49,7 +70,23 @@ namespace scriptable {
         QVector<QString> getMaterialNames() { return materialNames; }
 
     public slots:
+
+        /**jsdoc
+         * Makes a copy of the model.
+         * @function GraphicsModel.cloneModel
+         * @param {object} [options] - <em>Not used.</em>
+         * @returns {GraphicsModel} A copy of the model.
+         */
         scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
+        
+        /**jsdoc
+         * Gets a string description of the model.
+         * @function GraphicsModel.toString
+         * @returns {string} A string description of the model.
+         * @example <caption>Report the string description of your avatar's model.</caption>
+         * var model = Graphics.getModel(MyAvatar.sessionUUID);
+         * print("Avatar model info:", model.toString());
+         */
         QString toString() const;
 
     protected:
diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp
index 301f5d8d73..076cb92dcf 100644
--- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp
+++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp
@@ -34,6 +34,50 @@ namespace buffer_helpers {
 const std::array<const char*, 4> XYZW = { { "x", "y", "z", "w" } };
 const std::array<const char*, 4> ZERO123 = { { "0", "1", "2", "3" } };
 
+/**jsdoc
+ * <p>The type name of a graphics buffer.</p>
+ * <table>
+ *   <thead>
+ *     <tr><th>Value</th><th>Description</th></tr>
+ *   </thead>
+ *   <tbody>
+ *     <tr><td><code>"position"</code></td><td>Position buffer.</td></tr>
+ *     <tr><td><code>"normal"</code></td><td>normal buffer.</td></tr>
+ *     <tr><td><code>"tangent"</code></td><td>Tangent buffer.</td></tr>
+ *     <tr><td><code>"color"</code></td><td>Color buffer.</td></tr>
+ *     <tr><td><code>"skin_cluster_index"</code></td><td>Skin cluster index buffer.</td></tr>
+ *     <tr><td><code>"skin_cluster_weight"</code></td><td>Skin cluster weight buffer.</td></tr>
+ *     <tr><td><code>"texcoord0"</code></td><td>First UV coordinates buffer.</td></tr>
+ *     <tr><td><code>"texcoord1"</code></td><td>Second UV coordinates buffer.</td></tr>
+ *     <tr><td><code>"texcoord2"</code></td><td>Third UV coordinates buffer.</td></tr>
+ *     <tr><td><code>"texcoord3"</code></td><td>Fourth UV coordinates buffer.</td></tr>
+ *     <tr><td><code>"texcoord4"</code></td><td>Fifth UV coordinates buffer.</td></tr>
+ *   </tbody>
+ * </table>
+ * @typedef {string} Graphics.BufferTypeName
+ */
+/**jsdoc
+ * <p>The type of a graphics buffer value as accessed by JavaScript.</p>
+ * <table>
+ *   <thead>
+ *     <tr><th>Type</th><th>Name</th><th>Description</th></tr>
+ *   </thead>
+ *   <tbody>
+ *     <tr><td>{@link Vec3}</td><td><code>"position"</code></td><td>Position buffer.</td></tr>
+ *     <tr><td>{@link Vec3}</td><td><code>"normal"</code></td><td>normal buffer.</td></tr>
+ *     <tr><td>{@link Vec3}</td><td><code>"tangent"</code></td><td>Tangent buffer.</td></tr>
+ *     <tr><td>{@link Vec4}</td><td><code>"color"</code></td><td>Color buffer.</td></tr>
+ *     <tr><td>{@link Vec4}</td><td><code>"skin_cluster_index"</code></td><td>Skin cluster index buffer.</td></tr>
+ *     <tr><td>{@link Vec4}</td><td><code>"skin_cluster_weight"</code></td><td>Skin cluster weight buffer.</td></tr>
+ *     <tr><td>{@link Vec2}</td><td><code>"texcoord0"</code></td><td>First UV coordinates buffer.</td></tr>
+ *     <tr><td>{@link Vec2}</td><td><code>"texcoord1"</code></td><td>Second UV coordinates buffer.</td></tr>
+ *     <tr><td>{@link Vec2}</td><td><code>"texcoord2"</code></td><td>Third UV coordinates buffer.</td></tr>
+ *     <tr><td>{@link Vec2}</td><td><code>"texcoord3"</code></td><td>Fourth UV coordinates buffer.</td></tr>
+ *     <tr><td>{@link Vec2}</td><td><code>"texcoord4"</code></td><td>Fifth UV coordinates buffer.</td></tr>
+ *   </tbody>
+ * </table>
+ * @typedef {Vec3|vec2} Graphics.BufferType
+ */
 QMap<QString,int> ATTRIBUTES{
     {"position", gpu::Stream::POSITION },
     {"normal", gpu::Stream::NORMAL },
diff --git a/libraries/graphics/src/graphics/Geometry.h b/libraries/graphics/src/graphics/Geometry.h
index 20018ba71b..fe1981c0e9 100755
--- a/libraries/graphics/src/graphics/Geometry.h
+++ b/libraries/graphics/src/graphics/Geometry.h
@@ -79,23 +79,6 @@ public:
     // Access vertex position value
     const Vec3& getPos(Index index) const { return _vertexBuffer.get<Vec3>(index); }
 
-    /**jsdoc
-     * <table>
-     *   <thead>
-     *     <tr><th>Value</th><th>Description</th></tr>
-     *   </thead>
-     *   <tbody>
-     *     <tr><td><code>0</code></td><td>Points.</td></tr>
-     *     <tr><td><code>1</code></td><td>Lines.</td></tr>
-     *     <tr><td><code>2</code></td><td>Line strip.</td></tr>
-     *     <tr><td><code>3</code></td><td>Triangles.</td></tr>
-     *     <tr><td><code>4</code></td><td>Triangle strip.</td></tr>
-     *     <tr><td><code>5</code></td><td>Quads.</td></tr>
-     *     <tr><td><code>6</code></td><td>Quad strip.</td></tr>
-     *   </tbody>
-     * </table>
-     * @typedef {number} Graphics.Topology
-     */
     enum Topology {
         POINTS = 0,
         LINES,
diff --git a/libraries/graphics/src/graphics/GpuHelpers.cpp b/libraries/graphics/src/graphics/GpuHelpers.cpp
index b864b0f040..dd911e33c2 100644
--- a/libraries/graphics/src/graphics/GpuHelpers.cpp
+++ b/libraries/graphics/src/graphics/GpuHelpers.cpp
@@ -8,6 +8,24 @@
 
 #include "GpuHelpers.h"
 
+/**jsdoc
+ * <p>The interpretation of mesh elements.</p>
+ * <table>
+ *   <thead>
+ *     <tr><th>Value</th><th>Description</th></tr>
+ *   </thead>
+ *   <tbody>
+ *     <tr><td><code>"points"</code></td><td>Points.</td></tr>
+ *     <tr><td><code>"lines"</code></td><td>Lines.</td></tr>
+ *     <tr><td><code>"line_strip"</code></td><td>Line strip.</td></tr>
+ *     <tr><td><code>"triangles"</code></td><td>Triangles.</td></tr>
+ *     <tr><td><code>"triangle_strip"</code></td><td>Triangle strip.</td></tr>
+ *     <tr><td><code>"quads"</code></td><td>Quads.</td></tr>
+ *     <tr><td><code>"quad_strip"</code></td><td>Quad strip.</td></tr>
+ *   </tbody>
+ * </table>
+ * @typedef {string} Graphics.MeshTopology
+ */
 namespace graphics {
     DebugEnums<Mesh::Topology> TOPOLOGIES{
        { Mesh::Topology::POINTS, "points" },