2019년 3월 12일 화요일

발사체 코드



namespace physics
{
typedef CELL::float3 vec3;
typedef CELL::matrix4 mat4;

class force
{
private:

vec3 forceVector;
vec3 forceLocation;

public:

force() : forceVector(vec3(0,0,0)), forceLocation(vec3(0, 0, 0)) {}

void Force(const vec3& theForce) { forceVector = theForce; }
vec3& Force() { return forceVector; }

void ApplicationPoint(const vec3& forceApplicationPoint) { forceLocation = forceApplicationPoint; }
vec3& ApplicationPoint() { return forceLocation; }
};


class CPhysicsObject
{
private:
// 월드 좌표
mat4 worldMatrix;

// 물리적 속성과 선형 운동 속성
float mass;

vec3 centerOfMassLocation;
vec3 linearVelocity;
vec3 linearAcceleration;

force constantForce; // 지속력
force impulseForce; // 충격력

public:

const mat4& WorldMatrix() { return worldMatrix;}

void Mass(float _mass) { mass = _mass; }
float Mass() { return mass; }

void Location(const vec3& locationCenterOfMass) {
centerOfMassLocation = locationCenterOfMass ;
worldMatrix.translate(centerOfMassLocation.x, centerOfMassLocation.y, centerOfMassLocation.z);}

const vec3& Location() { return centerOfMassLocation; }

void LinearVelocity(const vec3& newVelocity) { linearVelocity = newVelocity; }
const vec3& LinearVelocity() { return linearVelocity; }

void LinearAcceleration(const vec3& newAcceleration) { linearAcceleration = newAcceleration; }
const vec3& LinearAcceleration() { return linearAcceleration; }

void ConstantForce(const force& sumOfConstantForces) { constantForce = sumOfConstantForces; };
force& ConstantForce() { return constantForce; }

void ImpulseForce(const force& sumImpulseForces) { impulseForce = sumImpulseForces; };
force& ImpulseForce() { return impulseForce; }

void Update(float changeInTime)
{
force sumForces;

sumForces.Force(constantForce.Force() + impulseForce.Force());

assert(mass != 0);

// 선형 가속도를 구한다.
linearAcceleration = sumForces.Force() / mass;

// 선형 속도를 구한다.
linearVelocity += linearAcceleration * changeInTime;

// 무게 중심의 새로운 위치를 구한다.
centerOfMassLocation += linearVelocity * changeInTime;

// 평행 이동 행렬을 생성한다.
worldMatrix.translate(centerOfMassLocation.x, centerOfMassLocation.y, centerOfMassLocation.z);

// 0으로 리셋
impulseForce.Force(vec3(0, 0, 0));
impulseForce.ApplicationPoint(vec3(0, 0, 0));
}
};


class CPhysicsObjectController
{
std::vector<CPhysicsObject> list;

public:

vec3 GetRandomFireForce()
{
vec3 frontVec = vec3(.0f, .0f, 1.0f);
mat4 mat;

mat.identify();
mat.rotateX(-45);
frontVec = frontVec * mat;

mat.identify();
mat.rotateY(rand() % 180);
frontVec = frontVec * mat;

mat.identify();
mat.scale(rand() % 360);
frontVec = frontVec * mat;

return frontVec;
}

void Fire()
{
vec3 tmp = vec3(0.0f, 5.0f, 0.0f);

CPhysicsObject p;
p.Mass(1.0f);
p.Location(tmp);

force theForce;
theForce.Force(vec3(0.0f, -9.8f, 0.0f));
theForce.ApplicationPoint(tmp);
p.ConstantForce(theForce);

for (int i = 0; i < 10; i++)
{
theForce.Force(GetRandomFireForce());
theForce.ApplicationPoint(vec3(0.0f, 0.0f, 0.0f));

p.ImpulseForce(theForce);
p.LinearVelocity(tmp);
p.LinearAcceleration(tmp);

list.push_back(p);
}
}

std::vector<CPhysicsObject>& get() { return list; }

void Update(float changeInTime)
{
for (auto itr = list.begin(); itr != list.end(); ++itr)
{
itr->Update(changeInTime);
}
}
};
};