253 lines
7.0 KiB
C++
253 lines
7.0 KiB
C++
#include "main.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include "sphere.h"
|
|
#include "utils.h"
|
|
#include "3dutils.h"
|
|
#include "audio.h"
|
|
#include "vector.h"
|
|
#include "collision.h"
|
|
#include "glapi.h"
|
|
|
|
Sphere::Sphere(void) {
|
|
appearance = new SphereAppearance();
|
|
Object::appearance = appearance;
|
|
geometry = new SphereShape(this);
|
|
Object::geometry = geometry;
|
|
}
|
|
|
|
void Sphere::setRadius(float r) {
|
|
if (r < 0)
|
|
r = -r;
|
|
this->r = r;
|
|
appearance->setRadius(r);
|
|
geometry->setRadius(r);
|
|
}
|
|
|
|
SphereAppearance::SphereAppearance(void) { setRadius(1); }
|
|
|
|
void SphereAppearance::setRadius(float r) {
|
|
if (r < 0)
|
|
r = -r;
|
|
this->r = r;
|
|
}
|
|
|
|
void Sphere::setColor(float red, float green, float blue) {
|
|
appearance->getMaterial()->setColor(red, green, blue, 1);
|
|
}
|
|
|
|
void SphereAppearance::draw(void) {
|
|
material.enable();
|
|
createSphere(r);
|
|
}
|
|
|
|
SphereShape::SphereShape(Object *sphere) : Shape(sphere) { setRadius(1); }
|
|
|
|
void SphereShape::setRadius(float r) { this->r = r; }
|
|
|
|
float SphereShape::getRadius(void) { return r; }
|
|
|
|
bool SphereShape::checkCollision(Object *target) {
|
|
return target->geometry->checkCollisionPeer(this);
|
|
}
|
|
|
|
float SphereShape::calculateMomentOfInertia(float *rotationvector) {
|
|
return 2.0 / 3.0 * r * r;
|
|
}
|
|
|
|
/*bool SphereShape::checkCollisionPeer(PlaneShape *target){
|
|
float sourceposition[3], targetposition[3];
|
|
object->getPosition(sourceposition);
|
|
target->object->getPosition(targetposition);
|
|
float height = target->height + targetposition[1];
|
|
|
|
if (sourceposition[1] - r < height){
|
|
//shotsound->play();
|
|
float normal[3] = {0, 1, 0};
|
|
|
|
float contactpoint[3] = {0, target->height, 0};
|
|
collide(object, target->object, normal, contactpoint);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}*/
|
|
|
|
bool SphereShape::checkCollisionPeer(SphereShape *target) {
|
|
/*float sourceposition[3], targetposition[3];
|
|
object->getPosition(sourceposition);
|
|
target->object->getPosition(targetposition);
|
|
float impact[3];
|
|
vectorSub(impact, sourceposition, targetposition);*/
|
|
float impact[3] = {0, 0, 0};
|
|
object->transformPoint(impact, impact);
|
|
target->object->unTransformPoint(impact, impact);
|
|
float distance2 = vectorDot(impact, impact);
|
|
|
|
if (distance2 < (r + target->r) * (r + target->r)) {
|
|
/*float temp[3], temp2[3], temp3[3];
|
|
object->getMomentum(temp2);
|
|
target->object->getMomentum(temp3);
|
|
vectorSub(temp, temp2, temp3);
|
|
shotsound->setVolume(1.0-1/(1+vectorLength(temp)*0.5));
|
|
shotsound->play();*/
|
|
float normal[3];
|
|
vectorNormalize(normal, impact);
|
|
|
|
float contactpoint[3];
|
|
vectorScale(contactpoint, normal, target->r);
|
|
|
|
target->object->transformVector(normal, normal);
|
|
target->object->transformPoint(contactpoint, contactpoint);
|
|
|
|
addCollision(object, target->object, normal, contactpoint);
|
|
|
|
// vectorAdd(contactnormal, normal);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool between(float x, float x1, float x2) {
|
|
if ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*bool SphereShape::checkCollisionPeer(BoxShape *target){
|
|
float sourceposition[3], targetposition[3];
|
|
object->getPosition(sourceposition);
|
|
target->object->getPosition(targetposition);
|
|
float x1 = target->x1 + targetposition[0];
|
|
float x2 = target->x2 + targetposition[0];
|
|
float y1 = target->y1 + targetposition[1];
|
|
float y2 = target->y2 + targetposition[1];
|
|
float z1 = target->z1 + targetposition[2];
|
|
float z2 = target->z2 + targetposition[2];
|
|
float points[3][2] = {{x1, x2}, {y1, y2}, {z1, z2}};
|
|
float p[2], op1[2], op2[2];
|
|
float c, oc1, oc2;
|
|
int i;
|
|
float normal[3];
|
|
float *normal2[3];
|
|
//Faces
|
|
for (i = 0; i < 3; i++){
|
|
p[0] = points[i][0];
|
|
p[1] = points[i][1];
|
|
op1[0] = points[(i+1)%3][0];
|
|
op1[1] = points[(i+1)%3][1];
|
|
op2[0] = points[(i+2)%3][0];
|
|
op2[1] = points[(i+2)%3][1];
|
|
c = sourceposition[i];
|
|
oc1 = sourceposition[(i+1)%3];
|
|
oc2 = sourceposition[(i+2)%3];
|
|
normal2[0] = &normal[i];
|
|
normal2[1] = &normal[(i+1)%3];
|
|
normal2[2] = &normal[(i+2)%3];
|
|
|
|
if (between(oc1, op1[0], op1[1]) &&
|
|
between(oc2, op2[0], op2[1])){
|
|
if (c < p[0] && c+r > p[0]){
|
|
*normal2[0] = -1;
|
|
*normal2[1] = 0;
|
|
*normal2[2] = 0;
|
|
collide(object, target->object, normal);
|
|
return true;
|
|
}
|
|
if (c > p[1] && c-r < p[1]){
|
|
*normal2[0] = 1;
|
|
*normal2[1] = 0;
|
|
*normal2[2] = 0;
|
|
collide(object, target->object, normal);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Edges
|
|
for (i = 0; i < 3; i++){
|
|
p[0] = points[i][0];
|
|
p[1] = points[i][1];
|
|
op1[0] = points[(i+1)%3][0];
|
|
op1[1] = points[(i+1)%3][1];
|
|
op2[0] = points[(i+2)%3][0];
|
|
op2[1] = points[(i+2)%3][1];
|
|
c = sourceposition[i];
|
|
oc1 = sourceposition[(i+1)%3];
|
|
oc2 = sourceposition[(i+2)%3];
|
|
normal2[0] = &normal[i];
|
|
normal2[1] = &normal[(i+1)%3];
|
|
normal2[2] = &normal[(i+2)%3];
|
|
float edges[4][2] = {
|
|
{p[0], op1[0]},
|
|
{p[1], op1[0]},
|
|
{p[0], op1[1]},
|
|
{p[1], op1[1]}};
|
|
|
|
if (between(oc2, op2[0], op2[1])){
|
|
int j;
|
|
for (j = 0; j < 4; j++){
|
|
float diff[2] = {c - edges[j][0], oc1 - edges[j][1]};
|
|
if (diff[0]*diff[0] + diff[1]*diff[1] < r*r){
|
|
*normal2[0] = diff[0];
|
|
*normal2[1] = diff[1];
|
|
*normal2[2] = 0;
|
|
vectorNormalize(normal);
|
|
collide(object, target->object, normal);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Corners
|
|
float corners[8][3] = {
|
|
{x1, y1, z1},
|
|
{x1, y1, z2},
|
|
{x1, y2, z1},
|
|
{x1, y2, z2},
|
|
{x2, y1, z1},
|
|
{x2, y1, z2},
|
|
{x2, y2, z1},
|
|
{x2, y2, z2}};
|
|
for (i = 0; i < 8; i++){
|
|
float *corner = corners[i];
|
|
float difference[3];
|
|
vectorSub(difference, sourceposition, corner);
|
|
float length2 = vectorDot(difference, difference);
|
|
if (length2 < r*r){
|
|
float normal[3];
|
|
vectorNormalize(normal, difference);
|
|
collide(object, target->object, normal);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}*/
|
|
|
|
bool SphereShape::checkCollisionPeer(MeshShape *target) {
|
|
float position[3] = {0, 0, 0};
|
|
object->transformPoint(position, position);
|
|
target->object->unTransformPoint(position, position);
|
|
Mesh *mesh = target->mesh;
|
|
|
|
float normal[3];
|
|
float contactpoint[3];
|
|
|
|
if (checkSphereMeshCollision(position, r, mesh, normal, contactpoint)) {
|
|
target->object->transformVector(normal, normal);
|
|
target->object->transformPoint(contactpoint, contactpoint);
|
|
|
|
addCollision(object, target->object, normal, contactpoint);
|
|
|
|
// vectorAdd(contactnormal, normal);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|