void IK_QSwingSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax) { if (lmin >= lmax) return; // clamp and convert to axis angle parameters lmin = MT_clamp(lmin, -180, 180); lmax = MT_clamp(lmax, -180, 180); lmin = sin(MT_radians(lmin)*0.5); lmax = sin(MT_radians(lmax)*0.5); // put center of ellispe in the middle between min and max MT_Scalar offset = 0.5*(lmin + lmax); //lmax = lmax - offset; if (axis == 0) { m_min[0] = -lmax; m_max[0] = -lmin; m_limit_x = true; m_offset_x = offset; m_max_x = lmax; } else if (axis == 2) { m_min[1] = -lmax; m_max[1] = -lmin; m_limit_z = true; m_offset_z = offset; m_max_z = lmax; } }
void IK_QSphericalSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax) { if (lmin >= lmax) return; if (axis == 1) { lmin = MT_clamp(lmin, -180, 180); lmax = MT_clamp(lmax, -180, 180); m_min_y = MT_radians(lmin); m_max_y = MT_radians(lmax); m_limit_y = true; } else { // clamp and convert to axis angle parameters lmin = MT_clamp(lmin, -180, 180); lmax = MT_clamp(lmax, -180, 180); lmin = sin(MT_radians(lmin)*0.5); lmax = sin(MT_radians(lmax)*0.5); if (axis == 0) { m_min[0] = -lmax; m_max[0] = -lmin; m_limit_x = true; } else if (axis == 2) { m_min[1] = -lmax; m_max[1] = -lmin; m_limit_z = true; } } }
void IK_QRevoluteSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax) { if (lmin >= lmax || m_axis != axis) return; // clamp and convert to axis angle parameters lmin = MT_clamp(lmin, -180, 180); lmax = MT_clamp(lmax, -180, 180); m_min = MT_radians(lmin); m_max = MT_radians(lmax); m_limit = true; }
void IK_QElbowSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax) { if (lmin >= lmax) return; // clamp and convert to axis angle parameters lmin = MT_clamp(lmin, -180, 180); lmax = MT_clamp(lmax, -180, 180); lmin = MT_radians(lmin); lmax = MT_radians(lmax); if (axis == 1) { m_min_twist = lmin; m_max_twist = lmax; m_limit_twist = true; } else if (axis == m_axis) { m_min = lmin; m_max = lmax; m_limit = true; } }
/** * Transforms the collision object. A cone is not correctly centered * for usage. */ void KX_RadarSensor::SynchronizeTransform() { // Getting the parent location was commented out. Why? MT_Transform trans; trans.setOrigin(((KX_GameObject*)GetParent())->NodeGetWorldPosition()); trans.setBasis(((KX_GameObject*)GetParent())->NodeGetWorldOrientation()); // What is the default orientation? pointing in the -y direction? // is the geometry correctly converted? // a collision cone is oriented // center the cone correctly // depends on the radar 'axis' switch (m_axis) { case SENS_RADAR_X_AXIS: // +X Axis { MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90)); trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case SENS_RADAR_Y_AXIS: // +Y Axis { MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180)); trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case SENS_RADAR_Z_AXIS: // +Z Axis { MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-90)); trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case SENS_RADAR_NEG_X_AXIS: // -X Axis { MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(-90)); trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case SENS_RADAR_NEG_Y_AXIS: // -Y Axis { //MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180)); //trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case SENS_RADAR_NEG_Z_AXIS: // -Z Axis { MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(90)); trans.rotate(rotquatje); trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; default: { } } //Using a temp variable to translate MT_Point3 to float[3]. //float[3] works better for the Python interface. MT_Point3 temp = trans.getOrigin(); m_cone_origin[0] = temp[0]; m_cone_origin[1] = temp[1]; m_cone_origin[2] = temp[2]; temp = trans(MT_Point3(0, -m_coneheight/2.0 ,0)); m_cone_target[0] = temp[0]; m_cone_target[1] = temp[1]; m_cone_target[2] = temp[2]; if (m_physCtrl) { PHY_IMotionState* motionState = m_physCtrl->GetMotionState(); const MT_Point3& pos = trans.getOrigin(); float ori[12]; trans.getBasis().getValue(ori); motionState->setWorldPosition(pos[0], pos[1], pos[2]); motionState->setWorldOrientation(ori); m_physCtrl->WriteMotionStateToDynamics(true); } }
void BL_ConvertSensors(struct Object* blenderobject, class KX_GameObject* gameobj, SCA_LogicManager* logicmgr, KX_Scene* kxscene, KX_KetsjiEngine* kxengine, int activeLayerBitInfo, bool isInActiveLayer, RAS_ICanvas* canvas, KX_BlenderSceneConverter* converter ) { int executePriority = 0; int uniqueint = 0; int count = 0; bSensor* sens = (bSensor*)blenderobject->sensors.first; bool pos_pulsemode = false; bool neg_pulsemode = false; int frequency = 0; bool invert = false; bool level = false; bool tap = false; while (sens) { sens = sens->next; count++; } gameobj->ReserveSensor(count); sens = (bSensor*)blenderobject->sensors.first; while(sens) { SCA_ISensor* gamesensor=NULL; /* All sensors have a pulse toggle, frequency, and invert field. */ /* These are extracted here, and set when the sensor is added to the */ /* list. */ pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; frequency = sens->freq; invert = !(sens->invert == 0); level = !(sens->level == 0); tap = !(sens->tap == 0); switch (sens->type) { case SENS_ALWAYS: { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); } break; } case SENS_DELAY: { // we can reuse the Always event manager for the delay sensor SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { bDelaySensor* delaysensor = (bDelaySensor*)sens->data; gamesensor = new SCA_DelaySensor(eventmgr, gameobj, delaysensor->delay, delaysensor->duration, (delaysensor->flag & SENS_DELAY_REPEAT) != 0); } break; } case SENS_COLLISION: { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); if (eventmgr) { // collision sensor can sense both materials and properties. bool bFindMaterial = false, bTouchPulse = false; bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); STR_String touchPropOrMatName = ( bFindMaterial ? blendertouchsensor->materialName: (blendertouchsensor->name ? blendertouchsensor->name: "")); if (gameobj->GetPhysicsController()) { gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, bTouchPulse, touchPropOrMatName); } } break; } case SENS_TOUCH: { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); if (eventmgr) { STR_String touchpropertyname; bTouchSensor* blendertouchsensor = (bTouchSensor*)sens->data; if (blendertouchsensor->ma) { touchpropertyname = (char*) (blendertouchsensor->ma->id.name+2); } bool bFindMaterial = true; if (gameobj->GetPhysicsController()) { gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, false, touchpropertyname); } } break; } case SENS_MESSAGE: { KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); if (eventmgr) { bMessageSensor* msgSens = (bMessageSensor*) sens->data; /* Get our NetworkScene */ NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); /* filter on the incoming subjects, might be empty */ STR_String subject = (msgSens->subject ? (char*)msgSens->subject : ""); gamesensor = new KX_NetworkMessageSensor( eventmgr, // our eventmanager NetworkScene, // our NetworkScene gameobj, // the sensor controlling object subject); // subject to filter on } break; } case SENS_NEAR: { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); if (eventmgr) { STR_String nearpropertyname; bNearSensor* blendernearsensor = (bNearSensor*)sens->data; if (blendernearsensor->name) { // only objects that own this property will be taken into account nearpropertyname = (char*) blendernearsensor->name; } //DT_ShapeHandle shape = DT_Sphere(0.0); // this sumoObject is not deleted by a gameobj, so delete it ourself // later (memleaks)! float radius = blendernearsensor->dist; PHY__Vector3 pos; const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); pos[0] = (float)wpos[0]; pos[1] = (float)wpos[1]; pos[2] = (float)wpos[2]; pos[3] = 0.f; bool bFindMaterial = false; PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,pos); //will be done in KX_TouchEventManager::RegisterSensor() //if (isInActiveLayer) // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); gamesensor = new KX_NearSensor(eventmgr,gameobj, blendernearsensor->dist, blendernearsensor->resetdist, bFindMaterial, nearpropertyname, physCtrl); } break; } case SENS_KEYBOARD: { /* temporary input device, for converting the code for the keyboard sensor */ bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); if (eventmgr) { gamesensor = new SCA_KeyboardSensor(eventmgr, ConvertKeyCode(blenderkeybdsensor->key), ConvertKeyCode(blenderkeybdsensor->qual), ConvertKeyCode(blenderkeybdsensor->qual2), (blenderkeybdsensor->type == SENS_ALL_KEYS), blenderkeybdsensor->targetName, blenderkeybdsensor->toggleName, gameobj); // blenderkeybdsensor->pad); } break; } case SENS_MOUSE: { int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; int trackfocus = 0; bMouseSensor *bmouse = (bMouseSensor *)sens->data; /* There are two main types of mouse sensors. If there is * no focus-related behavior requested, we can make do * with a basic sensor. This cuts down memory usage and * gives a slight performance gain. */ SCA_MouseManager *eventmgr = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); if (eventmgr) { /* Determine key mode. There is at most one active mode. */ switch (bmouse->type) { case BL_SENS_MOUSE_LEFT_BUTTON: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; break; case BL_SENS_MOUSE_MIDDLE_BUTTON: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; break; case BL_SENS_MOUSE_RIGHT_BUTTON: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; break; case BL_SENS_MOUSE_WHEEL_UP: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; break; case BL_SENS_MOUSE_WHEEL_DOWN: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; break; case BL_SENS_MOUSE_MOVEMENT: keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; break; case BL_SENS_MOUSE_MOUSEOVER: trackfocus = 1; break; case BL_SENS_MOUSE_MOUSEOVER_ANY: trackfocus = 2; break; default: ; /* error */ } /* initial mouse position */ int startx = canvas->GetWidth()/2; int starty = canvas->GetHeight()/2; if (!trackfocus) { /* plain, simple mouse sensor */ gamesensor = new SCA_MouseSensor(eventmgr, startx,starty, keytype, gameobj); } else { /* give us a focus-aware sensor */ gamesensor = new KX_MouseFocusSensor(eventmgr, startx, starty, keytype, trackfocus, (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, kxscene, kxengine, gameobj); } } else { // cout << "\n Could't find mouse event manager..."; - should throw an error here... } break; } case SENS_PROPERTY: { bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { STR_String propname=blenderpropsensor->name; STR_String propval=blenderpropsensor->value; STR_String propmaxval=blenderpropsensor->maxvalue; SCA_PropertySensor::KX_PROPSENSOR_TYPE propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; /* Better do an explicit conversion here! (was implicit */ /* before...) */ switch(blenderpropsensor->type) { case SENS_PROP_EQUAL: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; break; case SENS_PROP_NEQUAL: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; break; case SENS_PROP_INTERVAL: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; break; case SENS_PROP_CHANGED: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; break; case SENS_PROP_EXPRESSION: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; /* error */ break; default: ; /* error */ } gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); } break; } case SENS_ACTUATOR: { bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; // we will reuse the property event manager, there is nothing special with this sensor SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); if (eventmgr) { STR_String propname=blenderactsensor->name; gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); } break; } case SENS_ARMATURE: { bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; // we will reuse the property event manager, there is nothing special with this sensor SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { STR_String bonename=blenderarmsensor->posechannel; STR_String constraintname=blenderarmsensor->constraint; gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); } break; } case SENS_RADAR: { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); if (eventmgr) { STR_String radarpropertyname; STR_String touchpropertyname; bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; int radaraxis = blenderradarsensor->axis; if (blenderradarsensor->name) { // only objects that own this property will be taken into account radarpropertyname = (char*) blenderradarsensor->name; } MT_Scalar coneheight = blenderradarsensor->range; // janco: the angle was doubled, so should I divide the factor in 2 // or the blenderradarsensor->angle? // nzc: the angle is the opening angle. We need to init with // the axis-hull angle,so /2.0. MT_Scalar factor = tan(MT_radians((blenderradarsensor->angle)/2.0)); //MT_Scalar coneradius = coneheight * (factor / 2); MT_Scalar coneradius = coneheight * factor; // this sumoObject is not deleted by a gameobj, so delete it ourself // later (memleaks)! MT_Scalar smallmargin = 0.0; MT_Scalar largemargin = 0.0; bool bFindMaterial = false; PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); gamesensor = new KX_RadarSensor( eventmgr, gameobj, ctrl, coneradius, coneheight, radaraxis, smallmargin, largemargin, bFindMaterial, radarpropertyname); } break; } case SENS_RAY: { bRaySensor* blenderraysensor = (bRaySensor*) sens->data; //blenderradarsensor->angle; SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); // don't want to get rays of length 0.0 or so double distance = (blenderraysensor->range < 0.01 ? 0.01 : blenderraysensor->range ); int axis = blenderraysensor->axisflag; gamesensor = new KX_RaySensor(eventmgr, gameobj, checkname, bFindMaterial, bXRay, distance, axis, kxscene); } break; } case SENS_RANDOM: { bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; // some files didn't write randomsensor, avoid crash now for NULL ptr's if (blenderrndsensor) { SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { int randomSeed = blenderrndsensor->seed; if (randomSeed == 0) { randomSeed = (int)(kxengine->GetRealTime()*100000.0); randomSeed ^= (intptr_t)blenderrndsensor; } gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } } break; } case SENS_JOYSTICK: { int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; SCA_JoystickManager *eventmgr = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); if (eventmgr) { int axis =0; int axisf =0; int button =0; int hat =0; int hatf =0; int prec =0; switch(bjoy->type) { case SENS_JOY_AXIS: axis = bjoy->axis; axisf = bjoy->axisf; prec = bjoy->precision; joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; break; case SENS_JOY_BUTTON: button = bjoy->button; joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; break; case SENS_JOY_HAT: hat = bjoy->hat; hatf = bjoy->hatf; joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; break; case SENS_JOY_AXIS_SINGLE: axis = bjoy->axis_single; prec = bjoy->precision; joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; break; default: printf("Error: bad case statement\n"); break; } gamesensor = new SCA_JoystickSensor( eventmgr, gameobj, bjoy->joyindex, joysticktype, axis,axisf, prec, button, hat,hatf, (bjoy->flag & SENS_JOY_ANY_EVENT)); } else { printf("Error there was a problem finding the event manager\n"); } break; } default: { } } if (gamesensor) { gamesensor->SetExecutePriority(executePriority++); STR_String uniquename = sens->name; uniquename += "#SENS#"; uniqueint++; CIntValue* uniqueval = new CIntValue(uniqueint); uniquename += uniqueval->GetText(); uniqueval->Release(); /* Conversion succeeded, so we can set the generic props here. */ gamesensor->SetPulseMode(pos_pulsemode, neg_pulsemode, frequency); gamesensor->SetInvert(invert); gamesensor->SetLevel(level); gamesensor->SetTap(tap); gamesensor->SetName(sens->name); gameobj->AddSensor(gamesensor); // only register to manager if it's in an active layer // Make registration dynamic: only when sensor is activated //if (isInActiveLayer) // gamesensor->RegisterToManager(); gamesensor->ReserveController(sens->totlinks); for (int i=0;i<sens->totlinks;i++) { bController* linkedcont = (bController*) sens->links[i]; if (linkedcont) { SCA_IController* gamecont = converter->FindGameController(linkedcont); if (gamecont) { logicmgr->RegisterToSensor(gamecont,gamesensor); } else { printf( "Warning, sensor \"%s\" could not find its controller " "(link %d of %d) from object \"%s\"\n" "\tthere has been an error converting the blender controller for the game engine," "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } else { printf( "Warning, sensor \"%s\" has lost a link to a controller " "(link %d of %d) from object \"%s\"\n" "\tpossible causes are partially appended objects or an error reading the file," "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } // special case: Keyboard sensor with no link // this combination is usually used for key logging. if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { // Force the registration so that the sensor runs gamesensor->IncLink(); } // done with gamesensor gamesensor->Release(); } sens=sens->next; } }