示例#1
0
void Engine::make_litcube(std::string name, glm::vec4 color,
                          glm::vec3 scale, float mass,
                          glm::vec3 position, glm::quat orientation) {
    Shader* shader = shaders["light1"];
    Node* node = nodes[name] =
            new Node(nodes["scene"], position, orientation);
    VAO* vao = parse_obj_file("data/cube.obj", scale);
    std::vector<Uniform*> material;

    StoredUniform<glm::vec4>* mycolor =
            new StoredUniform<glm::vec4>(shader, "mycolor", color);
    material.push_back(mycolor);

    Renderable* renderable =
            new LitRenderObject(shader, node, vao, material);
    renderables.push_back(renderable);

    // mem
    vaos.push_back(vao);
    uniforms.push_back(mycolor);

    if (mass >= 0.f) {
        // physics
        btCollisionShape* cube_shape = new btBoxShape(from_vec3(scale/2.f));

        physics->add_rigid_body(
                create_rigid_body(mass, node, cube_shape));

        // mem
        collision_shapes.push_back(cube_shape);
    }
}
示例#2
0
    void trimesh::create_physical_body(
                    double x, 
                    double y, 
                    double z, 
                    double size_x, 
                    double size_y,
                    double size_z,
                    double mass, 
                    std::vector<double>& vertices_vec,
                    std::vector<int>& indices_vec,
                    const std::string name,
                   manager& mgr)
    {
        world_id = mgr.ode_world();
        space_id = mgr.ode_space();

        //see if the trimesh data is cached so that we don't have to recreate it
        if(name.size() > 0) mesh_data = mgr.trimesh_cache().get_data(name);

        //if it is not cached then we create the trimesh data and put it in the cache
        if(!mesh_data)
        {
            trimesh_data* new_data = create_trimesh_data(vertices_vec, indices_vec);
            if(new_data == 0)
            {
                std::cout << "Error creating trimesh: " << name << std::endl;
                return; //TODO should throw instead...
            }
            mesh_data = trimesh_data_cache::data_ptr(new_data);
            mgr.trimesh_cache().cache_data(name, mesh_data);
        }

        //create the geom using the trimesh data
        geom_id = dCreateTriMesh(mgr.ode_space(),mesh_data->data_id, 0, 0, 0); 

        object::set_geom_data(geom_id);
        //create and position the geom to represent the pysical shape of the rigid body   
        dGeomSetPosition (geom_id, x, y, z); //we position it at the center relative to the body
        //if the mass is greater than 0 then the object is a dynamic mesh
        //so we have to create a rigid body
        if(mass > 0)
        {
            create_rigid_body(x, y, z,  mgr);
            size[0] = size_x;
            size[1] = size_y;
            size[2] = size_z;
            set_mass(mass);
            dGeomSetBody (geom_id, body_id); 
        }
    }
