735 lines · 24.1 KB · JavaScript
RawDownload
// botProceduralWayPoints.js  // modified by Adrian McCarlie for worklist job hifi: #19977// 1 September 2014.// this script enables a user to define unlimited number of way points on the Domain,// these points form a path that the bot will follow, once the final way point is reached, // the bot will return to the start and continue until script is stopped.// pause times for each way point can be set individually.// User must input the x, y, z co-ords for wayPoints[] and time in milliseconds for pauseTimes[]. //// original script// bot_procedural.js// hifi// Created by Ben Arnold on 7/29/2013//// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.//// This is an example script that demonstrates an NPC avatar.//// //For procedural walk animationScript.include(Script.getExternalPath(Script.ExternalPaths.Assets, "scripts/acScripts/proceduralAnimationAPI.js"); var procAnimAPI = new ProcAnimAPI(); function getRandomFloat(min, max) {    return Math.random() * (max - min) + min;} function getRandomInt (min, max) {    return Math.floor(Math.random() * (max - min + 1)) + min;} function printVector(string, vector) {    print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);} //input co-ords for start position and 7 other positions var AVATAR_PELVIS_HEIGHT = 0.84;//only change this if you have an odd size avatar var wayPoints = []; //input locations for all the waypoints    wayPoints[0] = {x:8131.5, y:202.0, z:8261.5}; //input the location of the start position    wayPoints[1] = {x: 8160.5, y: 202.0, z: 8261.5}; //input the location of the first way point    wayPoints[2] = {x: 8160.5, y: 203.0, z: 8270.5};     wayPoints[3] = {x: 8142.5, y: 204.0, z: 8270.5};    wayPoints[4] = {x: 8142.5, y: 204.0, z: 8272.5};    wayPoints[5] = {x: 8160.5, y: 203.0, z: 8272.5};    wayPoints[6] = {x: 8160.5, y: 202.0, z: 8284.5};    wayPoints[7] = {x: 8111.5, y: 202.0, z: 8284.5};// continue to add locations and add or remove lines as needed.    var pauseTimes = []; // the number of pauseTimes must equal the number of wayPoints. Time is in milliseconds    pauseTimes[0] = 5000; //waiting to go to wayPoint0 (startPoint)    pauseTimes[1] = 10000; //waiting to go to wayPoint1    pauseTimes[2] = 3000;    pauseTimes[3] = 3000;    pauseTimes[4] = 8000;    pauseTimes[5] = 6000;    pauseTimes[6] = 3000;    pauseTimes[7] = 3000;// add or delete to match way points.     wayPoints[0].y = wayPoints[0].y + AVATAR_PELVIS_HEIGHT;wayPoints[1].y = wayPoints[1].y + AVATAR_PELVIS_HEIGHT;wayPoints[2].y = wayPoints[2].y + AVATAR_PELVIS_HEIGHT;wayPoints[3].y = wayPoints[3].y + AVATAR_PELVIS_HEIGHT;wayPoints[4].y = wayPoints[4].y + AVATAR_PELVIS_HEIGHT;wayPoints[5].y = wayPoints[5].y + AVATAR_PELVIS_HEIGHT;wayPoints[6].y = wayPoints[6].y + AVATAR_PELVIS_HEIGHT;wayPoints[7].y = wayPoints[7].y + AVATAR_PELVIS_HEIGHT; var CHANCE_OF_MOVING = 0.005;var CHANCE_OF_SOUND = 0.005;var CHANCE_OF_HEAD_TURNING = 0.01;var CHANCE_OF_BIG_MOVE = 1.0; var isMoving = false;var isTurningHead = false;var isPlayingAudio = false;   var AVATAR_PELVIS_HEIGHT = 1.84;var MAX_PELVIS_DELTA = 2.5; var MOVE_RANGE_SMALL = 3.0;var MOVE_RANGE_BIG = 10.0;var TURN_RANGE = 70.0;var STOP_TOLERANCE = 0.05;var MOVE_RATE = 0.05;var TURN_RATE = 0.2;var HEAD_TURN_RATE = 0.05;var PITCH_RANGE = 15.0;var YAW_RANGE = 35.0; var firstPosition = wayPoints[0]; var targetPosition =  { x: 0, y: 0, z: 0 };var targetOrientation = { x: 0, y: 0, z: 0, w: 0 };var currentOrientation = { x: 0, y: 0, z: 0, w: 0 };var targetHeadPitch = 0.0;var targetHeadYaw = 0.0; var basePelvisHeight = 0.0;var pelvisOscillatorPosition = 0.0;var pelvisOscillatorVelocity = 0.0; function clamp(val, min, max){    return Math.max(min, Math.min(max, val))} //Array of all valid bot numbersvar validBotNumbers = []; // right now we only use bot 63, since many other bots have messed up skeletons and LOD issuesvar botNumber = 63;//getRandomInt(0, 99); var newFaceFilePrefix = "ron"; var newBodyFilePrefix = "bot" + botNumber; // set the face model fst using the bot number// there is no need to change the body model - we're using the defaultAvatar.faceModelURL = Script.getExternalPath(Script.ExternalPaths.Assets, "meshes/" + newFaceFilePrefix + ".fst");Avatar.skeletonModelURL = Script.getExternalPath(Script.ExternalPaths.Assets, "meshes/" + newBodyFilePrefix + "_a.fst");Avatar.billboardURL = Script.getExternalPath(Script.ExternalPaths.Assets, "meshes/billboards/bot" + botNumber + ".png"); Agent.isAvatar = true;Agent.isListeningToAudioStream = true; // change the avatar's position to wayPoints[0]Avatar.position = firstPosition;  basePelvisHeight = firstPosition.y; printVector("New dancer, position = ", Avatar.position); function loadSounds() {    var sound_filenames = ["AB1.raw", "Anchorman2.raw", "B1.raw", "B1.raw", "Bale1.raw", "Bandcamp.raw",    "Big1.raw", "Big2.raw", "Brian1.raw", "Buster1.raw", "CES1.raw", "CES2.raw", "CES3.raw", "CES4.raw",     "Carrie1.raw", "Carrie3.raw", "Charlotte1.raw", "EN1.raw", "EN2.raw", "EN3.raw", "Eugene1.raw", "Francesco1.raw",    "Italian1.raw", "Japanese1.raw", "Leigh1.raw", "Lucille1.raw", "Lucille2.raw", "MeanGirls.raw", "Murray2.raw",    "Nigel1.raw", "PennyLane.raw", "Pitt1.raw", "Ricardo.raw", "SN.raw", "Sake1.raw", "Samantha1.raw", "Samantha2.raw",     "Spicoli1.raw", "Supernatural.raw", "Swearengen1.raw", "TheDude.raw", "Tony.raw", "Triumph1.raw", "Uma1.raw",    "Walken1.raw", "Walken2.raw", "Z1.raw", "Z2.raw"    ];     var footstep_filenames = ["FootstepW2Left-12db.wav", "FootstepW2Right-12db.wav", "FootstepW3Left-12db.wav", "FootstepW3Right-12db.wav",                         "FootstepW5Left-12db.wav", "FootstepW5Right-12db.wav"];     var SOUND_BASE_URL = Script.getExternalPath(Script.ExternalPaths.Assets, "sounds/Cocktail+Party+Snippets/Raws/");     var FOOTSTEP_BASE_URL = Script.getExternalPath(Script.ExternalPaths.Assets, "sounds/Footsteps/");     for (var i = 0; i < sound_filenames.length; i++) {        sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));    }     for (var i = 0; i < footstep_filenames.length; i++) {        footstepSounds.push(SoundCache.getSound(FOOTSTEP_BASE_URL + footstep_filenames[i]));    }} var sounds = [];var footstepSounds = [];loadSounds();  function playRandomSound() {    if (!Agent.isPlayingAvatarSound) {        var whichSound = Math.floor((Math.random() * sounds.length));        Agent.playAvatarSound(sounds[whichSound]);    }} function playRandomFootstepSound() {  var whichSound = Math.floor((Math.random() * footstepSounds.length));      Audio.playSound(footstepSounds[whichSound], {      position: Avatar.position,    volume: 1.0    });} //  Facial Animation var allBlendShapes = [];var targetBlendCoefficient = [];var currentBlendCoefficient = []; //Blendshape constructorfunction addBlendshapeToPose(pose, shapeIndex, val) {    var index = pose.blendShapes.length;    pose.blendShapes[index] = {shapeIndex: shapeIndex, val: val };}//The mood of the avatar, determines face. 0 = happy, 1 = angry, 2 = sad. //Randomly pick avatar mood. 80% happy, 10% mad 10% sadvar randMood = Math.floor(Math.random() * 11);var avatarMood;if (randMood == 0) {    avatarMood = 1;} else if (randMood == 2) {    avatarMood = 2;} else {    avatarMood = 0;} var currentExpression = -1;//Face pose constructorvar happyPoses = []; happyPoses[0] = {blendShapes: []};addBlendshapeToPose(happyPoses[0], 28, 0.7); //MouthSmile_LaddBlendshapeToPose(happyPoses[0], 29, 0.7); //MouthSmile_R happyPoses[1] = {blendShapes: []};addBlendshapeToPose(happyPoses[1], 28, 1.0); //MouthSmile_LaddBlendshapeToPose(happyPoses[1], 29, 1.0); //MouthSmile_RaddBlendshapeToPose(happyPoses[1], 21, 0.2); //JawOpen happyPoses[2] = {blendShapes: []};addBlendshapeToPose(happyPoses[2], 28, 1.0); //MouthSmile_LaddBlendshapeToPose(happyPoses[2], 29, 1.0); //MouthSmile_RaddBlendshapeToPose(happyPoses[2], 21, 0.5); //JawOpenaddBlendshapeToPose(happyPoses[2], 46, 1.0); //CheekSquint_LaddBlendshapeToPose(happyPoses[2], 47, 1.0); //CheekSquint_RaddBlendshapeToPose(happyPoses[2], 17, 1.0); //BrowsU_LaddBlendshapeToPose(happyPoses[2], 18, 1.0); //BrowsU_R var angryPoses = []; angryPoses[0] = {blendShapes: []};addBlendshapeToPose(angryPoses[0], 26, 0.6); //MouthFrown_LaddBlendshapeToPose(angryPoses[0], 27, 0.6); //MouthFrown_RaddBlendshapeToPose(angryPoses[0], 14, 0.6); //BrowsD_LaddBlendshapeToPose(angryPoses[0], 15, 0.6); //BrowsD_R angryPoses[1] = {blendShapes: []};addBlendshapeToPose(angryPoses[1], 26, 0.9); //MouthFrown_LaddBlendshapeToPose(angryPoses[1], 27, 0.9); //MouthFrown_RaddBlendshapeToPose(angryPoses[1], 14, 0.9); //BrowsD_LaddBlendshapeToPose(angryPoses[1], 15, 0.9); //BrowsD_R angryPoses[2] = {blendShapes: []};addBlendshapeToPose(angryPoses[2], 26, 1.0); //MouthFrown_LaddBlendshapeToPose(angryPoses[2], 27, 1.0); //MouthFrown_RaddBlendshapeToPose(angryPoses[2], 14, 1.0); //BrowsD_LaddBlendshapeToPose(angryPoses[2], 15, 1.0); //BrowsD_RaddBlendshapeToPose(angryPoses[2], 21, 0.5); //JawOpenaddBlendshapeToPose(angryPoses[2], 46, 1.0); //CheekSquint_LaddBlendshapeToPose(angryPoses[2], 47, 1.0); //CheekSquint_R var sadPoses = []; sadPoses[0] = {blendShapes: []};addBlendshapeToPose(sadPoses[0], 26, 0.6); //MouthFrown_LaddBlendshapeToPose(sadPoses[0], 27, 0.6); //MouthFrown_RaddBlendshapeToPose(sadPoses[0], 16, 0.2); //BrowsU_CaddBlendshapeToPose(sadPoses[0], 2, 0.6); //EyeSquint_LaddBlendshapeToPose(sadPoses[0], 3, 0.6); //EyeSquint_R sadPoses[1] = {blendShapes: []};addBlendshapeToPose(sadPoses[1], 26, 0.9); //MouthFrown_LaddBlendshapeToPose(sadPoses[1], 27, 0.9); //MouthFrown_RaddBlendshapeToPose(sadPoses[1], 16, 0.6); //BrowsU_CaddBlendshapeToPose(sadPoses[1], 2, 0.9); //EyeSquint_LaddBlendshapeToPose(sadPoses[1], 3, 0.9); //EyeSquint_R sadPoses[2] = {blendShapes: []};addBlendshapeToPose(sadPoses[2], 26, 1.0); //MouthFrown_LaddBlendshapeToPose(sadPoses[2], 27, 1.0); //MouthFrown_RaddBlendshapeToPose(sadPoses[2], 16, 0.1); //BrowsU_CaddBlendshapeToPose(sadPoses[2], 2, 1.0); //EyeSquint_LaddBlendshapeToPose(sadPoses[2], 3, 1.0); //EyeSquint_RaddBlendshapeToPose(sadPoses[2], 21, 0.3); //JawOpen var facePoses = [];facePoses[0] = happyPoses;facePoses[1] = angryPoses;facePoses[2] = sadPoses;  function addBlendShape(s) {    allBlendShapes[allBlendShapes.length] = s;} //It is imperative that the following blendshapes are all present and are in the correct orderaddBlendShape("EyeBlink_L"); //0addBlendShape("EyeBlink_R"); //1addBlendShape("EyeSquint_L"); //2addBlendShape("EyeSquint_R"); //3addBlendShape("EyeDown_L"); //4addBlendShape("EyeDown_R"); //5addBlendShape("EyeIn_L"); //6addBlendShape("EyeIn_R"); //7addBlendShape("EyeOpen_L"); //8addBlendShape("EyeOpen_R"); //9addBlendShape("EyeOut_L"); //10addBlendShape("EyeOut_R"); //11addBlendShape("EyeUp_L"); //12addBlendShape("EyeUp_R"); //13addBlendShape("BrowsD_L"); //14addBlendShape("BrowsD_R"); //15addBlendShape("BrowsU_C"); //16addBlendShape("BrowsU_L"); //17addBlendShape("BrowsU_R"); //18addBlendShape("JawFwd"); //19addBlendShape("JawLeft"); //20addBlendShape("JawOpen"); //21addBlendShape("JawChew"); //22addBlendShape("JawRight"); //23addBlendShape("MouthLeft"); //24addBlendShape("MouthRight"); //25addBlendShape("MouthFrown_L"); //26addBlendShape("MouthFrown_R"); //27addBlendShape("MouthSmile_L"); //28addBlendShape("MouthSmile_R"); //29addBlendShape("MouthDimple_L"); //30addBlendShape("MouthDimple_R"); //31addBlendShape("LipsStretch_L"); //32addBlendShape("LipsStretch_R"); //33addBlendShape("LipsUpperClose"); //34addBlendShape("LipsLowerClose"); //35addBlendShape("LipsUpperUp"); //36addBlendShape("LipsLowerDown"); //37addBlendShape("LipsUpperOpen"); //38addBlendShape("LipsLowerOpen"); //39addBlendShape("LipsFunnel"); //40addBlendShape("LipsPucker"); //41addBlendShape("ChinLowerRaise"); //42addBlendShape("ChinUpperRaise"); //43addBlendShape("Sneer"); //44addBlendShape("Puff"); //45addBlendShape("CheekSquint_L"); //46addBlendShape("CheekSquint_R"); //47 for (var i = 0; i < allBlendShapes.length; i++) {    targetBlendCoefficient[i] = 0;    currentBlendCoefficient[i] = 0;} function setRandomExpression() {     //Clear all expression data for current expression    if (currentExpression != -1) {        var expression = facePoses[avatarMood][currentExpression];        for (var i = 0; i < expression.blendShapes.length; i++) {            targetBlendCoefficient[expression.blendShapes[i].shapeIndex] = 0.0;        }    }    //Get a new current expression    currentExpression = Math.floor(Math.random() * facePoses[avatarMood].length);    var expression = facePoses[avatarMood][currentExpression];    for (var i = 0; i < expression.blendShapes.length; i++) {        targetBlendCoefficient[expression.blendShapes[i].shapeIndex] = expression.blendShapes[i].val;    }} var expressionChangeSpeed = 0.1;function updateBlendShapes(deltaTime) {      for (var i = 0; i < allBlendShapes.length; i++) {        currentBlendCoefficient[i] += (targetBlendCoefficient[i] - currentBlendCoefficient[i]) * expressionChangeSpeed;        Avatar.setBlendshape(allBlendShapes[i], currentBlendCoefficient[i]);    }} var BLINK_SPEED = 0.15;var CHANCE_TO_BLINK = 0.0025;var MAX_BLINK = 0.85;var blink = 0.0;var isBlinking = false;function updateBlinking(deltaTime) {    if (isBlinking == false) {        if (Math.random() < CHANCE_TO_BLINK) {            isBlinking = true;        } else {            blink -= BLINK_SPEED;            if (blink < 0.0) blink = 0.0;        }    } else {        blink += BLINK_SPEED;        if (blink > MAX_BLINK) {            blink = MAX_BLINK;            isBlinking = false;        }    }        currentBlendCoefficient[0] = blink;    currentBlendCoefficient[1] = blink;    targetBlendCoefficient[0] = blink;    targetBlendCoefficient[1] = blink;} // //Procedural walk animation using two keyframes//We use a separate array for front and back joints//Pitch, yaw, and roll for the jointsvar rightAngles = [];var leftAngles = [];//for non mirrored joints such as the spinevar middleAngles = []; //Actual joint mappingsvar SHOULDER_JOINT_NUMBER = 15; var ELBOW_JOINT_NUMBER = 16;var JOINT_R_HIP = 1;var JOINT_R_KNEE = 2;var JOINT_L_HIP = 6;var JOINT_L_KNEE = 7;var JOINT_R_ARM = 15;var JOINT_R_FOREARM = 16;var JOINT_L_ARM = 39;var JOINT_L_FOREARM = 40;var JOINT_SPINE = 11;var JOINT_R_FOOT = 3;var JOINT_L_FOOT = 8;var JOINT_R_TOE = 4;var JOINT_L_TOE = 9; //  Animation Is Defined Below  var NUM_FRAMES = 2;for (var i = 0; i < NUM_FRAMES; i++) {    rightAngles[i] = [];    leftAngles[i] = [];    middleAngles[i] = [];}//Joint order for actual joint mappings, should be interleaved R,L,R,L,...S,S,S for R = right, L = left, S = singlevar JOINT_ORDER = [];//*** right / left joints ***var HIP = 0;JOINT_ORDER.push(JOINT_R_HIP);JOINT_ORDER.push(JOINT_L_HIP);var KNEE = 1;JOINT_ORDER.push(JOINT_R_KNEE);JOINT_ORDER.push(JOINT_L_KNEE);var ARM = 2;JOINT_ORDER.push(JOINT_R_ARM);JOINT_ORDER.push(JOINT_L_ARM);var FOREARM = 3;JOINT_ORDER.push(JOINT_R_FOREARM);JOINT_ORDER.push(JOINT_L_FOREARM);var FOOT = 4;JOINT_ORDER.push(JOINT_R_FOOT);JOINT_ORDER.push(JOINT_L_FOOT);var TOE = 5;JOINT_ORDER.push(JOINT_R_TOE);JOINT_ORDER.push(JOINT_L_TOE);//*** middle joints ***var SPINE = 0;JOINT_ORDER.push(JOINT_SPINE); //We have to store the angles so we can invert yaw and roll when making the animation//symmetrical //Front refers to leg, not arm.//Legs ExtendingrightAngles[0][HIP] = [30.0, 0.0, 8.0];rightAngles[0][KNEE] = [-15.0, 0.0, 0.0];rightAngles[0][ARM] = [85.0, -25.0, 0.0];rightAngles[0][FOREARM] = [0.0, 0.0, -15.0];rightAngles[0][FOOT] = [0.0, 0.0, 0.0];rightAngles[0][TOE] = [0.0, 0.0, 0.0]; leftAngles[0][HIP] = [-15, 0.0, 8.0];leftAngles[0][KNEE] = [-26, 0.0, 0.0];leftAngles[0][ARM] = [85.0, 20.0, 0.0];leftAngles[0][FOREARM] = [10.0, 0.0, -25.0];leftAngles[0][FOOT] = [-13.0, 0.0, 0.0];leftAngles[0][TOE] = [34.0, 0.0, 0.0]; middleAngles[0][SPINE] = [0.0, -15.0, 5.0]; //Legs PassingrightAngles[1][HIP] = [6.0, 0.0, 8.0];rightAngles[1][KNEE] = [-12.0, 0.0, 0.0];rightAngles[1][ARM] = [85.0, 0.0, 0.0];rightAngles[1][FOREARM] = [0.0, 0.0, -15.0];rightAngles[1][FOOT] = [6.0, -8.0, 0.0];rightAngles[1][TOE] = [0.0, 0.0, 0.0]; leftAngles[1][HIP] = [10.0, 0.0, 8.0];leftAngles[1][KNEE] = [-60.0, 0.0, 0.0];leftAngles[1][ARM] = [85.0, 0.0, 0.0];leftAngles[1][FOREARM] = [0.0, 0.0, -15.0];leftAngles[1][FOOT] = [0.0, 0.0, 0.0];leftAngles[1][TOE] = [0.0, 0.0, 0.0]; middleAngles[1][SPINE] = [0.0, 0.0, 0.0]; //Actual keyframes for the animationvar walkKeyFrames = procAnimAPI.generateKeyframes(rightAngles, leftAngles, middleAngles, NUM_FRAMES); //  Animation Is Defined Above //  Standing Key Frame //We don't have to do any mirroring or anything, since this is just a single pose.var rightQuats = [];var leftQuats = [];var middleQuats = []; rightQuats[HIP] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 7.0);

Lines 1–500 of 735.