This commit is contained in:
2025-05-13 05:18:03 +03:00
parent 0790b782f2
commit 2ca246b75c
1494 changed files with 22057 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class WaterField : MonoBehaviour {
public List<GameObject> capturedObjects = new List<GameObject>();
public bool enableDrag = true;
float maxDrag = 0.0f;
float vel = 0.0f;
// Use this for initialization
void Start () {
if (collider == null) {
var c = gameObject.AddComponent<BoxCollider>();
c.center = new Vector3(0, -0.5f, 0);
c.isTrigger = true;
}
}
// Update is called once per frame
void FixedUpdate () {
float envDensity = AdvancedPhysics.Matters.Water.Density;
Plane p = new Plane(transform.up, transform.position);
foreach (var obj in capturedObjects) {
if(obj.collider is SphereCollider){
float objDensity = AdvancedPhysics.Matters.Water.Density * 1.05f;
Vector3 sphereCenter;
float sphereRadius;
SphereCollider c = obj.collider as SphereCollider;
if(c != null){
sphereCenter = c.transform.position;
sphereRadius = c.radius;
}else{
sphereCenter = obj.collider.bounds.center;
Vector3 ext = obj.collider.bounds.extents;
sphereRadius = ext.x > ext.y ? ext.x : (ext.y > ext.z ? ext.y : ext.z);
}
float underwaterVolume = SphereVolumeUnderPlane(p, sphereCenter, sphereRadius);
float forceMagnitude = AdvancedMath.BuoyantForce(underwaterVolume, objDensity, envDensity, Physics.gravity.magnitude);
Vector3 force = Physics.gravity.normalized * -forceMagnitude;
Vector3 sphereDragForce = -obj.rigidbody.velocity.normalized * AdvancedMath.SphereDrag(envDensity, obj.rigidbody.velocity.magnitude, sphereRadius);
float sphereVolume = AdvancedMath.SphereVolume(sphereRadius);
Vector3 speedForce = Vector3.zero;
if(underwaterVolume < sphereVolume){
if(underwaterVolume > 0.0f)
speedForce = Vector3.Cross(obj.rigidbody.angularVelocity, transform.up) * 30;
}else{
speedForce = Vector3.Cross(obj.rigidbody.angularVelocity, transform.up) * 10;
}
obj.rigidbody.AddForce(force + sphereDragForce + speedForce);
}if(obj.collider is BoxCollider){
float objDensity = AdvancedPhysics.Matters.Water.Density * 1.05f;
var mat = obj.GetComponent<AdvancedPhysicsMaterial>();
if(mat != null){
objDensity = mat.matter.Density;
}
var tf = obj.transform.localToWorldMatrix;
Vector3[] vertices;
int[] indices;
var mf = obj.GetComponent<MeshFilter>();
if(mf != null && mf.sharedMesh != null){
vertices = mf.mesh.vertices;
indices = mf.mesh.triangles;
int cnt = vertices.Length;
for(int i = 0; i < cnt; ++i){
vertices[i] = tf.MultiplyPoint3x4(vertices[i]);
}
}else{
AdvancedUtils.CreateMeshCube (obj.transform.localToWorldMatrix, out vertices, out indices);
}
List<Vector3> cuttedTriangles = AdvancedUtils.CutMesh (vertices, indices, p);
//AdvancedGizmo.DrawMesh(cuttedTriangles.ToArray(), true);
float totalVolume = 0;
Vector3 totalBuoyantForce = Vector3.zero;
for (int i = 0; i < cuttedTriangles.Count; i+=3) {
Vector3 v0 = cuttedTriangles[i + 0];
Vector3 v1 = cuttedTriangles[i + 1];
Vector3 v2 = cuttedTriangles[i + 2];
Vector3 normal = AdvancedMath.TriangleNormal(v0, v1, v2);
float dot = Vector3.Dot (normal, p.normal);
if(Mathf.Abs(dot) >= 0.0001f){
float sign = Mathf.Sign(dot);
float h0 = p.GetDistanceToPoint(v0);
float h1 = p.GetDistanceToPoint(v1);
float h2 = p.GetDistanceToPoint(v2);
float avgH = (h0 + h1 + h2) / 3.0f;
Vector3 vp0 = v0 - p.normal * h0;
Vector3 vp1 = v1 - p.normal * h1;
Vector3 vp2 = v2 - p.normal * h2;
float triangleSquare = AdvancedMath.TriangleSquare(vp0, vp1, vp2);
float prismVolume = AdvancedMath.PrismVolume(triangleSquare, avgH) * sign;
float prismBuoyantMagnitude = AdvancedMath.BuoyantForce(prismVolume, objDensity, envDensity, Physics.gravity.magnitude);
Vector3 prismBuoyantForce = Physics.gravity.normalized * -prismBuoyantMagnitude;
totalBuoyantForce += prismBuoyantForce;
totalVolume += prismVolume;
Vector3 com = AdvancedMath.PrismCenterOfMass(vp0, vp1, vp2, p.normal, h0, h1, h2);
obj.rigidbody.AddForceAtPosition(prismBuoyantForce, com, ForceMode.Force);
//obj.rigidbody.d
//Physics.
}
}
if(obj.name == "CubeTest"){
// Debug.Log("Total underwater volume: " + totalVolume);
//Debug.Log("Total buoyant force: " + totalBuoyantForce);
}
Vector3 ext = obj.collider.bounds.extents;
float sphereRadius = ext.x > ext.y ? ext.x : (ext.y > ext.z ? ext.y : ext.z);
float v = obj.rigidbody.velocity.magnitude;
float dragMagnitude = AdvancedMath.Drag(envDensity, v, 1.02f, Mathf.PI * sphereRadius * sphereRadius);
if(v < 0.01f){
dragMagnitude = 0.0f;
}
if( dragMagnitude > v*v*obj.rigidbody.mass){
dragMagnitude = v*v*obj.rigidbody.mass;
}
/* if(dragMagnitude > obj.rigidbody.velocity.magnitude){
dragMagnitude = obj.rigidbody.velocity.magnitude;
}*/
if(enableDrag){
Vector3 sphereDragForce = -obj.rigidbody.velocity.normalized * dragMagnitude;
obj.rigidbody.AddForce(sphereDragForce, ForceMode.Force);
Debug.DrawRay(obj.transform.position,obj.rigidbody.velocity, Color.green);
Debug.DrawRay(obj.transform.position,sphereDragForce, Color.red);
if(obj.name == "CubeTest"){
if(maxDrag < dragMagnitude){
maxDrag = dragMagnitude;
vel = v;
}
}
}
// obj.rigidbody.velocity -= (sphereDragForce / obj.rigidbody.mass) * Time.fixedDeltaTime;
AdvancedGizmo.DrawMesh(cuttedTriangles.ToArray(), true);
}
}
}
void OnGUI(){
GUI.Label (new Rect(0,0,100,100), "Max drag = " + maxDrag);
GUI.Label (new Rect(0,30,100,100), "Vel = " + vel);
}
void OnDrawGizmos(){
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube (new Vector3 (0, -0.5f, 0), Vector3.one);
Gizmos.matrix = Matrix4x4.identity;
//AdvancedGizmo.DrawGrid (transform.position, width, height);
int waveLineCount = 5;
int wavesCount = 7;
float hLineOffset = (1.0f / (float)(waveLineCount + 1));
for (int i = 0; i < waveLineCount; ++i) {
float hOffset = -hLineOffset * (float)(i + 1);
AdvancedGizmo.Plot2D (Mathf.Sin, transform.localToWorldMatrix, new Vector3(-0.5f, 0, 0.5f + hOffset), Vector3.right, Vector3.forward, 1, Mathf.PI * wavesCount, 0.05f, 40, Color.blue);
}
}
float SphereVolumeUnderPlane(Plane p, Vector3 sphereCenter, float r){
float distance = p.GetDistanceToPoint (sphereCenter);
if (distance >= r) {
return 0;
} else if (distance <= -r) {
return AdvancedMath.SphereVolume (r);
} else {
float h = Mathf.Abs(distance - r);
return AdvancedMath.SphereSegmentVolume(r, h);
}
}
void OnTriggerEnter(Collider other){
if (other.rigidbody != null && !other.rigidbody.isKinematic) {
capturedObjects.Add(other.gameObject);
}
}
void OnTriggerExit(Collider other){
if (other.rigidbody != null && !other.rigidbody.isKinematic) {
capturedObjects.Remove(other.gameObject);
}
}
}