Guest User

Untitled

a guest
Apr 9th, 2018
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.24 KB | None | 0 0
  1. /*
  2. ** 2012 Januar 21
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. ** May you do good and not evil.
  7. ** May you find forgiveness for yourself and forgive others.
  8. ** May you share freely, never taking more than you give.
  9. */
  10. package com.TheRPGAdventurer.ROTD.client.model.anim;
  11.  
  12. import com.TheRPGAdventurer.ROTD.client.model.DragonModel;
  13. import com.TheRPGAdventurer.ROTD.client.model.ModelPart;
  14. import com.TheRPGAdventurer.ROTD.server.entity.EntityTameableDragon;
  15. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonHeadPositionHelper;
  16. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonHelper;
  17. import com.TheRPGAdventurer.ROTD.server.entity.helper.breath.DragonBreathHelper;
  18. import com.TheRPGAdventurer.ROTD.util.math.Interpolation;
  19. import com.TheRPGAdventurer.ROTD.util.math.MathX;
  20.  
  21. import net.minecraft.util.math.BlockPos;
  22. import net.minecraft.util.math.Vec3d;
  23.  
  24. /**
  25. * Animation control class to put useless reptiles in motion.
  26. *
  27. * @author Nico Bergemann <barracuda415 at yahoo.de>
  28. */
  29. public class DragonAnimator extends DragonHelper {
  30.  
  31. // constants
  32. private static final int JAW_OPENING_TIME_FOR_ATTACK = 5;
  33.  
  34. private final DragonHeadPositionHelper dragonHeadPositionHelper;
  35. private DragonModel model;
  36.  
  37. private boolean haveCalculatedAnimations = false;
  38.  
  39. // entity parameters
  40. private float partialTicks;
  41. private float moveTime;
  42. private float moveSpeed;
  43. private float lookYaw;
  44. private float lookPitch;
  45. private double prevRenderYawOffset;
  46. private double yawAbs;
  47. private BlockPos pos;
  48.  
  49. // timing vars
  50. private float animBase;
  51. private float cycleOfs;
  52. private float anim;
  53. private float ground;
  54. private float flutter;
  55. private float walk;
  56. private float sit;
  57. private float speed;
  58. private float bite;
  59. private float breath;
  60.  
  61. // timing interp vars
  62. private TickFloat animTimer = new TickFloat();
  63. private TickFloat biteTimer = new TickFloat().setLimit(0, 1);
  64. private TickFloat breathTimer = new TickFloat().setLimit(0, 1);
  65. private TickFloat groundTimer = new TickFloat(1).setLimit(0, 1);
  66. private TickFloat flutterTimer = new TickFloat().setLimit(0, 1);
  67. private TickFloat walkTimer = new TickFloat().setLimit(0, 1);
  68. private TickFloat sitTimer = new TickFloat().setLimit(0, 1);
  69. private TickFloat jawTimer = new TickFloat().setLimit(0, 1);
  70. private TickFloat speedTimer = new TickFloat(1).setLimit(0, 1);
  71.  
  72. // trails
  73. private boolean initTrails = true;
  74. private CircularBuffer yTrail = new CircularBuffer(8);
  75. private CircularBuffer yawTrail = new CircularBuffer(16);
  76. private CircularBuffer pitchTrail = new CircularBuffer(16);
  77.  
  78. // model flags
  79. private boolean onGround;
  80. private boolean openJaw;
  81. private boolean wingsDown;
  82.  
  83. private float jawRotateAngleX;
  84. private float[] wingFingerRotateX;
  85. private float[] wingFingerRotateY;
  86.  
  87. // animation parameters
  88. private float[] wingArm = new float[3];
  89. private float[] wingForearm = new float[3];
  90. private float[] wingArmFlutter = new float[3];
  91. private float[] wingForearmFlutter = new float[3];
  92. private float[] wingArmGlide = new float[3];
  93. private float[] wingForearmGlide = new float[3];
  94. private float[] wingArmGround = new float[3];
  95. private float[] wingForearmGround = new float[3];
  96.  
  97. private final int WING_FINGERS;
  98. private final int NECK_SEGMENTS;
  99. private final int TAIL_SEGMENTS;
  100.  
  101. // final X rotation angles for ground
  102. private float[] xGround = {0, 0, 0, 0};
  103.  
  104. // X rotation angles for ground
  105. // 1st dim - front, hind
  106. // 2nd dim - thigh, crus, foot, toe
  107. private float[][] xGroundStand = {
  108. {0.8f, -1.5f, 1.3f, 0},
  109. {-0.3f, 1.5f, -0.2f, 0},
  110. };
  111. private float[][] xGroundSit = {
  112. {0.3f, -1.8f, 1.8f, 0},
  113. {-0.8f, 1.8f, -0.9f, 0},
  114. };
  115.  
  116. // X rotation angles for walking
  117. // 1st dim - animation keyframe
  118. // 2nd dim - front, hind
  119. // 3rd dim - thigh, crus, foot, toe
  120. private float[][][] xGroundWalk = {{
  121. {0.4f, -1.4f, 1.3f, 0}, // move down and forward
  122. {0.1f, 1.2f, -0.5f, 0} // move back
  123. }, {
  124. {1.2f, -1.6f, 1.3f, 0}, // move back
  125. {-0.3f, 2.1f, -0.9f, 0.6f} // move up and forward
  126. }, {
  127. {0.9f, -2.1f, 1.8f, 0.6f}, // move up and forward
  128. {-0.7f, 1.4f, -0.2f, 0} // move down and forward
  129. }};
  130.  
  131. // final X rotation angles for walking
  132. private float[] xGroundWalk2 = {0, 0, 0, 0};
  133.  
  134. // Y rotation angles for ground, thigh only
  135. private float[] yGroundStand = {-0.25f, 0.25f};
  136. private float[] yGroundSit = {0.1f, 0.35f};
  137. private float[] yGroundWalk = {-0.1f, 0.1f};
  138.  
  139. // final X rotation angles for air
  140. private float[] xAir;
  141.  
  142. // X rotation angles for air
  143. // 1st dim - front, hind
  144. // 2nd dim - thigh, crus, foot, toe
  145. private float[][] xAirAll = {{0, 0, 0, 0}, {0, 0, 0, 0}};
  146.  
  147. // Y rotation angles for air, thigh only
  148. private float[] yAirAll = {-0.1f, 0.1f};
  149.  
  150. public DragonAnimator(EntityTameableDragon dragon) {
  151. super(dragon);
  152. WING_FINGERS = dragon.getBreedType().getNumberOfWingFingers();
  153. NECK_SEGMENTS = dragon.getBreedType().getNumberOfNeckSegments();
  154. TAIL_SEGMENTS = dragon.getBreedType().getNumberOfTailSegments();
  155.  
  156. wingFingerRotateX = new float[WING_FINGERS];
  157. wingFingerRotateY = new float[WING_FINGERS];
  158. dragonHeadPositionHelper = new DragonHeadPositionHelper(dragon, NECK_SEGMENTS);
  159. }
  160.  
  161. public void setPartialTicks(float partialTicks) {
  162. this.partialTicks = partialTicks;
  163. }
  164.  
  165. public void setMovement(float moveTime, float moveSpeed) {
  166. this.moveTime = moveTime;
  167. this.moveSpeed = moveSpeed;
  168. }
  169.  
  170. public void setLook(float lookYaw, float lookPitch) {
  171. // don't twist the neck
  172. this.lookYaw = MathX.clamp(lookYaw, -120, 120);
  173. this.lookPitch = MathX.clamp(lookPitch, -90, 90);
  174. }
  175.  
  176. /**
  177. * Applies the animations on the model. Called every frame before the model
  178. * is rendered.
  179. *
  180. * @param model model to animate
  181. */
  182. public void animate(DragonModel model) {
  183. anim = animTimer.get(partialTicks);
  184. ground = groundTimer.get(partialTicks);
  185. flutter = flutterTimer.get(partialTicks);
  186. bite = biteTimer.get(partialTicks);
  187. breath = breathTimer.get(partialTicks);
  188. walk = walkTimer.get(partialTicks);
  189. sit = sitTimer.get(partialTicks);
  190. speed = speedTimer.get(partialTicks);
  191.  
  192. animBase = anim * MathX.PI_F * 2;
  193. cycleOfs = MathX.sin(animBase - 1) + 1;
  194.  
  195. // check if the wings are moving down and trigger the event
  196. boolean newWingsDown = cycleOfs > 1;
  197. if (newWingsDown && !wingsDown && flutter != 0) {
  198. dragon.getSoundManager().onWingsDown(speed);
  199. }
  200. wingsDown = newWingsDown;
  201.  
  202. // update flags
  203. model.back.isHidden = dragon.isSaddled();
  204.  
  205. cycleOfs = (cycleOfs * cycleOfs + cycleOfs * 2) * 0.05f;
  206.  
  207. // reduce up/down amplitude
  208. cycleOfs *= Interpolation.linear(0.5f, 1, flutter);
  209. cycleOfs *= Interpolation.linear(1, 0.5f, ground);
  210.  
  211. // update offsets
  212. model.offsetX = getModelOffsetX();
  213. model.offsetY = getModelOffsetY();
  214. model.offsetZ = getModelOffsetZ();
  215.  
  216. // update pitch
  217. model.pitch = getModelPitch();
  218.  
  219. // animate body parts
  220. animHeadAndNeck(model);
  221. animTail(model);
  222. animWings(model);
  223. animLegs(model);
  224. }
  225.  
  226. /**
  227. * Updates the animation state. Called on every tick.
  228. */
  229. @Override
  230. public void onLivingUpdate() {
  231. if (!dragon.isEgg()) {
  232. setOnGround(!dragon.isFlying());
  233. }
  234.  
  235. // init trails
  236. if (initTrails) {
  237. yTrail.fill((float) dragon.posY);
  238. yawTrail.fill(dragon.renderYawOffset);
  239. pitchTrail.fill(getModelPitch());
  240. initTrails = false;
  241. }
  242.  
  243. // don't move anything during death sequence
  244. if (dragon.getHealth() <= 0) {
  245. animTimer.sync();
  246. groundTimer.sync();
  247. flutterTimer.sync();
  248. walkTimer.sync();
  249. sitTimer.sync();
  250. jawTimer.sync();
  251. biteTimer.sync();
  252. return;
  253. }
  254.  
  255. float speedMax = 0.05f;
  256. float speedEnt = (float) (dragon.motionX * dragon.motionX + dragon.motionZ * dragon.motionZ);
  257. float speedMulti = MathX.clamp(speedEnt / speedMax, 0, 1);
  258.  
  259. // update main animation timer
  260. float animAdd = 0.035f;
  261.  
  262. // depend timing speed on movement
  263. if (!onGround) {
  264. animAdd += (1 - speedMulti) * animAdd;
  265. }
  266.  
  267. animTimer.add(animAdd);
  268.  
  269. // update ground transition
  270. float groundVal = groundTimer.get();
  271. if (onGround) {
  272. groundVal *= 0.95f;
  273. groundVal += 0.08f;
  274. } else {
  275. groundVal -= 0.1f;
  276. }
  277. groundTimer.set(groundVal);
  278.  
  279. // update flutter transition
  280. boolean flutterFlag = !onGround && (dragon.isCollided || dragon.motionY > -0.1 || speedEnt < speedMax);
  281. flutterTimer.add(flutterFlag ? 0.1f : -0.1f);
  282.  
  283. // update walking transition
  284. boolean walkFlag = moveSpeed > 0.1 && !dragon.isSitting();
  285. float walkVal = 0.1f;
  286. walkTimer.add(walkFlag ? walkVal : -walkVal);
  287.  
  288. // update sitting transisiton
  289. float sitVal = sitTimer.get();
  290. sitVal += dragon.isSitting() ? 0.1f : -0.1f;
  291. sitVal *= 0.95f;
  292. sitTimer.set(sitVal);
  293.  
  294. // update bite opening transition and breath transitions
  295. DragonBreathHelper.BreathState breathState = dragon.getBreathHelper().getCurrentBreathState();
  296. switch (breathState) {
  297. case IDLE: { // breath is idle, handle bite attack
  298. int ticksSinceLastAttack = dragon.getTicksSinceLastAttack();
  299. final int JAW_OPENING_TIME_FOR_ATTACK = 5;
  300. boolean jawFlag = (ticksSinceLastAttack >= 0 && ticksSinceLastAttack < JAW_OPENING_TIME_FOR_ATTACK);
  301. biteTimer.add(jawFlag ? 0.2f : -0.2f);
  302. breathTimer.set(0.0F);
  303. break;
  304. }
  305. case STARTING: {
  306. biteTimer.set(0.0F);
  307. breathTimer.set(dragon.getBreathHelper().getBreathStateFractionComplete());
  308. break;
  309. }
  310. case STOPPING: {
  311. float breathStateFractionComplete = dragon.getBreathHelper().getBreathStateFractionComplete();
  312. breathTimer.set(1.0F - breathStateFractionComplete);
  313. break;
  314. }
  315. case SUSTAIN: {
  316. breathTimer.set(1.0F);
  317. break;
  318. }
  319. default: {
  320. System.err.println("unexpected breathstate:" + breathState);
  321. return;
  322. }
  323. }
  324.  
  325. // update speed transition
  326. boolean nearGround = dragon.getAltitude() < dragon.height * 2;
  327. boolean speedFlag = speedEnt > speedMax || onGround || nearGround;
  328. float speedValue = 0.05f;
  329. speedTimer.add(speedFlag ? speedValue : -speedValue);
  330.  
  331. // update trailers
  332. double yawDiff = dragon.renderYawOffset - prevRenderYawOffset;
  333. prevRenderYawOffset = dragon.renderYawOffset;
  334.  
  335. // filter out 360 degrees wrapping
  336. if (yawDiff < 180 && yawDiff > -180) {
  337. yawAbs += yawDiff;
  338. }
  339.  
  340. // TODO: where's yOffset?
  341. //yTrail.update(entity.posY - entity.yOffset);
  342. yTrail.update((float) dragon.posY);
  343. yawTrail.update((float) yawAbs);
  344. pitchTrail.update(getModelPitch());
  345. }
  346.  
  347. public float getAnimTime() {
  348. return anim;
  349. }
  350.  
  351. public float getGroundTime() {
  352. return ground;
  353. }
  354.  
  355. public float getFlutterTime() {
  356. return flutter;
  357. }
  358.  
  359. public float getWalkTime() {
  360. return walk;
  361. }
  362.  
  363. protected void animHeadAndNeck(DragonModel model) {
  364. model.neck.rotationPointX = 0;
  365. model.neck.rotationPointY = 14;
  366. model.neck.rotationPointZ = -8;
  367.  
  368. model.neck.rotateAngleX = 0;
  369. model.neck.rotateAngleY = 0;
  370. model.neck.rotateAngleZ = 0;
  371.  
  372. float health = (float) dragon.getHealthRelative();
  373. float neckSize;
  374.  
  375. for (int i = 0; i < model.neckProxy.length; i++) {
  376. float vertMulti = (i + 1) / (float) model.neckProxy.length;
  377.  
  378. float baseRotX = MathX.cos((float) i * 0.45f + animBase) * 0.15f;
  379. baseRotX *= Interpolation.linear(0.2f, 1, flutter);
  380. baseRotX *= Interpolation.linear(1, 0.2f, sit);
  381. float ofsRotX = MathX.sin(vertMulti * MathX.PI_F * 0.9f) * 0.75f;
  382.  
  383. // basic up/down movement
  384. model.neck.rotateAngleX = baseRotX;
  385. // reduce rotation when on ground
  386. model.neck.rotateAngleX *= Interpolation.smoothStep(1, 0.5f, walk);
  387. // flex neck down when hovering
  388. model.neck.rotateAngleX += (1 - speed) * vertMulti;
  389. // lower neck on low health
  390. model.neck.rotateAngleX -= Interpolation.linear(0, ofsRotX, ground * health);
  391. // use looking yaw
  392. model.neck.rotateAngleY = MathX.toRadians(lookYaw) * vertMulti * speed;
  393.  
  394. // update scale
  395. model.neck.renderScaleX = model.neck.renderScaleY = Interpolation.linear(1.6f, 1, vertMulti);
  396. model.neck.renderScaleZ = 0.6f;
  397.  
  398. // hide the first and every second scale
  399. model.neckScale.isHidden = i % 2 != 0 || i == 0;
  400.  
  401. // update proxy
  402. model.neckProxy[i].update();
  403.  
  404. // move next proxy behind the current one
  405. neckSize = DragonModel.NECK_SIZE * model.neck.renderScaleZ - 1.4f;
  406. model.neck.rotationPointX -= MathX.sin(model.neck.rotateAngleY) * MathX.cos(model.neck.rotateAngleX) * neckSize;
  407. model.neck.rotationPointY += MathX.sin(model.neck.rotateAngleX) * neckSize;
  408. model.neck.rotationPointZ -= MathX.cos(model.neck.rotateAngleY) * MathX.cos(model.neck.rotateAngleX) * neckSize;
  409. }
  410.  
  411. final float HEAD_TILT_DURING_BREATH = -0.1F;
  412. model.head.rotateAngleX = MathX.toRadians(lookPitch) + (1 - speed) + breath * HEAD_TILT_DURING_BREATH;
  413. model.head.rotateAngleY = model.neck.rotateAngleY;
  414. model.head.rotateAngleZ = model.neck.rotateAngleZ * 0.2f;
  415.  
  416. model.head.rotationPointX = model.neck.rotationPointX;
  417. model.head.rotationPointY = model.neck.rotationPointY;
  418. model.head.rotationPointZ = model.neck.rotationPointZ;
  419.  
  420. final float BITE_ANGLE = 0.75F;
  421. final float BREATH_ANGLE = 0.75F;
  422. model.jaw.rotateAngleX = (bite * BITE_ANGLE + breath * BREATH_ANGLE);
  423. model.jaw.rotateAngleX += (1 - MathX.sin(animBase)) * 0.1f * flutter;
  424. }
  425.  
  426. protected void animWings(DragonModel model) {
  427. // move wings slower while sitting
  428. float aSpeed = sit > 0 ? 0.6f : 1;
  429.  
  430. // animation speeds
  431. float a1 = animBase * aSpeed * 0.35f;
  432. float a2 = animBase * aSpeed * 0.5f;
  433. float a3 = animBase * aSpeed * 0.75f;
  434.  
  435. if (ground < 1) {
  436. // fluttering
  437. wingArmFlutter[0] = 0.125f - MathX.cos(animBase) * 0.2f ;
  438. wingArmFlutter[1] = 0.25f;
  439. wingArmFlutter[2] = (MathX.sin(animBase) + 0.125f) * 0.8f;
  440.  
  441. wingForearmFlutter[0] = 0;
  442. wingForearmFlutter[1] = -wingArmFlutter[1] * 2;
  443. wingForearmFlutter[2] = -(MathX.sin(animBase + 2) + 0.5f) * 0.75f;
  444.  
  445. // gliding
  446. wingArmGlide[0] = -0.25f - MathX.cos(animBase * 2) * MathX.cos(animBase * 1.5f) * 0.04f;
  447. wingArmGlide[1] = 0.25f;
  448. wingArmGlide[2] = 0.35f + MathX.sin(animBase) * 0.05f;
  449.  
  450. wingForearmGlide[0] = 0;
  451. wingForearmGlide[1] = -wingArmGlide[1] * 2;
  452. wingForearmGlide[2] = -0.25f + (MathX.sin(animBase + 2) + 0.5f) * 0.05f;
  453. }
  454.  
  455. if (ground > 0) {
  456. // standing
  457. wingArmGround[0] = 0;
  458. wingArmGround[1] = 1.4f - MathX.sin(a1) * MathX.sin(a2) * 0.02f;
  459. wingArmGround[2] = 0.8f + MathX.sin(a2) * MathX.sin(a3) * 0.05f;
  460.  
  461. // walking
  462. wingArmGround[1] += MathX.sin(moveTime * 0.5f) * 0.02f * walk;
  463. wingArmGround[2] += MathX.cos(moveTime * 0.5f) * 0.05f * walk;
  464.  
  465. wingForearmGround[0] = 0;
  466. wingForearmGround[1] = -wingArmGround[1] * 2;
  467. wingForearmGround[2] = 0;
  468. }
  469.  
  470. // interpolate between fluttering and gliding
  471. slerpArrays(wingArmGlide, wingArmFlutter, wingArm, flutter);
  472. slerpArrays(wingForearmGlide, wingForearmFlutter, wingForearm, flutter);
  473.  
  474. // interpolate between flying and grounded
  475. slerpArrays(wingArm, wingArmGround, wingArm, ground);
  476. slerpArrays(wingForearm, wingForearmGround, wingForearm, ground);
  477.  
  478. // apply angles
  479. model.wingArm.rotateAngleX = wingArm[0];
  480. model.wingArm.rotateAngleY = wingArm[1];
  481. model.wingArm.rotateAngleZ = wingArm[2];
  482. model.wingArm.preRotateAngleX = 1 - speed;
  483. model.wingForearm.rotateAngleX = wingForearm[0];
  484. model.wingForearm.rotateAngleY = wingForearm[1];
  485. model.wingForearm.rotateAngleZ = wingForearm[2];
  486.  
  487. // interpolate between folded and unfolded wing angles
  488. float[] yFold = new float[] {2.7f, 2.8f, 2.9f, 3.0f};
  489. float[] yUnfold = new float[] {0.1f, 0.9f, 1.7f, 2.5f};
  490.  
  491. // set wing finger angles
  492. float rotX = 0;
  493. float rotYOfs = MathX.sin(a1) * MathX.sin(a2) * 0.03f;
  494. float rotYMulti = 1;
  495.  
  496. for (int i = 0; i < model.wingFinger.length; i++) {
  497. model.wingFinger[i].rotateAngleX = rotX += 0.005f; // reduce Z-fighting
  498. model.wingFinger[i].rotateAngleY = Interpolation.smoothStep(yUnfold[i],
  499. yFold[i] + rotYOfs * rotYMulti, ground);
  500. rotYMulti -= 0.2f;
  501. }
  502. }
  503.  
  504. protected void animTail(DragonModel model) {
  505. model.tail.rotationPointX = 0;
  506. model.tail.rotationPointY = 16;
  507. model.tail.rotationPointZ = 62;
  508.  
  509. model.tail.rotateAngleX = 0;
  510. model.tail.rotateAngleY = 0;
  511. model.tail.rotateAngleZ = 0;
  512.  
  513. float rotXStand = 0;
  514. float rotYStand = 0;
  515. float rotXSit = 0;
  516. float rotYSit = 0;
  517. float rotXAir = 0;
  518. float rotYAir = 0;
  519.  
  520. for (int i = 0; i < model.tailProxy.length; i++) {
  521. float vertMulti = (i + 1) / (float) model.tailProxy.length;
  522.  
  523. // idle
  524. float amp = 0.1f + i / (model.tailProxy.length * 2f);
  525.  
  526. rotXStand = (i - model.tailProxy.length * 0.6f) * -amp * 0.4f;
  527. rotXStand += (MathX.sin(animBase * 0.2f) * MathX.sin(animBase * 0.37f) * 0.4f * amp - 0.1f) * (1 - sit);
  528. rotXSit = rotXStand * 0.8f;
  529.  
  530. rotYStand = (rotYStand + MathX.sin(i * 0.45f + animBase * 0.5f)) * amp * 0.4f;
  531. rotYSit = MathX.sin(vertMulti * MathX.PI_F) * MathX.PI_F * 1.2f - 0.5f; // curl to the left
  532.  
  533. rotXAir -= MathX.sin(i * 0.45f + animBase) * 0.04f * Interpolation.linear(0.3f, 1, flutter);
  534.  
  535. // interpolate between sitting and standing
  536. model.tail.rotateAngleX = Interpolation.linear(rotXStand, rotXSit, sit);
  537. model.tail.rotateAngleY = Interpolation.linear(rotYStand, rotYSit, sit);
  538.  
  539. // interpolate between flying and grounded
  540. model.tail.rotateAngleX = Interpolation.linear(rotXAir, model.tail.rotateAngleX, ground);
  541. model.tail.rotateAngleY = Interpolation.linear(rotYAir, model.tail.rotateAngleY, ground);
  542.  
  543. // body movement
  544. float angleLimit = 160 * vertMulti;
  545. float yawOfs = MathX.clamp((float) yawTrail.get(partialTicks, 0, i + 1) * 2, -angleLimit, angleLimit);
  546. float pitchOfs = MathX.clamp((float) pitchTrail.get(partialTicks, 0, i + 1) * 2, -angleLimit, angleLimit);
  547.  
  548. model.tail.rotateAngleX += MathX.toRadians(pitchOfs);
  549. model.tail.rotateAngleX -= (1 - speed) * vertMulti * 2;
  550. model.tail.rotateAngleY += MathX.toRadians(180 - yawOfs);
  551.  
  552. // display horns near the tip
  553. boolean horn = i > model.tailProxy.length - 7 && i < model.tailProxy.length - 3;
  554. model.tailHornLeft.isHidden = model.tailHornRight.isHidden = !horn;
  555.  
  556. // update scale
  557. float neckScale = Interpolation.linear(1.5f, 0.3f, vertMulti);
  558. model.tail.setRenderScale(neckScale);
  559.  
  560. // update proxy
  561. model.tailProxy[i].update();
  562.  
  563. // move next proxy behind the current one
  564. float tailSize = DragonModel.TAIL_SIZE * model.tail.renderScaleZ - 0.7f;
  565. model.tail.rotationPointY += MathX.sin(model.tail.rotateAngleX) * tailSize;
  566. model.tail.rotationPointZ -= MathX.cos(model.tail.rotateAngleY) * MathX.cos(model.tail.rotateAngleX) * tailSize;
  567. model.tail.rotationPointX -= MathX.sin(model.tail.rotateAngleY) * MathX.cos(model.tail.rotateAngleX) * tailSize;
  568. }
  569. }
  570.  
  571. protected void animLegs(DragonModel model) {
  572. // dangling legs for flying
  573. if (ground < 1) {
  574. float footAirOfs = cycleOfs * 0.1f;
  575. float footAirX = 0.75f + cycleOfs * 0.1f;
  576.  
  577. xAirAll[0][0] = 1.3f + footAirOfs;
  578. xAirAll[0][1] = -(0.7f * speed + 0.1f + footAirOfs);
  579. xAirAll[0][2] = footAirX;
  580. xAirAll[0][3] = footAirX * 0.5f;
  581.  
  582. xAirAll[1][0] = footAirOfs + 0.6f;
  583. xAirAll[1][1] = footAirOfs + 0.8f;
  584. xAirAll[1][2] = footAirX;
  585. xAirAll[1][3] = footAirX * 0.5f;
  586. }
  587.  
  588. // 0 - front leg, right side
  589. // 1 - hind leg, right side
  590. // 2 - front leg, left side
  591. // 3 - hind leg, left side
  592. for (int i = 0; i < model.thighProxy.length; i++) {
  593. ModelPart thigh, crus, foot, toe;
  594.  
  595. if (i % 2 == 0) {
  596. thigh = model.forethigh;
  597. crus = model.forecrus;
  598. foot = model.forefoot;
  599. toe = model.foretoe;
  600.  
  601. thigh.rotationPointZ = 4;
  602. } else {
  603. thigh = model.hindthigh;
  604. crus = model.hindcrus;
  605. foot = model.hindfoot;
  606. toe = model.hindtoe;
  607.  
  608. thigh.rotationPointZ = 46;
  609. }
  610.  
  611. xAir = xAirAll[i % 2];
  612.  
  613. // interpolate between sitting and standing
  614. slerpArrays(xGroundStand[i % 2], xGroundSit[i % 2], xGround, sit);
  615.  
  616. // align the toes so they're always horizontal on the ground
  617. xGround[3] = -(xGround[0] + xGround[1] + xGround[2]);
  618.  
  619. // apply walking cycle
  620. if (walk > 0) {
  621. // interpolate between the keyframes, based on the cycle
  622. splineArrays(moveTime * 0.2f, i > 1, xGroundWalk2,
  623. xGroundWalk[0][i % 2], xGroundWalk[1][i % 2], xGroundWalk[2][i % 2]);
  624. // align the toes so they're always horizontal on the ground
  625. xGroundWalk2[3] -= xGroundWalk2[0] + xGroundWalk2[1] + xGroundWalk2[2];
  626.  
  627. slerpArrays(xGround, xGroundWalk2, xGround, walk);
  628. }
  629.  
  630. float yAir = yAirAll[i % 2];
  631. float yGround;
  632.  
  633. // interpolate between sitting and standing
  634. yGround = Interpolation.smoothStep(yGroundStand[i % 2], yGroundSit[i % 2], sit);
  635.  
  636. // interpolate between standing and walking
  637. yGround = Interpolation.smoothStep(yGround, yGroundWalk[i % 2], walk);
  638.  
  639. // interpolate between flying and grounded
  640. thigh.rotateAngleY = Interpolation.smoothStep(yAir, yGround, ground);
  641. thigh.rotateAngleX = Interpolation.smoothStep(xAir[0], xGround[0], ground);
  642. crus.rotateAngleX = Interpolation.smoothStep(xAir[1], xGround[1], ground);
  643. foot.rotateAngleX = Interpolation.smoothStep(xAir[2], xGround[2], ground);
  644. toe.rotateAngleX = Interpolation.smoothStep(xAir[3], xGround[3], ground);
  645.  
  646. // update proxy
  647. model.thighProxy[i].update();
  648. }
  649. }
  650.  
  651. private void splineArrays(float x, boolean shift, float[] result, float[]... nodes) {
  652. // uncomment to disable interpolation
  653. // if (true) {
  654. // if (shift) {
  655. // System.arraycopy(nodes[(int) (x + 1) % nodes.length], 0, result, 0, nodes.length);
  656. // } else {
  657. // System.arraycopy(nodes[(int) x % nodes.length], 0, result, 0, nodes.length);
  658. // }
  659. // return;
  660. // }
  661.  
  662. int i1 = (int) x % nodes.length;
  663. int i2 = (i1 + 1) % nodes.length;
  664. int i3 = (i1 + 2) % nodes.length;
  665.  
  666. float[] a1 = nodes[i1];
  667. float[] a2 = nodes[i2];
  668. float[] a3 = nodes[i3];
  669.  
  670. float xn = x % nodes.length - i1;
  671.  
  672. if (shift) {
  673. Interpolation.catmullRomSpline(xn, result, a2, a3, a1, a2);
  674. } else {
  675. Interpolation.catmullRomSpline(xn, result, a1, a2, a3, a1);
  676. }
  677. }
  678.  
  679. private void slerpArrays(float[] a, float[] b, float[] c, float x) {
  680. if (a.length != b.length || b.length != c.length) {
  681. throw new IllegalArgumentException();
  682. }
  683.  
  684. if (x <= 0) {
  685. System.arraycopy(a, 0, c, 0, a.length);
  686. return;
  687. }
  688. if (x >= 1) {
  689. System.arraycopy(b, 0, c, 0, a.length);
  690. return;
  691. }
  692.  
  693. for (int i = 0; i < c.length; i++) {
  694. c[i] = Interpolation.smoothStep(a[i], b[i], x);
  695. }
  696. }
  697.  
  698. public float getModelPitch() {
  699. return getModelPitch(partialTicks);
  700. }
  701.  
  702. public float getModelPitch(float pt) {
  703. float pitchMovingMax = 90;
  704. float pitchMoving = MathX.clamp(yTrail.get(pt, 5, 0) * 10, -pitchMovingMax, pitchMovingMax);
  705. float pitchHover = 60;
  706. return Interpolation.smoothStep(pitchHover, pitchMoving, speed);
  707. }
  708.  
  709. public float getBodyPitch() {
  710. return getBodyPitch(partialTicks);
  711. }
  712.  
  713. public float getBodyPitch(float pt) {
  714. float pitchMovingMax = 90;
  715. float pitchMoving = (float) MathX.clamp(yTrail.getChangeInValue(pt, 5, 0) * 10, -pitchMovingMax, pitchMovingMax);
  716. float pitchHover = 60;
  717. return MathX.slerp(pitchHover, pitchMoving, speed);
  718. }
  719.  
  720. public float getModelOffsetX() {
  721. return 0;
  722. }
  723.  
  724. public float getModelOffsetY() {
  725. return -1.5f + (sit * 0.6f);
  726. }
  727.  
  728. public float getModelOffsetZ() {
  729. return -1.5f;
  730. }
  731.  
  732. public boolean isOnGround() {
  733. return onGround;
  734. }
  735.  
  736. public void setOnGround(boolean onGround) {
  737. this.onGround = onGround;
  738. }
  739.  
  740. public boolean isOpenJaw() {
  741. return openJaw;
  742. }
  743.  
  744. public void setOpenJaw(boolean openJaw) {
  745. this.openJaw = openJaw;
  746. }
  747.  
  748. public Vec3d getThroatPosition() {
  749. if (!haveCalculatedAnimations) {
  750. animate(model);
  751. }
  752. return dragonHeadPositionHelper.getThroatPosition();
  753. }
  754. }
Add Comment
Please, Sign In to add comment