示例#3
0
void MiuraModel::makeMiura(int vehicle_id,
                           DisplayInterface * di,
                           bool add_ghost,
                           const btVector3 & origin,
                           float rotation)
{
    if (!vehicle_config_ptr) return;

btRigidBody * ghost = 0;
// miurabody0
    if (add_ghost)
    {
    btTriangleIndexVertexArray * miurabody0_mi = new btTriangleIndexVertexArray();

        for (unsigned int z=0;z<miurabody0_meshes.size();z++)
        {
        Mesh m = miurabody0_meshes.at(z);

        btVector3 * va = new btVector3[m.vertices_size/3];

        unsigned int * ia = new unsigned int[m.faces_size/4];
        
        int j = -1;
            for (unsigned int ind0 = 0; ind0 < m.vertices_size; ind0+=3 )
            {
            va[++j].setValue(btScalar( *(m.p_vertices + ind0 + 0)),
                             btScalar( *(m.p_vertices + ind0 + 1)),
                             btScalar( *(m.p_vertices + ind0 + 2)));
            }

        int i = -1;
            for (unsigned int ind1 = 0; ind1 < m.faces_size; ind1+=12 )
            {
            unsigned int c1  = *(m.p_faces + ind1 + 0);
            unsigned int c2  = *(m.p_faces + ind1 + 4);
            unsigned int c3  = *(m.p_faces + ind1 + 8);
            ia[++i] = c1-1;
            ia[++i] = c2-1;
            ia[++i] = c3-1;
            }

        btIndexedMesh * im = new btIndexedMesh();
        im->m_numTriangles = m.faces_size/12;
        im->m_triangleIndexBase = reinterpret_cast<unsigned char*>(ia);
        im->m_triangleIndexStride = 3*sizeof(unsigned int);
        im->m_numVertices = j+1;
        im->m_vertexBase = reinterpret_cast<unsigned char*>(&va[0][0]);
        im->m_vertexStride = sizeof(btVector3);
        miurabody0_mi->addIndexedMesh(*im);
        ArraysTrack at;
        at.vertex_array = va;
        at.index_array  = ia;
        at.indexed_mesh = im;
        arrays_track.push_back(at);
        }

    btGImpactMeshShape * miurabody0_shape = new btGImpactMeshShape(miurabody0_mi);
    miurabody0_shape->updateBound();
    collision_shapes.push_back(miurabody0_shape);
    ArraysTrack at0;
    at0.mesh_interface = miurabody0_mi;
    arrays_track.push_back(at0);

    btTransform t;
    t.setIdentity();
    t.setOrigin(origin);
    
    MyKinematicMotionState * motion_state = new MyKinematicMotionState(t);
    btRigidBody::btRigidBodyConstructionInfo rbi(0.,motion_state,miurabody0_shape);
    ghost = new btRigidBody(rbi);
    
    int * usrP = new int[2];
    usrP[0] = vehicle_id + 1; // group id, don't collide inside the group, here group with id "1"
    usrP[1] = 2; // wheel raytest (MyVehicleRayResultCallback), "1" to process, "2" skip
    ghost->setUserPointer(usrP);
    ghost->setCollisionFlags( ghost->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
    //ghost->setCollisionFlags( ghost->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
    ghost->setActivationState(DISABLE_DEACTIVATION);
    m_dynamicsWorld->addRigidBody(ghost);
    }

VehicleConfig * vehicle_config = new VehicleConfig;
vehicle_config->vehicle_mass           = btScalar(vehicle_config_ptr[0]);
vehicle_config->max_suspension_force   = btScalar(vehicle_config_ptr[1]);
vehicle_config->suspension_stiffness   = btScalar(vehicle_config_ptr[2]);
vehicle_config->damping_relaxation     = btScalar(vehicle_config_ptr[3]);
vehicle_config->damping_compression    = btScalar(vehicle_config_ptr[4]);
vehicle_config->suspension_rest_length = btScalar(vehicle_config_ptr[5]);
vehicle_config->max_suspension_travel  = btScalar(vehicle_config_ptr[6]);
vehicle_config->roll_influence         = btScalar(vehicle_config_ptr[7]);
vehicle_config->inertia_coefficient    = btScalar(vehicle_config_ptr[8]);
//= btScalar(vehicle_config_ptr[ 9]);
//= btScalar(vehicle_config_ptr[10]);
vehicle_config->max_braking_force      = btScalar(vehicle_config_ptr[11]);
vehicle_config->steering_clamp         = btScalar(vehicle_config_ptr[12]);
vehicle_config->chassis_mass_y_shift   = btScalar(vehicle_config_ptr[13]);
vehicle_config->chassis_mass_z_shift   = btScalar(vehicle_config_ptr[14]);
vehicle_config->fwheel_radius          = btScalar(vehicle_config_ptr[15]);
vehicle_config->rwheel_radius          = btScalar(vehicle_config_ptr[16]);
vehicle_config->fwheel_width           = btScalar(vehicle_config_ptr[17]);
vehicle_config->rwheel_width           = btScalar(vehicle_config_ptr[18]);
vehicle_config->chassis_friction       = btScalar(vehicle_config_ptr[19]);
vehicle_config->chassis_restitution    = btScalar(vehicle_config_ptr[20]);
vehicle_config->chassis_angular_dump   = btScalar(vehicle_config_ptr[21]);
vehicle_config->chassis_linear_dump    = btScalar(vehicle_config_ptr[22]);
vehicle_config->steering_wheel_factor  = btScalar(vehicle_config_ptr[23]);
vehicle_config->steering_wheel_sensitivity = btScalar(vehicle_config_ptr[30]);
// = btScalar(vehicle_config_ptr[24]);
// = btScalar(vehicle_config_ptr[25]);
vehicle_config->Crr                    = btScalar(vehicle_config_ptr[29]);
vehicle_config->vehicle_steering = btScalar(0.0);
vehicle_config->origin = btVector3(origin);
vehicle_config->right_index = 0;
vehicle_config->up_index = 1;
vehicle_config->forward_index = 2;
vehicle_config->wheel_direction_CS0 = btVector3(btScalar(0.0), btScalar(-1.0), btScalar(0.0));
vehicle_config->wheel_axle_CS = btVector3(btScalar(-1.0), btScalar(0.0), btScalar(0.0));
vehicle_config->steering_wheel_axis = btVector3(btScalar(0.0), btScalar(0.371), btScalar(-0.928));
//vehicle_config->steering_wheel_pos = btVector3(world_loc_miura_rul[0],world_loc_miura_rul[1],world_loc_miura_rul[2]);
//vehicle_config->driver_pos = btVector3(btScalar(world_loc_miura[0] + 0.35f),
//                          btScalar(world_loc_miura[1] + 0.3f  - c->chassis_mass_y_shift),
//                          btScalar(world_loc_miura[2] - 0.35f - c->chassis_mass_z_shift));
btScalar f_wheel_y = btScalar(-0.308666);
btScalar r_wheel_y = f_wheel_y;

vehicle_config->wheel_fr_v = btVector3( btScalar(-0.714463),
                           -(vehicle_config->chassis_mass_y_shift) + f_wheel_y,
                           btScalar(1.186053) - vehicle_config->chassis_mass_z_shift);

vehicle_config->wheel_fl_v = btVector3( btScalar(0.714463),
                           -(vehicle_config->chassis_mass_y_shift) + f_wheel_y,
                           btScalar(1.186053) - vehicle_config->chassis_mass_z_shift);

vehicle_config->wheel_br_v = btVector3( btScalar(-0.714463),
                           -(vehicle_config->chassis_mass_y_shift) + r_wheel_y,
                           btScalar(-1.313947) - vehicle_config->chassis_mass_z_shift);

vehicle_config->wheel_bl_v = btVector3( btScalar(0.714463),
                           -(vehicle_config->chassis_mass_y_shift) + r_wheel_y,
                           btScalar(-1.313947) - vehicle_config->chassis_mass_z_shift);

//////////////////////////////////////////////////////


{
int vertex_stride = sizeof(btVector3);
btVector3 * vertex_array = new btVector3[vertices_size_miura_proxy/3];

int j = -1;
    for ( int ind = 0; ind < vertices_size_miura_proxy; ind+=3 )
    {
    vertex_array[++j].setValue(btScalar( *(p_vertices_miura_proxy+ind+0)),
                               btScalar( *(p_vertices_miura_proxy+ind+1)),
                               btScalar( *(p_vertices_miura_proxy+ind+2)));
    }
btCollisionShape * shape = new btConvexHullShape((btScalar *) &vertex_array[0][0],vertices_size_miura_proxy/3,vertex_stride);
 
ArraysTrack bo;
bo.vertex_array = vertex_array;
arrays_track.push_back(bo);

btCompoundShape * compound = new btCompoundShape();

btTransform chassis_local_trans;
chassis_local_trans.setIdentity();
chassis_local_trans.setOrigin(btVector3(btScalar(0.0),
                                        -(vehicle_config->chassis_mass_y_shift),
                                        -(vehicle_config->chassis_mass_z_shift)));
compound->addChildShape(chassis_local_trans,shape);
collision_shapes.push_back(compound);

btTransform compound_trans;
compound_trans.setIdentity();
compound_trans.setOrigin(vehicle_config->origin);
btQuaternion q(btVector3(btScalar(0.),btScalar(1.),btScalar(0.)),btScalar(rotation));
compound_trans.setRotation(q);

btRigidBody * chassis;
chassis = create_rigid_body(vehicle_config->vehicle_mass,
                            compound_trans, 
                            compound,
                            vehicle_config->chassis_friction,
                            vehicle_config->chassis_restitution,
                            vehicle_config->chassis_angular_dump,
                            vehicle_config->chassis_linear_dump);

chassis->setLinearVelocity(btVector3(btScalar(0.0),btScalar(0.0),btScalar(0.0)));
chassis->setAngularVelocity(btVector3(btScalar(0.0),btScalar(0.0),btScalar(0.0)));
int * usrP = new int[2];
usrP[0] = vehicle_id + 1;// group id, don't collide inside the group, here group with id "1"
usrP[1] = 1;// wheel raytest (MyVehicleRayResultCallback), "2" to skip
chassis->setUserPointer(usrP);

RaycastCar * vehicle = new RaycastCar(chassis);
vehicle->m_dynamicsWorld = m_dynamicsWorld;
chassis->setActivationState(DISABLE_DEACTIVATION);

vehicle->setCoordinateSystem(vehicle_config->right_index,
                             vehicle_config->up_index,
                             vehicle_config->forward_index);
vehicle->m_Crr = vehicle_config->Crr;
vehicle->m_inertia_coef = vehicle_config->inertia_coefficient;

    for (int x=0;x<4;x++) vehicle->addWheel(vehicle_config, x);

VehicleObject * vo = new VehicleObject;
vo->set_raycast_vehicle(vehicle);
vo->set_compound_shape(compound);
vo->set_chassis_shape(shape);
vo->set_chassis_body(chassis);
    if (add_ghost) vo->set_ghost_body(ghost);
vo->set_vehicle_config(vehicle_config);
vo->set_draw_object(di);
vo->draw_wheel_fr = draw_wheel_fr;
vo->draw_wheel_fl = draw_wheel_fl;
vo->draw_wheel_rr = draw_wheel_rr;
vo->draw_wheel_rl = draw_wheel_rl;

    if (vehicles.size() <= vehicle_id)
    {
    vehicles.push_back(vo);
    }
    else
    {
    vehicles[vehicle_id] = vo;
    }

m_dynamicsWorld->addAction(vehicle);
}
/////////////////////////////////////////////////////


}
示例#4
0
core::RigidBody create_rigid_body(Hierarchy h) {
  return create_rigid_body(Hierarchies(1,h), h->get_name()+" rigid body");
}
示例#5
0
void Engine::init_scene() {
    Node* scene = nodes["scene"] = new Node(NULL);

    // shaders //

    // "simple_shader"
    shaders["simple_shader"] = make_shader("shaders/p_v.glsl",
                                           "shaders/unicolor_f.glsl");

    // "light1"
    {
        Shader* shader = shaders["light1"] =
                make_shader("shaders/pn_v.glsl", "shaders/light1_f.glsl");

        // TODO put uniforms in "material"-class or something?
        set_uniform(shader, "mycolor", glm::vec4(1.f));
        set_uniform(shader, "ambient_intensity", glm::vec4(.1f,.1f,.1f,1.f));
        set_uniform(shader, "diffuse_color", glm::vec4(.5f,.5f,.5f,1.f));
        set_uniform(shader, "specular_color", glm::vec4(1.f,1.f,1.f,1.f));

        set_uniform(shader, "atten_k", .04f);
        set_uniform(shader, "gauss_k", .1f);
    }

    // objects //

    // grid
    {
        Shader* shader = shaders["simple_shader"];

        Node* node = nodes["grid"] = new Node(scene);

        int no = 5;
        glm::vec3 scale = glm::vec3(20.f);
        VAO* vao = create_grid(no, scale);

        std::vector<Uniform*> material;

        glm::vec4 white = glm::vec4(1.f);
        StoredUniform<glm::vec4>* mycolor =
                new StoredUniform<glm::vec4>(shader, "mycolor", white);
        material.push_back(mycolor);

        renderables.push_back(
                    new BasicRenderObject(shader, node, vao, material));

        // mem
        vaos.push_back(vao);
        uniforms.push_back(mycolor);
    }

    // redcube
    {
        Shader* shader = shaders["light1"];

        Node* node = nodes["redcube"] = new Node(scene);
        node->position = glm::vec3(.5f,.5f,-1.7f);

        glm::vec3 scale = glm::vec3(.05f);
        VAO* vao = create_cube_with_normals(scale);

        std::vector<Uniform*> material;

        glm::vec4 red = glm::vec4(1.f,0.f,.5f,1.f);
        StoredUniform<glm::vec4>* mycolor =
                new StoredUniform<glm::vec4>(shader, "mycolor", red);
        material.push_back(mycolor);

        renderables.push_back(
                new LitRenderObject(shader, node, vao, material));


        // physics
        btCollisionShape* cube_shape = new btBoxShape(from_vec3(scale/2.f));

        float mass = 0.f;
        redcube_rb = create_rigid_body(mass, node, cube_shape);
        physics->add_rigid_body(redcube_rb);


        // mem
        vaos.push_back(vao);
        uniforms.push_back(mycolor);
        collision_shapes.push_back(cube_shape);
    }

    make_litcube("cyancube",
                 glm::vec4(0.f, 1.f, 1.f, 1.f),
                 glm::vec3(0.05f));
    nodes["cyancube"]->orientation =
            glm::angleAxis(glm::radians(45.f),
                           glm::normalize(glm::vec3(-1.f, 1.f, 1.f)));

    make_litcube("yellowcube",
                 glm::vec4(1.f, 1.f, 0.f, 1.f),
                 glm::vec3(0.05f));
    nodes["yellowcube"]->orientation = nodes["cyancube"]->orientation;

    make_litcube("bluecube",
                 glm::vec4(0.f, 0.f, 1.f, 1.f),
                 glm::vec3(1.f),
                 30.f,
                 glm::vec3(0.f, 1.5f, -5.f));

    // lightcube
    {
        Shader* shader = shaders["simple_shader"];

        Node* node = nodes["lightcube"] = new Node(scene);
        node->position = glm::vec3(0.f, 1.f, 0.f);

        glm::vec3 scale = glm::vec3(.3f,.3f,.3f);
        VAO* vao = create_cube(scale);

        std::vector<Uniform*> material;

        glm::vec4 white = glm::vec4(1.f,1.f,1.f,1.f);
        StoredUniform<glm::vec4>* mycolor =
                new StoredUniform<glm::vec4>(shader, "mycolor", white);
        material.push_back(mycolor);

        renderables.push_back(
                new BasicRenderObject(shader, node, vao, material));

        // sync point light with position
        PointLight light0(node, glm::vec4(.7f,.7f,.7f,1.f));
        set_uniform(shaders["light1"], "light.position",
                    glm::vec3(light0.get_position()));
        set_uniform(shaders["light1"], "light.intensity",
                    light0.get_intensity());

        // mem
        vaos.push_back(vao);
        uniforms.push_back(mycolor);
    }

    // plane
    {
        Shader* shader = shaders["light1"];

        Node* node = nodes["plane"] = new Node(scene);
        node->position = glm::vec3(0.f, -.5f, 0.f);

        glm::vec3 scale = glm::vec3(20.f, 1.f, 20.f);
        VAO* vao = create_cube_with_normals(scale);

        std::vector<Uniform*> material;

        glm::vec4 goldish = glm::vec4(1.f,1.f,0.f,1.f);
        StoredUniform<glm::vec4>* mycolor =
                new StoredUniform<glm::vec4>(shader, "mycolor", goldish);
        material.push_back(mycolor);

        renderables.push_back(
                new LitRenderObject(shader, node, vao, material));

        // physics
        btCollisionShape* shape = new btBoxShape(from_vec3(scale/2.f));

        float mass = 0.f;
        btRigidBody* rigid_body = create_rigid_body(mass, node, shape);
        physics->add_rigid_body(rigid_body);

        // mem
        uniforms.push_back(mycolor);
        vaos.push_back(vao);
        collision_shapes.push_back(shape);
    }

    // bound
    {
        Shader* shader = shaders["light1"];

        Node* node = nodes["bound"] = new Node(scene);

        glm::vec3 scale = glm::vec3(20.f);
        bool face_inward = true;
        VAO* vao = create_cube_with_normals(scale, face_inward);

        std::vector<Uniform*> material;

        glm::vec4 greenblueish = glm::vec4(0.f,1.f,1.f,1.f);
        StoredUniform<glm::vec4>* mycolor =
            new StoredUniform<glm::vec4>(shader, "mycolor", greenblueish);
        material.push_back(mycolor);

        renderables.push_back(
                new LitRenderObject(shader, node, vao, material));

        // mem
        vaos.push_back(vao);
        uniforms.push_back(mycolor);
    }

    // roboarm
    {
        nodes["roboarm0"] = new Node(scene);
        nodes["roboarm1"] = new Node(scene);
        nodes["roboarm2"] = new Node(scene);
        nodes["roboarm3"] = new Node(scene);

        glm::vec3 scale = glm::vec3(0.1f, 0.4f, 0.1f);

        nodes["roboarm0"]->position = glm::vec3(0.f, 1.f, -2.f);
        //nodes["roboarm0"]->orientation =
        //        glm::angleAxis(glm::radians(180.f), glm::vec3(1.f, 0.f, 0.f));

        nodes["roboarm1"]->position = nodes["roboarm0"]->position +
            nodes["roboarm0"]->orientation * glm::vec3(0.f, scale.y, 0.f);
        nodes["roboarm1"]->orientation = nodes["roboarm0"]->orientation;

        nodes["roboarm2"]->position = nodes["roboarm1"]->position +
            nodes["roboarm1"]->orientation * glm::vec3(0.f, scale.y, 0.f);
        nodes["roboarm2"]->orientation = nodes["roboarm1"]->orientation;

        nodes["roboarm3"]->position = nodes["roboarm2"]->position +
            nodes["roboarm2"]->orientation * glm::vec3(0.f, scale.y, 0.f);
        nodes["roboarm3"]->orientation = nodes["roboarm2"]->orientation;

        // render
        {
            Shader* shader = shaders["light1"];

            glm::vec4 black = glm::vec4(0.f,0.f,0.f,1.f);
            StoredUniform<glm::vec4>* mycolor =
                    new StoredUniform<glm::vec4>(shader, "mycolor", black);

            std::vector<Uniform*> material;
            material.push_back(mycolor);

            // TODO use rounder shapes...
            VAO* vao = create_cube_with_normals(scale);

            auto make_renderable =
                [&shader, &material, &vao] (Node* node) {
                    return new LitRenderObject(shader, node, vao, material);
                };

            renderables.insert(renderables.end(),
                {
                    make_renderable(nodes["roboarm0"]),
                    make_renderable(nodes["roboarm1"]),
                    make_renderable(nodes["roboarm2"]),
                    make_renderable(nodes["roboarm3"]),
                }
            );

            // mem
            uniforms.push_back(mycolor);
            vaos.push_back(vao);
        }

        btCollisionShape *shape = new btBoxShape(from_vec3(scale/2.f));
        float density = 1000.f,
              volume = scale.x * scale.y * scale.z,
              mass = density * volume;

        // mem
        collision_shapes.push_back(shape);


        btRigidBody *rb0 = create_rigid_body(0.f, nodes["roboarm0"], shape),
                    *rb1 = create_rigid_body(mass, nodes["roboarm1"], shape),
                    *rb2 = create_rigid_body(mass, nodes["roboarm2"], shape),
                    *rb3 = create_rigid_body(mass, nodes["roboarm3"], shape);

        rb1->setActivationState(DISABLE_DEACTIVATION);
        rb2->setActivationState(DISABLE_DEACTIVATION);
        rb3->setActivationState(DISABLE_DEACTIVATION);

        physics->add_rigid_body(rb0);
        physics->add_rigid_body(rb1);
        physics->add_rigid_body(rb2);
        physics->add_rigid_body(rb3);

        btMatrix3x3 rot;
        rot.setIdentity();

        btTransform trans_up(rot, btVector3(0.f, scale.y/2, 0.f)),
                    trans_down(rot, btVector3(0.f, -scale.y/2, 0.f));

        rc1 = new btHingeConstraint(*rb0, *rb1,
                                    trans_up, trans_down);

        rc2 = new btHingeConstraint(*rb1, *rb2,
                                    trans_up, trans_down);

        rc3 = new btHingeConstraint(*rb2, *rb3,
                                    trans_up, trans_down);

        float pi = glm::pi<float>();

        rc1->setLimit(-pi/2, pi/2);
        rc2->setLimit(-pi/2, pi/2);
        rc3->setLimit(-pi/2, pi/2);

        bool intercollision = false;
        physics->add_constraint(rc1, intercollision);
        physics->add_constraint(rc2, intercollision);
        physics->add_constraint(rc3, intercollision);

        roboarm0 = new KinematicChain(nullptr, rb0, nullptr);
        roboarm1 = new KinematicChain(roboarm0, rb1, rc1);
        roboarm2 = new KinematicChain(roboarm1, rb2, rc2);
        roboarm3 = new KinematicChain(roboarm2, rb3, rc3);
    }
}