{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "camera": {
            "properties": {
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "direction": {
                    "$ref": "#/definitions/vector"
                },
                "up": {
                    "$ref": "#/definitions/vector"
                }
            },
            "additionalProperties": false
        },
        "objects": {
            "type": "array",
            "items": {
                "type": "object",
                "oneOf": [
                    {
                        "$ref": "#/definitions/sphere"
                    },
                    {
                        "$ref": "#/definitions/torus"
                    },
                    {
                        "$ref": "#/definitions/cone"
                    },
                    {
                        "$ref": "#/definitions/cylinder"
                    },
                    {
                        "$ref": "#/definitions/plane"
                    },
                    {
                        "$ref": "#/definitions/polygon"
                    }
                ]
            },
            "_uniqueItems": true
        },
        "lights": {
            "type": "array",
            "items": {
                "type": "object",
                "oneOf": [
                    {
                        "$ref": "#/definitions/directionLight"
                    },
                    {
                        "$ref": "#/definitions/pointLight"
                    }
                ]
            },
            "_uniqueItems": true
        },
        "ambientColour": {
            "$ref": "#/definitions/colour"
        },
        "backgroundColour": {
            "$ref": "#/definitions/colour"
        }
    },
    "definitions": {
        "vector": {
            "type": [
                "array",
                "object"
            ],
            "properties": {
                "x": {
                    "type": "number"
                },
                "y": {
                    "type": "number"
                },
                "z": {
                    "type": "number"
                }
            },
            "minItems": 0,
            "maxItems": 3,
            "additionalProperties": false
        },
        "colour": {
            "type": [
                "array",
                "object"
            ],
            "properties": {
                "r": {
                    "type": "number"
                },
                "g": {
                    "type": "number"
                },
                "b": {
                    "type": "number"
                },
                "a": {
                    "type": "number"
                }
            },
            "minItems": 0,
            "maxItems": 4,
            "additionalProperties": false
        },
        "material": {
            "oneOf": [
                {
                    "$ref": "#/definitions/solidMaterial"
                },
                {
                    "$ref": "#/definitions/textureMaterial"
                },
                {
                    "$ref": "#/definitions/stripedMaterial"
                }
            ]
        },
        "solidMaterial": {
            "properties": {
                "type": {
                    "enum": [
                        "solid"
                    ]
                },
                "colour": {
                    "$ref": "#/definitions/colour"
                },
                "reflectivity": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                },
                "refractivity": {
                    "minimum": -1,
                    "maximum": 1
                },
                "specularity": {
                    "type": "number"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "colour"
            ]
        },
        "textureMaterial": {
            "properties": {
                "type": {
                    "enum": [
                        "texture"
                    ]
                },
                "path": {
                    "type": "string"
                },
                "scaling": {
                    "$ref": "#/definitions/vector"
                },
                "reflectivity": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                },
                "refractivity": {
                    "minimum": -1,
                    "maximum": 1
                },
                "specularity": {
                    "type": "number"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "path"
            ]
        },
        "stripedMaterial": {
            "properties": {
                "type": {
                    "enum": [
                        "pattern-stripe"
                    ]
                },
                "direction": {
                    "enum": [
                        "horizontal",
                        "vertical"
                    ]
                },
                "multiplier": {
                    "type": "number"
                },
                "colour1": {
                    "$ref": "#/definitions/colour"
                },
                "colour2": {
                    "$ref": "#/definitions/colour"
                },
                "reflectivity": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                },
                "refractivity": {
                    "minimum": -1,
                    "maximum": 1
                },
                "specularity": {
                    "type": "number"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "direction",
                "multiplier",
                "colour1",
                "colour2"
            ]
        },
        "sphere": {
            "properties": {
                "type": {
                    "enum": [
                        "sphere"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "radius": {
                    "type": "number",
                    "minimum": 0
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "radius",
                "material"
            ]
        },
        "torus": {
            "properties": {
                "type": {
                    "enum": [
                        "torus"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "majorRadius": {
                    "type": "number",
                    "minimum": 0
                },
                "minorRadius": {
                    "type": "number",
                    "minimum": 0
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "majorRadius",
                "minorRadius",
                "material"
            ]
        },
        "cone": {
            "properties": {
                "type": {
                    "enum": [
                        "cone"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "radius": {
                    "type": "number",
                    "minimum": 0
                },
                "height": {
                    "type": "number",
                    "minimum": 0
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "radius",
                "height",
                "material"
            ]
        },
        "cylinder": {
            "properties": {
                "type": {
                    "enum": [
                        "cylinder"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "radius": {
                    "type": "number",
                    "minimum": 0
                },
                "height": {
                    "type": "number",
                    "minimum": 0
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "radius",
                "height",
                "material"
            ]
        },
        "plane": {
            "properties": {
                "type": {
                    "enum": [
                        "plane"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "normal": {
                    "$ref": "#/definitions/vector"
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "normal",
                "material"
            ]
        },
        "polygon": {
            "properties": {
                "type": {
                    "enum": [
                        "polygon"
                    ]
                },
                "points": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/vector"
                    },
                    "minItems": 3,
                    "maxItems": 4,
                    "_uniqueItems": true
                },
                "texCoords": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/vector"
                    },
                    "minItems": 3,
                    "maxItems": 4
                },
                "material": {
                    "$ref": "#/definitions/material"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "points",
                "material"
            ]
        },
        "directionLight": {
            "properties": {
                "type": {
                    "enum": [
                        "direction"
                    ]
                },
                "direction": {
                    "$ref": "#/definitions/vector"
                },
                "colour": {
                    "$ref": "#/definitions/colour"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "direction",
                "colour"
            ]
        },
        "pointLight": {
            "properties": {
                "type": {
                    "enum": [
                        "point"
                    ]
                },
                "position": {
                    "$ref": "#/definitions/vector"
                },
                "colour": {
                    "$ref": "#/definitions/colour"
                },
                "attenuation-constant": {
                    "type": "number"
                },
                "attenuation-linear": {
                    "type": "number"
                },
                "attenuation-quadratic": {
                    "type": "number"
                }
            },
            "additionalProperties": false,
            "required": [
                "type",
                "position",
                "colour",
                "attenuation-constant",
                "attenuation-linear",
                "attenuation-quadratic"
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "objects"
    ]
}