Exemple #1
0
Matrix4::Matrix4(const Any& any) {
    any.verifyName("Matrix4");
    any.verifyType(Any::ARRAY);

    const std::string& name = toLower(any.name());
    if (name == "matrix4") {
        any.verifySize(16);

        for (int r = 0; r < 4; ++r) {
            for (int c = 0; c < 4; ++c) {
                elt[r][c] = any[r * 4 + c];
            }
        }
    } else if (name == "matrix4::scale") {
        if (any.size() == 1) {
            *this = scale(any[0].number());
        } else if (any.size() == 3) {
            *this = scale(any[0], any[1], any[2]);
        } else {
            any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
        }
    } else if (name == "matrix4::translation") {
        if (any.size() == 3) {
            *this = translation(any[0], any[1], any[2]);
        } else {
            any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
        }    } else {
        any.verify(false, "Expected Matrix4 constructor");
    }
}
ArticulatedModel::Instruction::Identifier::Identifier(const Any& a) {
    switch (a.type()) {
    case Any::NUMBER:
        id = ID(iRound(a.number()));
        a.verify(id >= 0, "Illegal ID");
        break;

    case Any::STRING:
        name = a.string();
        break;

    case Any::ARRAY:
        a.verifySize(0);
        if (a.name() == "root") {
            *this = root();
        } else if (a.name() == "all") {
            *this = all();
        } else {
            a.verify(false, "Illegal function call: " + a.name());
        }
        break;

    default:
        a.verify(false, "Expected a name, integer ID, root(), or all()");
    }
}
PhysicsFrame::PhysicsFrame(const Any& a) {
    const std::string& n = toLower(a.name());
    *this = PhysicsFrame();

    if (beginsWith(n, "vector3")) {
        *this = PhysicsFrame(Vector3(a));
    } else if (beginsWith(n, "matrix3")) {        
        *this = PhysicsFrame(Matrix3(a));
    } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe")) {        
        *this = PhysicsFrame(CoordinateFrame(a));
    } else if (beginsWith(n, "pframe") || beginsWith(n, "physicsframe")) {
        if (a.type() == Any::ARRAY) {
            a.verifySize(2);
            rotation    = a[0];
            translation = a[1];
        } else {
            for (Any::AnyTable::Iterator it = a.table().begin(); it.hasMore(); ++it) {
                const std::string& n = toLower(it->key);
                if (n == "translation") {
                    translation = it->value;
                } else if (n == "rotation") {
                    rotation = it->value;
                } else {
                    a.verify(false, "Illegal table key: " + it->key);
                }
            }
        }
    }
}
Exemple #4
0
Sampler::Sampler(const Any& any) {
    *this = Sampler::defaults();
    any.verifyNameBeginsWith("Sampler");
    if (any.type() == Any::TABLE) {
        AnyTableReader r(any);
        r.getIfPresent("maxAnisotropy", maxAnisotropy);
        r.getIfPresent("maxMipMap", maxMipMap);
        r.getIfPresent("minMipMap", minMipMap);
        r.getIfPresent("mipBias", mipBias);
        r.getIfPresent("xWrapMode", xWrapMode);
        if (! r.getIfPresent("yWrapMode", yWrapMode)) {
            yWrapMode = xWrapMode;
        }
        r.getIfPresent("depthReadMode", depthReadMode);
        r.getIfPresent("interpolateMode", interpolateMode);
        r.verifyDone();
    } else {
        any.verifySize(0);
        const String& n = any.name();
        if (n == "Sampler::defaults") {
            // Done!
        } else if (n == "Sampler::buffer") {
            *this = Sampler::buffer();
        } else if (n == "Sampler::cubeMap") {
            *this = Sampler::cubeMap();
        } else if (n == "Sampler::shadow") {
            *this = Sampler::shadow();
        } else if (n == "Sampler::video") {
            *this = Sampler::video();
        } else {
            any.verify(false, "Unrecognized name for Sampler constructor or factory method.");
        }
    }
}
Exemple #5
0
Matrix4::Matrix4(const Any& any) {
    any.verifyNameBeginsWith("Matrix4", "CFrame", "CoordinateFrame");
    any.verifyType(Any::ARRAY);

    const std::string& name = any.name();
    if (name == "Matrix4") {
        any.verifySize(16);

        for (int r = 0; r < 4; ++r) {
            for (int c = 0; c < 4; ++c) {
                elt[r][c] = any[r * 4 + c];
            }
        }
    } else if (name == "Matrix4::scale") {
        if (any.size() == 1) {
            *this = scale(any[0].floatValue());
        } else if (any.size() == 3) {
            *this = scale(any[0], any[1], any[2]);
        } else {
            any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
        }
    } else if (name == "Matrix4::rollDegrees") {
        any.verifySize(1);
        *this = rollDegrees(any[0].floatValue());
    } else if (name == "Matrix4::yawDegrees") {
        any.verifySize(1);
        *this = yawDegrees(any[0].floatValue());
    } else if (name == "Matrix4::pitchDegrees") {
        any.verifySize(1);
        *this = pitchDegrees(any[0].floatValue());
    } else if (name == "Matrix4::translation") {
        if (any.size() == 3) {
            *this = translation(any[0], any[1], any[2]);
        } else {
            any.verify(false, "Matrix4::translation() requires 3 arguments");
        }    
    } else if (name == "Matrix4::diagonal") {
        any.verifySize(4);
        *this = diagonal(any[0], any[1], any[2], any[3]);
    } else if (name == "Matrix4::identity") {
        *this = identity();
    } else if (beginsWith(name, "CFrame") || beginsWith(name, "CoordinateFrame")) {
        *this = CFrame(any);
    } else {
        any.verify(false, "Expected Matrix4 constructor");
    }
}
Texture::Preprocess::Preprocess(const Any& any) {
    *this = Preprocess::defaults();
    any.verifyNameBeginsWith("Texture::Preprocess");
    if (any.type() == Any::TABLE) {
        for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
            const String& key = it->key;
            if (key == "modulate") {
                modulate = Color4(it->value);
            } else if (key == "gammaAdjust") {
                gammaAdjust = it->value;
            } else if (key == "scaleFactor") {
                scaleFactor = it->value;
            } else if (key == "computeMinMaxMean") {
                computeMinMaxMean = it->value;
            } else if (key == "computeNormalMap") {
                computeNormalMap = it->value;
            } else if (key == "convertToPremultipliedAlpha") {
                convertToPremultipliedAlpha = it->value;
            } else if (key == "bumpMapPreprocess") {
                bumpMapPreprocess = it->value;
            } else {
                any.verify(false, "Illegal key: " + it->key);
            }
        }
    } else {
        const String& n = any.name();
        if (n == "Texture::Preprocess::defaults") {
            any.verifySize(0);
        } else if (n == "Texture::Preprocess::gamma") {
            any.verifySize(1);
            *this = Texture::Preprocess::gamma(any[0]);
        } else if (n == "Texture::preprocess::none") {
            any.verifySize(0);
            *this = Texture::Preprocess::none();
        } else if (n == "Texture::Preprocess::quake") {
            any.verifySize(0);
            *this = Texture::Preprocess::quake();
        } else if (n == "Texture::Preprocess::normalMap") {
            any.verifySize(0);
            *this = Texture::Preprocess::normalMap();
        } else {
            any.verify(false, "Unrecognized name for Texture::Preprocess constructor or factory method.");
        }
    }
}
Exemple #7
0
ParticleSystemModel::Emitter::Specification::Specification(const Any& a) {
    a.verifyNameBeginsWith("ParticleSystemModel::Emitter");
    *this = Specification();
    AnyTableReader r(a);
    r.getIfPresent("location", location);
    r.getIfPresent("noisePower", noisePower);
    r.getIfPresent("initialDensity", initialDensity);
    r.getIfPresent("rateCurve", rateCurve);
    r.getIfPresent("coverageFadeInTime", coverageFadeInTime);
    r.getIfPresent("coverageFadeOutTime", coverageFadeOutTime);
    r.getIfPresent("particleLifetimeMean", particleLifetimeMean);
    r.getIfPresent("particleLifetimeVariance", particleLifetimeVariance);
    r.getIfPresent("angularVelocityMean", angularVelocityMean);
    r.getIfPresent("angularVelocityVariance", angularVelocityVariance);
    r.getIfPresent("material", material);
    r.getIfPresent("radiusMean", radiusMean);
    r.getIfPresent("radiusVariance", radiusVariance);
    r.getIfPresent("particleMassDensity", particleMassDensity);
    r.getIfPresent("dragCoefficient", dragCoefficient);

    shapeType = Shape::Type::NONE;
    Any shape;
    if (r.getIfPresent("shape", shape)) {
        if (shape.nameBeginsWith("ArticulatedModel") || (shape.type() == Any::STRING)) {
            shapeType = Shape::Type::MESH;
        } else {
            shapeType = Shape::Type(toUpper(shape.name()));
        }

        switch (shapeType) {
        case Shape::Type::BOX:
            box = Box(shape);
            break;

        case Shape::Type::CYLINDER:
            cylinder = Cylinder(shape);
            break;

        case Shape::Type::SPHERE:
            sphere = Sphere(shape);
            break;

        case Shape::Type::MESH:
            mesh = shape;
            break;

        default:
            shape.verify(false, "Shape must be a Box, Cylinder, Sphere, or ArticulatedModel specification");
        }
    }

    r.getIfPresent("velocityDirectionMean", velocityDirectionMean);
    r.getIfPresent("velocityConeAngleDegrees", velocityConeAngleDegrees);
    r.getIfPresent("velocityMagnitudeMean", velocityMagnitudeMean);
    r.getIfPresent("velocityMagnitudeVariance", velocityMagnitudeVariance);
    r.verifyDone();
}
Exemple #8
0
void VisibleEntity::init
   (AnyTableReader&    propertyTable,
    const ModelTable&  modelTable) {

    bool visible = true;
    propertyTable.getIfPresent("visible", visible);

    ArticulatedModel::Pose artPose;
    propertyTable.getIfPresent("articulatedModelPose", artPose);

    ArticulatedModel::PoseSpline artPoseSpline;
    propertyTable.getIfPresent("poseSpline", artPoseSpline);

	MD3Model::PoseSequence md3PoseSequence;
	propertyTable.getIfPresent("md3Pose", md3PoseSequence);

    Surface::ExpressiveLightScatteringProperties expressiveLightScatteringProperties;
    propertyTable.getIfPresent("expressiveLightScatteringProperties", expressiveLightScatteringProperties);
    
    if (propertyTable.getIfPresent("castsShadows", expressiveLightScatteringProperties.castsShadows)) {
        debugPrintf("Warning: castsShadows field is deprecated.  Use expressiveLightScatteringProperties");
    }    

    const lazy_ptr<Model>* model = NULL;
    Any modelNameAny;
    if (propertyTable.getIfPresent("model", modelNameAny)) {
        const String& modelName     = modelNameAny.string();
    
        modelNameAny.verify(modelTable.containsKey(modelName), 
                        "Can't instantiate undefined model named " + modelName + ".");
        model = modelTable.getPointer(modelName);
    }

    Any ignore;
    if (propertyTable.getIfPresent("materialTable", ignore)) {
        ignore.verify(false, "'materialTable' is deprecated. Specify materials on the articulatedModelPose field of VisibleEntity.");
    }

    init(notNull(model) ? model->resolve() : shared_ptr<Model>(), visible, expressiveLightScatteringProperties, artPoseSpline, md3PoseSequence, artPose);
}
BumpMapPreprocess::BumpMapPreprocess(const Any& any) {
    *this = BumpMapPreprocess();
    for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
        const std::string& key = toLower(it->key);
        if (key == "lowpassfilter") {
            lowPassFilter = it->value;
        } else if (key == "zextentpixels") {
            zExtentPixels = it->value;
        } else if (key == "scalezbynz") {
            scaleZByNz = it->value;
        } else {
            any.verify(false, "Illegal key: " + it->key);
        }
    }
}
Exemple #10
0
shared_ptr<Model> Scene::createModel(const Any& v, const std::string& name) {
    shared_ptr<Model> m;

    v.verify(! m_modelTable.containsKey(name), "A model named '" + name + "' already exists in this scene.");

    if ((v.type() == Any::STRING) || v.nameBeginsWith("ArticulatedModel")) {
        m = ArticulatedModel::create(v, name);

    } else if (v.nameBeginsWith("MD2Model")) {
        m = MD2Model::create(v, name);
    } else if (v.nameBeginsWith("MD3Model")) {
        m = MD3Model::create(v, name);
    } else if (v.nameBeginsWith("HeightfieldModel")) {
        m = HeightfieldModel::create(v, name);
    }

    if (isNull(m)) {
        v.verify(false, "Unrecognized model type: " + v.name());
    }

    m_modelTable.set(name, m);

    return m;
}
Exemple #11
0
BumpMap::Settings::Settings(const Any& any) {
    *this = Settings();
    any.verifyName("BumpMap::Settings");
    for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
        const std::string& key = toLower(it->key);
        if (key == "iterations") {
            iterations = iMax(0, iRound(it->value.number()));
        } else if (key == "scale") {
            scale = it->value;
        } else if (key == "bias") {
            bias = it->value;
        } else {
            any.verify(false, "Illegal key: " + it->key);
        }
    }
}
Exemple #12
0
ParseOBJ::Options::Options(const Any& a) {
    *this = Options();
    a.verifyName("OBJOptions");
    AnyTableReader r(a);
    String s;
    if (r.getIfPresent("texCoord1Mode", s)) {
        if      (s == "NONE")         { texCoord1Mode = NONE; }
        else if (s == "UNPACK_FROM_TEXCOORD0_Z")      { texCoord1Mode = UNPACK_FROM_TEXCOORD0_Z; }
        else if (s == "TEXCOORD0_ZW") { texCoord1Mode = TEXCOORD0_ZW; }
        else { a.verify(false, "Unexpected value for texCoord3DMode"); }
    }

	r.getIfPresent("stripRefraction", stripRefraction);
//    r.getIfPresent("sampler", sampler);

	r.verifyDone();
}
Texture::Visualization::Visualization(const Any& a) {
    *this = Visualization();
    if (a.type() == Any::ARRAY) {
        if (a.nameEquals("bumpInAlpha")) {
            *this = bumpInAlpha();
        } else if (a.nameEquals("defaults")) {
            *this = defaults();
        } else if (a.nameEquals("linearRGB")) {
            *this = linearRGB();
        } else if (a.nameEquals("depthBuffer")) {
            *this = depthBuffer();
        } else if (a.nameEquals("packedUnitVector")) {
            *this = packedUnitVector();
        } else if (a.nameEquals("radiance")) {
            *this = radiance();
        } else if (a.nameEquals("reflectivity")) {
            *this = reflectivity();
        } else if (a.nameEquals("sRGB")) {
            *this = sRGB();
        } else if (a.nameEquals("unitVector")) {
            *this = unitVector();
        } else {
            a.verify(false, "Unrecognized Visualization factory method");
        }
    } else {
        a.verifyName("Texture::Visualization", "Visualization");

        AnyTableReader r(a);
        String c;

        if (r.getIfPresent("channels", c)) {
            channels = toChannels(c);
        }

        r.getIfPresent("documentGamma", documentGamma);
        r.getIfPresent("invertIntensity", invertIntensity);
        r.getIfPresent("max", max);
        r.getIfPresent("min", min);
        r.getIfPresent("layer", layer);
        r.getIfPresent("mipLevel", mipLevel);

        r.verifyDone();
    }
}
Exemple #14
0
void Scene::createEntity(const std::string& entityType, const std::string& name, const Any& any) {
    AnyTableReader propertyTable(any);

    if (entityType == "VisibleEntity") {
        insert(VisibleEntity::create(name, this, propertyTable, m_modelTable));
    } else if (entityType == "Light") {
        insert(Light::create(name, this, propertyTable));
    } else if (entityType == "Camera") {
        insert(Camera::create(name, this, propertyTable));
    } else if (entityType == "MarkerEntity") {
        insert(MarkerEntity::create(name, this, propertyTable));
    } else if (entityType == "Skybox") {
        insert(Skybox::create(name, this, propertyTable));
    } else {
        any.verify(false, std::string("Unrecognized Entity type: \"") + entityType + "\"");
    }
        
    m_lastStructuralChangeTime = System::time();
}
CoordinateFrame::CoordinateFrame(const Any& any) {
    *this = CFrame();

    const std::string& n = toUpper(any.name());

    if (beginsWith(n, "VECTOR3")) {
        translation = any;
    } else if (beginsWith(n, "MATRIX3")) {
        rotation = any;
    } else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
        any.verifyType(Any::TABLE, Any::ARRAY);
        if (any.type() == Any::ARRAY) {
            any.verifySize(2);
            rotation    = any[0];
            translation = any[1];
        } else {
            for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
                const std::string& n = toLower(it->key);
                if (n == "translation") {
                    translation = Vector3(it->value);
                } else if (n == "rotation") {
                    rotation = Matrix3(it->value);
                } else {
                    any.verify(false, "Illegal table key: " + it->key);
                }
            }
        }
    } else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
        *this = PhysicsFrame(any);
    } else {
        any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
        any.verifyType(Any::ARRAY);
        any.verifySize(3, 6);

        int s = any.size();

        *this = fromXYZYPRDegrees(any[0], any[1], any[2],
                                  (s > 3) ? any[3].number() : 0.0f,
                                  (s > 4) ? any[4].number() : 0.0f,
                                  (s > 5) ? any[5].number() : 0.0f);
    }
}
Exemple #16
0
BumpMap::Specification::Specification(const Any& any) {
    if (any.type() == Any::STRING) {
        // Treat as a filename
        texture.filename = any.resolveStringAsFilename();
        texture.preprocess = Texture::Preprocess::normalMap();
    } else {
        for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
            const std::string& key = toLower(it->key);
            if (key == "texture") {
                texture = it->value;
                if (it->value.type() == Any::STRING) {
                    // Set bump map defaults
                    texture.preprocess = Texture::Preprocess::normalMap();
                }
            } else if (key == "settings") {
                settings = it->value;
            } else {
                any.verify(false, "Illegal key: " + it->key);        
            }
        }
    }
}
Exemple #17
0
shared_ptr<Entity::Track> Entity::Track::create(Entity* entity, Scene* scene, const Any& a, const VariableTable& variableTable) {
    if (a.type() == Any::STRING) {
        // This must be an id
        const shared_ptr<Entity::Track>& c = variableTable[a.string()];
        if (isNull(c)) {
            a.verify(false, "");
        }
        return c;
    }

    if ((beginsWith(a.name(), "PhysicsFrameSpline")) ||
        (beginsWith(a.name(), "PFrameSpline")) ||
        (beginsWith(a.name(), "Point3")) || 
        (beginsWith(a.name(), "Vector3")) || 
        (beginsWith(a.name(), "Matrix3")) || 
        (beginsWith(a.name(), "Matrix4")) || 
        (beginsWith(a.name(), "CFrame")) || 
        (beginsWith(a.name(), "PFrame")) || 
        (beginsWith(a.name(), "UprightSpline")) || 
        (beginsWith(a.name(), "CoordinateFrame")) || 
        (beginsWith(a.name(), "PhysicsFrame"))) {

        return Entity::SplineTrack::create(a);

    } else if (a.name() == "entity") {

        // Name of an Entity
        const std::string& targetName = a[0].string();
        alwaysAssertM(notNull(scene) && notNull(entity), "entity() Track requires non-NULL Scene and Entity");
        debugAssert(targetName != "");
        scene->setOrder(entity->name(), targetName);
        return shared_ptr<Entity::Track>(new TrackEntityTrack(targetName, scene));

    } else if (a.name() == "transform") {

        return shared_ptr<Entity::Track>
            (new TransformTrack(create(entity, scene, a[0], variableTable), 
                                create(entity, scene, a[1], variableTable)));

    } else if (a.name() == "follow") {

        a.verify(false, "follow Tracks are unimplemented");
        return shared_ptr<Entity::Track>();
        // return shared_ptr<Entity::Track>(new TransformTrack(create(a[0]), create(a[1])));

	} else if (a.name() == "orbit") {

        return shared_ptr<Entity::Track>(new OrbitTrack(a[0], a[1]));

    } else if (a.name() == "combine") {

        return shared_ptr<Entity::Track>
            (new CombineTrack(create(entity, scene, a[0], variableTable), 
                                   create(entity, scene, a[1], variableTable)));

    } else if (a.name() == "lookAt") {

        return shared_ptr<Entity::Track>
            (new LookAtTrack(create(entity, scene, a[0], variableTable), 
                                  create(entity, scene, a[1], variableTable), (a.size() > 2) ? Vector3(a[2]) : Vector3::unitY()));

    } else if (a.name() == "timeShift") {

        shared_ptr<Track> p = create(entity, scene, a[0], variableTable);
        a.verify(notNull(dynamic_pointer_cast<SplineTrack>(p)) || notNull(dynamic_pointer_cast<OrbitTrack>(p)), "timeShift() requires a PhysicsFrameSpline or orbit");
        return shared_ptr<Entity::Track>(new TimeShiftTrack(p, a[1].number()));

    } else if (a.name() == "with") {

        // Create a new variable table and recurse
        VariableTable extendedTable(&variableTable);

        const Any& vars = a[0];
        for (Table<std::string, Any>::Iterator it = vars.table().begin(); it.isValid(); ++it) {
            // Note that if Any allowed iteration through its table in definition order, then
            // we could implement Scheme LET* instead of LET here.
            extendedTable.set(it->key, create(entity, scene, it->value, variableTable));
        }

        return create(entity, scene, a[1], extendedTable);

    } else {

        // Some failure
        a.verify(false, "Unrecognized Entity::Track type");
        return shared_ptr<Entity::Track>();

    }
}
Exemple #18
0
GLight::GLight(const Any& any) {
    any.verifyName("GLight");

    if (any.type() == Any::TABLE) {
        *this = GLight();
        Vector3 spotTarget;
        bool hasSpotTarget = false;
        for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
            const std::string& key = toLower(it->key);
            if (key == "position") {
                position = it->value;
            } else if (key == "rightdirection") {
                rightDirection = it->value;
            } else if (key == "spotdirection") {
                spotDirection = Vector3(it->value).directionOrZero();
            } else if (key == "spottarget") {
                spotTarget = it->value;
                hasSpotTarget = true;
            } else if (key == "spotcutoff") {
                spotCutoff = it->value.number();
            } else if (key == "spotsquare") {
                spotSquare = it->value.boolean();
            } else if (key == "attenuation") {
                attenuation[0] = it->value[0].number();
                attenuation[1] = it->value[1].number();
                attenuation[2] = it->value[2].number();
            } else if (key == "color") {
                color = it->value;
            } else if (key == "enabled") {
                enabled = it->value.boolean();
            } else if (key == "specular") {
                specular = it->value.boolean();
            } else if (key == "diffuse") {
                diffuse = it->value.boolean();
            } else {
                any.verify(false, "Illegal key: " + it->key);
            }
        }
        if (hasSpotTarget) {
            spotDirection = (spotTarget - position.xyz()).direction();
        }
    } else if (toLower(any.name()) == "glight::directional") {

        *this = directional(any[0], any[1], 
            (any.size() > 2) ? any[2] : Any(true), 
            (any.size() > 3) ? any[3] : Any(true));

    } else if (toLower(any.name()) == "glight::point") {

        *this = point(any[0], any[1], 
            (any.size() > 2) ? any[2] : Any(1), 
            (any.size() > 3) ? any[3] : Any(0), 
            (any.size() > 4) ? any[4] : Any(0.5f), 
            (any.size() > 5) ? any[5] : Any(true), 
            (any.size() > 6) ? any[6] : Any(true));

    } else if (toLower(any.name()) == "glight::spot") {

        *this = spot(any[0], any[1], any[2], any[3],
            (any.size() > 4) ? any[4] : Any(1), 
            (any.size() > 5) ? any[5] : Any(0), 
            (any.size() > 6) ? any[6] : Any(0), 
            (any.size() > 7) ? any[7] : Any(true), 
            (any.size() > 8) ? any[8] : Any(true));
    } else {
        any.verify(false, "Unrecognized name");
    }
}
ArticulatedModel::Instruction::Instruction(const Any& any) {
    any.verifyType(Any::ARRAY);

    source = any;
    part = Identifier();
    mesh = Identifier();
    arg = Any();

    const std::string& instructionName = any.name();

    if (instructionName == "scale") {

        type = SCALE;
        any.verifySize(1);
        arg = any[0];

    } else if (instructionName == "moveCenterToOrigin") {

        type = MOVE_CENTER_TO_ORIGIN;
        any.verifySize(0);

    } else if (instructionName == "moveBaseToOrigin") {

        type = MOVE_BASE_TO_ORIGIN;
        any.verifySize(0);

    } else if (instructionName == "setCFrame") {

        type = SET_CFRAME;
        any.verifySize(2);
        part = any[0];
        arg = any[1];

    } else if (instructionName == "transformCFrame") {

        type = TRANSFORM_CFRAME;
        any.verifySize(2);
        part = any[0];
        arg = any[1];

    } else if (instructionName == "transformGeometry") {

        type = TRANSFORM_GEOMETRY;
        any.verifySize(2);
        part = any[0];
        arg = any[1];

    } else if (instructionName == "deleteMesh") {

        type = DELETE_MESH;
        any.verifySize(2);
        part = any[0];
        mesh = any[1];

    } else if (instructionName == "deletePart") {

        type = DELETE_PART;
        any.verifySize(1);
        part = any[0];

    } else if (instructionName == "setMaterial") {

        type = SET_MATERIAL;
        any.verifySize(3);
        part = any[0];
        mesh = any[1];
        arg = any[2];

    } else if (instructionName == "setTwoSided") {

        type = SET_TWO_SIDED;
        any.verifySize(3);
        part = any[0];
        mesh = any[1];
        arg = any[2];

    } else if (instructionName == "mergeAll") {

        type = MERGE_ALL;
        any.verifySize(0);

    } else if (instructionName == "renamePart") {

        type = RENAME_PART;
        any.verifySize(2);
        part = any[0];
        arg = any[1];

    } else if (instructionName == "renameMesh") {

        type = RENAME_MESH;
        any.verifySize(3);
        part = any[0];
        mesh = any[1];
        arg = any[2];

    } else if (instructionName == "add") {

        type = ADD;
        mesh = Identifier::none();
        if (any.size() == 2) {
            any.verifySize(2);
            part = any[0];
            arg = any[1];
        } else {
            any.verifySize(1);
            part = Identifier::none();
            arg = any[0];
        }

    } else {

        any.verify(false, std::string("Unknown instruction: \"") + instructionName + "\"");

    }
}