diff options
author | Melanie | 2010-10-02 00:19:30 +0200 |
---|---|---|
committer | Melanie | 2010-10-02 00:19:30 +0200 |
commit | b40c91777cf272b485da0cdfba2ffec868cfc7cf (patch) | |
tree | 16bd545ba26474fd76fe736eb691222b1b740a30 /OpenSim/Region | |
parent | Replace CalculateMass with a better, contributed version (diff) | |
download | opensim-SC-b40c91777cf272b485da0cdfba2ffec868cfc7cf.zip opensim-SC-b40c91777cf272b485da0cdfba2ffec868cfc7cf.tar.gz opensim-SC-b40c91777cf272b485da0cdfba2ffec868cfc7cf.tar.bz2 opensim-SC-b40c91777cf272b485da0cdfba2ffec868cfc7cf.tar.xz |
Replace CalculateMass with a more accurate version, contributed by Ubit.
Thank you.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 453 |
1 files changed, 219 insertions, 234 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index daf7fb0..319a951 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | |||
@@ -403,300 +403,285 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
403 | 403 | ||
404 | private float CalculateMass() | 404 | private float CalculateMass() |
405 | { | 405 | { |
406 | float volume = 0; | 406 | float volume = _size.X * _size.Y * _size.Z; // default |
407 | 407 | float tmp; | |
408 | // No material is passed to the physics engines yet.. soo.. | ||
409 | // we're using the m_density constant in the class definition | ||
410 | 408 | ||
411 | float returnMass = 0; | 409 | float returnMass = 0; |
412 | 410 | float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; | |
411 | float hollowVolume = hollowAmount * hollowAmount; | ||
412 | |||
413 | switch (_pbs.ProfileShape) | 413 | switch (_pbs.ProfileShape) |
414 | { | 414 | { |
415 | case ProfileShape.Square: | 415 | case ProfileShape.Square: |
416 | // Profile Volume | 416 | // default box |
417 | 417 | ||
418 | volume = _size.X*_size.Y*_size.Z; | 418 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
419 | { | ||
420 | if (hollowAmount > 0.0) | ||
421 | { | ||
422 | switch (_pbs.HollowShape) | ||
423 | { | ||
424 | case HollowShape.Square: | ||
425 | case HollowShape.Same: | ||
426 | break; | ||
419 | 427 | ||
420 | // If the user has 'hollowed out' | 428 | case HollowShape.Circle: |
421 | // ProfileHollow is one of those 0 to 50000 values :P | ||
422 | // we like percentages better.. so turning into a percentage | ||
423 | 429 | ||
424 | if (((float) _pbs.ProfileHollow/50000f) > 0.0) | 430 | hollowVolume *= 0.78539816339f; |
425 | { | 431 | break; |
426 | float hollowAmount = (float) _pbs.ProfileHollow/50000f; | ||
427 | 432 | ||
428 | // calculate the hollow volume by it's shape compared to the prim shape | 433 | case HollowShape.Triangle: |
429 | float hollowVolume = 0; | ||
430 | switch (_pbs.HollowShape) | ||
431 | { | ||
432 | case HollowShape.Square: | ||
433 | case HollowShape.Same: | ||
434 | // Cube Hollow volume calculation | ||
435 | float hollowsizex = _size.X*hollowAmount; | ||
436 | float hollowsizey = _size.Y*hollowAmount; | ||
437 | float hollowsizez = _size.Z*hollowAmount; | ||
438 | hollowVolume = hollowsizex*hollowsizey*hollowsizez; | ||
439 | break; | ||
440 | 434 | ||
441 | case HollowShape.Circle: | 435 | hollowVolume *= (0.5f * .5f); |
442 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | 436 | break; |
443 | // Cyllinder hollow volume calculation | ||
444 | float hRadius = _size.X/2; | ||
445 | float hLength = _size.Z; | ||
446 | |||
447 | // pi * r2 * h | ||
448 | hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); | ||
449 | break; | ||
450 | 437 | ||
451 | case HollowShape.Triangle: | 438 | default: |
452 | // Equilateral Triangular Prism volume hollow calculation | 439 | hollowVolume = 0; |
453 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | 440 | break; |
441 | } | ||
442 | volume *= (1.0f - hollowVolume); | ||
443 | } | ||
444 | } | ||
454 | 445 | ||
455 | float aLength = _size.Y; | 446 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
456 | // 1/2 abh | 447 | { |
457 | hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); | 448 | //a tube |
458 | break; | ||
459 | 449 | ||
460 | default: | 450 | volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); |
461 | hollowVolume = 0; | 451 | tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); |
462 | break; | 452 | volume -= volume*tmp*tmp; |
453 | |||
454 | if (hollowAmount > 0.0) | ||
455 | { | ||
456 | hollowVolume *= hollowAmount; | ||
457 | |||
458 | switch (_pbs.HollowShape) | ||
459 | { | ||
460 | case HollowShape.Square: | ||
461 | case HollowShape.Same: | ||
462 | break; | ||
463 | |||
464 | case HollowShape.Circle: | ||
465 | hollowVolume *= 0.78539816339f;; | ||
466 | break; | ||
467 | |||
468 | case HollowShape.Triangle: | ||
469 | hollowVolume *= 0.5f * 0.5f; | ||
470 | break; | ||
471 | default: | ||
472 | hollowVolume = 0; | ||
473 | break; | ||
474 | } | ||
475 | volume *= (1.0f - hollowVolume); | ||
476 | } | ||
463 | } | 477 | } |
464 | volume = volume - hollowVolume; | ||
465 | } | ||
466 | 478 | ||
467 | break; | 479 | break; |
480 | |||
468 | case ProfileShape.Circle: | 481 | case ProfileShape.Circle: |
469 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
470 | { | ||
471 | // Cylinder | ||
472 | float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); | ||
473 | float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); | ||
474 | 482 | ||
475 | // Approximating the cylinder's irregularity. | 483 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
476 | if (volume1 > volume2) | ||
477 | { | ||
478 | volume = (float)volume1 - (volume1 - volume2); | ||
479 | } | ||
480 | else if (volume2 > volume1) | ||
481 | { | ||
482 | volume = (float)volume2 - (volume2 - volume1); | ||
483 | } | ||
484 | else | ||
485 | { | 484 | { |
486 | // Regular cylinder | 485 | volume *= 0.78539816339f; // elipse base |
487 | volume = volume1; | ||
488 | } | ||
489 | } | ||
490 | else | ||
491 | { | ||
492 | // We don't know what the shape is yet, so use default | ||
493 | volume = _size.X * _size.Y * _size.Z; | ||
494 | } | ||
495 | // If the user has 'hollowed out' | ||
496 | // ProfileHollow is one of those 0 to 50000 values :P | ||
497 | // we like percentages better.. so turning into a percentage | ||
498 | 486 | ||
499 | if (((float)_pbs.ProfileHollow / 50000f) > 0.0) | 487 | if (hollowAmount > 0.0) |
500 | { | 488 | { |
501 | float hollowAmount = (float)_pbs.ProfileHollow / 50000f; | 489 | switch (_pbs.HollowShape) |
490 | { | ||
491 | case HollowShape.Same: | ||
492 | case HollowShape.Circle: | ||
493 | break; | ||
502 | 494 | ||
503 | // calculate the hollow volume by it's shape compared to the prim shape | 495 | case HollowShape.Square: |
504 | float hollowVolume = 0; | 496 | hollowVolume *= 0.5f * 2.5984480504799f; |
505 | switch (_pbs.HollowShape) | 497 | break; |
498 | |||
499 | case HollowShape.Triangle: | ||
500 | hollowVolume *= .5f * 1.27323954473516f; | ||
501 | break; | ||
502 | |||
503 | default: | ||
504 | hollowVolume = 0; | ||
505 | break; | ||
506 | } | ||
507 | volume *= (1.0f - hollowVolume); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
506 | { | 512 | { |
507 | case HollowShape.Same: | 513 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); |
508 | case HollowShape.Circle: | 514 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); |
509 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | 515 | volume *= (1.0f - tmp * tmp); |
510 | // Cyllinder hollow volume calculation | 516 | |
511 | float hRadius = _size.X / 2; | 517 | if (hollowAmount > 0.0) |
512 | float hLength = _size.Z; | 518 | { |
513 | |||
514 | // pi * r2 * h | ||
515 | hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); | ||
516 | break; | ||
517 | 519 | ||
518 | case HollowShape.Square: | 520 | // calculate the hollow volume by it's shape compared to the prim shape |
519 | // Cube Hollow volume calculation | 521 | hollowVolume *= hollowAmount; |
520 | float hollowsizex = _size.X * hollowAmount; | ||
521 | float hollowsizey = _size.Y * hollowAmount; | ||
522 | float hollowsizez = _size.Z * hollowAmount; | ||
523 | hollowVolume = hollowsizex * hollowsizey * hollowsizez; | ||
524 | break; | ||
525 | 522 | ||
526 | case HollowShape.Triangle: | 523 | switch (_pbs.HollowShape) |
527 | // Equilateral Triangular Prism volume hollow calculation | 524 | { |
528 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | 525 | case HollowShape.Same: |
526 | case HollowShape.Circle: | ||
527 | break; | ||
529 | 528 | ||
530 | float aLength = _size.Y; | 529 | case HollowShape.Square: |
531 | // 1/2 abh | 530 | hollowVolume *= 0.5f * 2.5984480504799f; |
532 | hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); | 531 | break; |
533 | break; | ||
534 | 532 | ||
535 | default: | 533 | case HollowShape.Triangle: |
536 | hollowVolume = 0; | 534 | hollowVolume *= .5f * 1.27323954473516f; |
537 | break; | 535 | break; |
536 | |||
537 | default: | ||
538 | hollowVolume = 0; | ||
539 | break; | ||
540 | } | ||
541 | volume *= (1.0f - hollowVolume); | ||
542 | } | ||
538 | } | 543 | } |
539 | volume = volume - hollowVolume; | ||
540 | } | ||
541 | break; | 544 | break; |
542 | 545 | ||
543 | case ProfileShape.HalfCircle: | 546 | case ProfileShape.HalfCircle: |
544 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) | 547 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
545 | { | 548 | { |
546 | if (_size.X == _size.Y && _size.Y == _size.Z) | 549 | volume *= 0.52359877559829887307710723054658f; |
547 | { | ||
548 | // regular sphere | ||
549 | // v = 4/3 * pi * r^3 | ||
550 | float sradius3 = (float)Math.Pow((_size.X / 2), 3); | ||
551 | volume = (float)((4f / 3f) * Math.PI * sradius3); | ||
552 | } | ||
553 | else | ||
554 | { | ||
555 | // we treat this as a box currently | ||
556 | volume = _size.X * _size.Y * _size.Z; | ||
557 | } | ||
558 | } | ||
559 | else | ||
560 | { | ||
561 | // We don't know what the shape is yet, so use default | ||
562 | volume = _size.X * _size.Y * _size.Z; | ||
563 | } | 550 | } |
564 | break; | 551 | break; |
565 | 552 | ||
566 | case ProfileShape.EquilateralTriangle: | 553 | case ProfileShape.EquilateralTriangle: |
567 | /* | ||
568 | v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h | ||
569 | 554 | ||
570 | // seed mesh | 555 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
571 | Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); | 556 | { |
572 | Vertex PM = new Vertex(+0.5f, 0f, 0.0f); | 557 | volume *= 0.32475953f; |
573 | Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); | ||
574 | */ | ||
575 | float xA = -0.25f * _size.X; | ||
576 | float yA = -0.45f * _size.Y; | ||
577 | 558 | ||
578 | float xB = 0.5f * _size.X; | 559 | if (hollowAmount > 0.0) |
579 | float yB = 0; | 560 | { |
580 | 561 | ||
581 | float xC = -0.25f * _size.X; | 562 | // calculate the hollow volume by it's shape compared to the prim shape |
582 | float yC = 0.45f * _size.Y; | 563 | switch (_pbs.HollowShape) |
564 | { | ||
565 | case HollowShape.Same: | ||
566 | case HollowShape.Triangle: | ||
567 | hollowVolume *= .25f; | ||
568 | break; | ||
583 | 569 | ||
584 | volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); | 570 | case HollowShape.Square: |
571 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
572 | break; | ||
585 | 573 | ||
586 | // If the user has 'hollowed out' | 574 | case HollowShape.Circle: |
587 | // ProfileHollow is one of those 0 to 50000 values :P | 575 | // Hollow shape is a perfect cyllinder in respect to the cube's scale |
588 | // we like percentages better.. so turning into a percentage | 576 | // Cyllinder hollow volume calculation |
589 | float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); | ||
590 | if (((float)fhollowFactor / 50000f) > 0.0) | ||
591 | { | ||
592 | float hollowAmount = (float)fhollowFactor / 50000f; | ||
593 | 577 | ||
594 | // calculate the hollow volume by it's shape compared to the prim shape | 578 | hollowVolume *= 0.1963495f * 3.07920140172638f; |
595 | float hollowVolume = 0; | 579 | break; |
596 | switch (_pbs.HollowShape) | 580 | |
581 | default: | ||
582 | hollowVolume = 0; | ||
583 | break; | ||
584 | } | ||
585 | volume *= (1.0f - hollowVolume); | ||
586 | } | ||
587 | } | ||
588 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
597 | { | 589 | { |
598 | case HollowShape.Same: | 590 | volume *= 0.32475953f; |
599 | case HollowShape.Triangle: | 591 | volume *= 0.01f * (float)(200 - _pbs.PathScaleX); |
600 | // Equilateral Triangular Prism volume hollow calculation | 592 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); |
601 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | 593 | volume *= (1.0f - tmp * tmp); |
602 | |||
603 | float aLength = _size.Y; | ||
604 | // 1/2 abh | ||
605 | hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); | ||
606 | break; | ||
607 | 594 | ||
608 | case HollowShape.Square: | 595 | if (hollowAmount > 0.0) |
609 | // Cube Hollow volume calculation | 596 | { |
610 | float hollowsizex = _size.X * hollowAmount; | ||
611 | float hollowsizey = _size.Y * hollowAmount; | ||
612 | float hollowsizez = _size.Z * hollowAmount; | ||
613 | hollowVolume = hollowsizex * hollowsizey * hollowsizez; | ||
614 | break; | ||
615 | 597 | ||
616 | case HollowShape.Circle: | 598 | hollowVolume *= hollowAmount; |
617 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | ||
618 | // Cyllinder hollow volume calculation | ||
619 | float hRadius = _size.X / 2; | ||
620 | float hLength = _size.Z; | ||
621 | 599 | ||
622 | // pi * r2 * h | 600 | switch (_pbs.HollowShape) |
623 | hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); | 601 | { |
624 | break; | 602 | case HollowShape.Same: |
603 | case HollowShape.Triangle: | ||
604 | hollowVolume *= .25f; | ||
605 | break; | ||
625 | 606 | ||
626 | default: | 607 | case HollowShape.Square: |
627 | hollowVolume = 0; | 608 | hollowVolume *= 0.499849f * 3.07920140172638f; |
628 | break; | 609 | break; |
629 | } | ||
630 | volume = volume - hollowVolume; | ||
631 | } | ||
632 | break; | ||
633 | 610 | ||
634 | default: | 611 | case HollowShape.Circle: |
635 | // we don't have all of the volume formulas yet so | ||
636 | // use the common volume formula for all | ||
637 | volume = _size.X*_size.Y*_size.Z; | ||
638 | break; | ||
639 | } | ||
640 | 612 | ||
641 | // Calculate Path cut effect on volume | 613 | hollowVolume *= 0.1963495f * 3.07920140172638f; |
642 | // Not exact, in the triangle hollow example | 614 | break; |
643 | // They should never be zero or less then zero.. | ||
644 | // we'll ignore it if it's less then zero | ||
645 | 615 | ||
646 | // ProfileEnd and ProfileBegin are values | 616 | default: |
647 | // from 0 to 50000 | 617 | hollowVolume = 0; |
618 | break; | ||
619 | } | ||
620 | volume *= (1.0f - hollowVolume); | ||
621 | } | ||
622 | } | ||
623 | break; | ||
648 | 624 | ||
649 | // Turning them back into percentages so that I can cut that percentage off the volume | 625 | default: |
626 | break; | ||
627 | } | ||
650 | 628 | ||
651 | float PathCutEndAmount = _pbs.ProfileEnd; | ||
652 | float PathCutStartAmount = _pbs.ProfileBegin; | ||
653 | if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) | ||
654 | { | ||
655 | float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); | ||
656 | 629 | ||
657 | // Check the return amount for sanity | ||
658 | if (pathCutAmount >= 0.99f) | ||
659 | pathCutAmount = 0.99f; | ||
660 | 630 | ||
661 | volume = volume - (volume*pathCutAmount); | 631 | float taperX1; |
662 | } | 632 | float taperY1; |
663 | UInt16 taperX = _pbs.PathScaleX; | 633 | float taperX; |
664 | UInt16 taperY = _pbs.PathScaleY; | 634 | float taperY; |
665 | float taperFactorX = 0; | 635 | float pathBegin; |
666 | float taperFactorY = 0; | 636 | float pathEnd; |
637 | float profileBegin; | ||
638 | float profileEnd; | ||
667 | 639 | ||
668 | // Mass = density * volume | 640 | if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) |
669 | if (taperX != 100) | ||
670 | { | ||
671 | if (taperX > 100) | ||
672 | { | 641 | { |
673 | taperFactorX = 1.0f - ((float)taperX / 200); | 642 | taperX1 = _pbs.PathScaleX * 0.01f; |
674 | //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); | 643 | if (taperX1 > 1.0f) |
675 | } | 644 | taperX1 = 2.0f - taperX1; |
676 | else | 645 | taperX = 1.0f - taperX1; |
677 | { | ||
678 | taperFactorX = 1.0f - ((100 - (float)taperX) / 100); | ||
679 | //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); | ||
680 | } | ||
681 | volume = (float)volume * ((taperFactorX / 3f) + 0.001f); | ||
682 | } | ||
683 | 646 | ||
684 | if (taperY != 100) | 647 | taperY1 = _pbs.PathScaleY * 0.01f; |
685 | { | 648 | if (taperY1 > 1.0f) |
686 | if (taperY > 100) | 649 | taperY1 = 2.0f - taperY1; |
687 | { | 650 | taperY = 1.0f - taperY1; |
688 | taperFactorY = 1.0f - ((float)taperY / 200); | ||
689 | //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); | ||
690 | } | 651 | } |
691 | else | 652 | else |
692 | { | 653 | { |
693 | taperFactorY = 1.0f - ((100 - (float)taperY) / 100); | 654 | taperX = _pbs.PathTaperX * 0.01f; |
694 | //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); | 655 | if (taperX < 0.0f) |
656 | taperX = -taperX; | ||
657 | taperX1 = 1.0f - taperX; | ||
658 | |||
659 | taperY = _pbs.PathTaperY * 0.01f; | ||
660 | if (taperY < 0.0f) | ||
661 | taperY = -taperY; | ||
662 | taperY1 = 1.0f - taperY; | ||
663 | |||
695 | } | 664 | } |
696 | volume = (float)volume * ((taperFactorY / 3f) + 0.001f); | 665 | |
697 | } | 666 | |
698 | returnMass = m_density*volume; | 667 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); |
699 | if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. | 668 | |
669 | pathBegin = (float)_pbs.PathBegin * 2.0e-5f; | ||
670 | pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; | ||
671 | volume *= (pathEnd - pathBegin); | ||
672 | |||
673 | // this is crude aproximation | ||
674 | profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; | ||
675 | profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; | ||
676 | volume *= (profileEnd - profileBegin); | ||
677 | |||
678 | returnMass = m_density * volume; | ||
679 | |||
680 | if (returnMass <= 0) | ||
681 | returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. | ||
682 | // else if (returnMass > _parent_scene.maximumMassObject) | ||
683 | // returnMass = _parent_scene.maximumMassObject; | ||
684 | |||
700 | 685 | ||
701 | 686 | ||
702 | 687 | ||