AABBテスト用コード①
参考図書
ゲームプログラミングのためのリアルタイム衝突判定 単行本 – 2005/11/1
Christer Ericson (著), 中村 達也 (翻訳)
表示まで
main
import java.util.Collections;
import java.util.Comparator;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;
import java.util.Stack;
import java.util.Arrays;
import processing.svg.*;
import java.util.List;
import java.util.Collection;
import java.util.stream.Collectors;
import processing.opengl.*;
void setup()
{
size(500,500);
background(255);
var o1 = new Object2D();
var o2 = new Object2D();
var o3 = new Object2D();
this.Objects.add(o1);
this.Objects.add(o2);
this.Objects.add(o3);
}
void draw()
{
background(255);
noFill();
strokeWeight(1);
for(var obj : this.Objects)
{
if(obj instanceof IDrawable)
{
((IDrawable)obj).draw();
}
}
}
//全てのオブジェクト。このリストはGUI機能を持つオブジェクトを含むことがある。
List<IObject> Objects = new ArrayList<IObject>();
IObject CurrentObject = null;
class Object2D implements IObject, IDrawable
{
IBV2D BV;
List<PVector> coordinates = new ArrayList<PVector>();
Object2D()
{
makeRandom(10);
var aabb = createAABBMinMax2D(this.coordinates);
this.BV = aabb;
}
void makeRandom(int count)
{
for(int i = 0; i<count; i++)
{
var v = new PVector(random(width),random(height));
this.coordinates.add(v);
}
}
void draw()
{
drawCoords();
drawBV();
}
void drawBV()
{
IAABBMinMax2D aabbmm = (IAABBMinMax2D)this.BV;
var ltv = aabbmm.GetLTV();
var rbv = aabbmm.GetRBV();
var w = abs(rbv.x-ltv.x);
var h = abs(rbv.y-ltv.y);
rect(ltv.x,ltv.y,w,h);
}
void updateBV()
{
}
void drawCoords()
{
for(var v : this.coordinates)
{
circle(v.x,v.y,10);
}
}
}
interface IObject{}
//これらにHit()を持たせるか否か
//p77
//bounding volume
interface IBV2D {}
interface IBV3D {}
interface HasBoundingVolume2D
{
IBV2D GetBV();
}
interface HasBoundingVolume3D
{
IBV3D GetBV();
}
interface IDrawable
{
void draw();
}
interface IGUI extends IDrawable
{
//void draw();
void draw(float x, float y);
}
interface IHit2D
{
boolean Hit(float x, float y);
}
interface IHit3D
{
boolean Hitfloat x, float y, float z);
}
interface ITranslate
{
void Translate(PVector dv);
}
interface HasOrigin
{
PVector GetOrigin();
}
interface IClickable
{
void mousePressed();
void mouseReleased();
}
interface IDraggable
{
void mouseDragged();
}
AABB
コメント部分はChatGPT4(アホの時期)が提出してきたもの。
////////////////////////////////////////////////////
//axis-aligned bounding box
interface IAABBMinMax2D extends IBV2D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
//processingの場合は2Dも3DもPVectorでまかなえる
interface IAABBMinMax3D extends IBV3D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
interface IAABBWH2D extends IBV2D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
}
interface IAABBWHD3D extends IBV3D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
float GetDepth();
}
//center radius
interface IAABBCR2D extends IBV2D
{
PVector GetCV();
float GetRX();
float GetRY();
}
interface IAABBCR3D extends IBV3D
{
PVector GetCV();
float GetRX();
float GetRY();
float GetRZ();
}
class AABBMinMax2D implements IAABBMinMax2D {
PVector LTV, RBV;
AABBMinMax2D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
}
class AABBMinMax3D implements IAABBMinMax3D {
PVector LTV, RBV;
AABBMinMax3D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
}
class AABBWH2D implements IAABBWH2D {
PVector LTV;
float width, height;
AABBWH2D(PVector LTV, float width, float height) {
this.LTV = LTV;
this.width = width;
this.height = height;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
}
class AABBWHD3D implements IAABBWHD3D {
PVector LTV;
float width, height, depth;
AABBWHD3D(PVector LTV, float width, float height, float depth) {
this.LTV = LTV;
this.width = width;
this.height = height;
this.depth = depth;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
public float GetDepth() { return this.depth; }
}
class AABBCR2D implements IAABBCR2D {
PVector CV;
float rx;
float ry;
AABBCR2D(PVector CV, float rx, float ry) {
this.CV = CV;
this.rx = rx;
this.ry = ry;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
}
class AABBCR3D implements IAABBCR3D {
PVector CV;
float rx;
float ry;
float rz;
AABBCR3D(PVector CV, float rx, float ry, float rz) {
this.CV = CV;
this.rx=rx;
this.ry=ry;
this.rz=rz;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
public float GetRZ() { return this.rz; }
}
///////////////////////////////////////////////////////////////////////////
MinMaxIndex extremePointsAlongDirection(PVector dir, List<PVector> pt)
{
MinMaxIndex minmax = new MinMaxIndex(0, 0);
float minproj = Float.MAX_VALUE;
float maxproj = -Float.MAX_VALUE;
for (int i = 0; i < pt.size(); i++) {
// Project vector from origin to point onto direction vector
float proj = pt.get(i).dot(dir);
// Keep track of least distant point along direction vector
if (proj < minproj) {
minproj = proj;
minmax.setMin(i);
}
// Keep track of most distant point along direction vector
if (proj > maxproj) {
maxproj = proj;
minmax.setMax(i);
}
}
return minmax;
}
AABBMinMax2D createAABBMinMax2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBMinMax2D(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y));
//return new AABBMinMax2D(pt.get(minmaxX.getMin()), pt.get(minmaxY.getMax()));
}
AABBMinMax3D createAABBMinMax3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBMinMax3D(new PVector(minx.x,miny.y,minz.z), new PVector(maxx.x,maxy.y,maxz.z));
//return new AABBMinMax3D(pt.get(minmaxX.getMin()), pt.get(minmaxZ.getMax()));
}
AABBWH2D createAABBWH2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBWH2D(new PVector(minx.x,miny.y), abs(maxx.x - minx.x), abs(maxy.y - miny.y));
//return new AABBWH2D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()));
}
AABBWHD3D createAABBWHD3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBWHD3D(new PVector(minx.x, miny.y, minz.z), abs(maxx.x - minx.x), abs(maxy.y - miny.y), abs(maxz.z - minz.z));
//return new AABBWHD3D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()), abs(minmaxZ.getMax() - minmaxZ.getMin()));
}
AABBCR2D createAABBCR2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
PVector center = PVector.add(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
return new AABBCR2D(center, radiusX, radiusY);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//return new AABBCR2D(center, radiusX, radiusY);
}
AABBCR3D createAABBCR3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
PVector center = PVector.add(new PVector(minx.x, miny.y, minz.z), new PVector(maxx.x, maxy.y, maxz.z)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
float radiusZ = abs(maxz.z - minz.z) * 0.5f;
return new AABBCR3D(center, radiusX, radiusY, radiusZ);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//float radiusZ = abs(minmaxZ.getMax() - minmaxZ.getMin()) * 0.5f;
//return new AABBCR3D(center, radiusX, radiusY, radiusZ);
}
Util
戻り値まとめ用クラス
class MinMaxIndex {
private int min;
private int max;
// Constructor
MinMaxIndex(int min, int max) {
this.min = min;
this.max = max;
}
// Accessors
int getMin() { return min; }
void setMin(int min) { this.min = min; }
int getMax() { return max; }
void setMax(int max) { this.max = max; }
}
Hit & Draggまで
main
import java.util.Collections;
import java.util.Comparator;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;
import java.util.Stack;
import java.util.Arrays;
import processing.svg.*;
import java.util.List;
import java.util.Collection;
import java.util.stream.Collectors;
import processing.opengl.*;
void setup()
{
size(500,500);
background(255);
var o1 = new Object2D();
var o2 = new Object2D();
var o3 = new Object2D();
this.Objects.add(o1);
this.Objects.add(o2);
this.Objects.add(o3);
}
void draw()
{
background(255);
noFill();
strokeWeight(1);
for(var obj : this.Objects)
{
if(obj instanceof IUpdatable)
{
((IUpdatable)obj).update();
}
if(obj instanceof IDrawable)
{
((IDrawable)obj).draw();
}
}
}
//全てのオブジェクト。このリストはGUI機能を持つオブジェクトを含むことがある。
List<IObject> Objects = new ArrayList<IObject>();
IObject CurrentObject = null;
class Object2D implements IObject, HasBoundingVolume2D, IUpdatable, IDrawable
{
IBV2D BV;
IBV2D GetBV()
{
return this.BV;
}
List<PVector> coordinates = new ArrayList<PVector>();
Object2D()
{
makeRandom(10);
var aabb = createAABBMinMax2D(this.coordinates);
this.BV = aabb;
}
void makeRandom(int count)
{
for(int i = 0; i<count; i++)
{
var v = new PVector(random(width),random(height));
this.coordinates.add(v);
}
}
void draw()
{
drawCoords();
drawBV();
}
void update()
{
//updateBV();
//完全再計算
this.BV = createAABBMinMax2D(this.coordinates);
}
void drawBV()
{
IAABBMinMax2D aabbmm = (IAABBMinMax2D)this.BV;
var ltv = aabbmm.GetLTV();
var rbv = aabbmm.GetRBV();
var w = abs(rbv.x-ltv.x);
var h = abs(rbv.y-ltv.y);
rect(ltv.x,ltv.y,w,h);
}
void updateBV()
{
}
void drawCoords()
{
for(var v : this.coordinates)
{
circle(v.x,v.y,5);
}
}
}
PVector pprev;
PVector prev;
PVector current;
PVector dv = new PVector(0,0);
void mousePressed()
{
pprev = new PVector(mouseX,mouseY);
prev = new PVector(mouseX,mouseY);
current = new PVector(mouseX,mouseY);
for(int i = 0; i<this.Objects.size(); i++)
{
IObject obj = this.Objects.get(i);
if(obj instanceof HasBoundingVolume2D)
{
var volume = ((HasBoundingVolume2D)obj).GetBV();
if(volume.Hit(mouseX,mouseY))
{
CurrentObject = obj;
}
}
}
}
//ボタンが押されていない時
void mouseMoved(){
}
//ボタンが押されている時
void mouseDragged(){
if(pprev==null){return;}
pprev = prev.copy();
if(prev==null){return;}
prev = current.copy();
current.x = mouseX;
current.y = mouseY;
dv = PVector.sub(current,prev);
if(CurrentObject!=null && CurrentObject instanceof Object2D)
{
for(var v : ((Object2D)CurrentObject).coordinates)
{
v.add(dv);
}
}
}
void mouseReleased()
{
pprev = null;
prev = null;
current = null;
CurrentObject=null;
}
interface IObject{}
//これらにHit()を持たせるか否か
//p77
//bounding volume
interface IBV2D extends IHit2D{}
interface IBV3D extends IHit3D{}
interface HasBoundingVolume2D
{
IBV2D GetBV();
}
interface HasBoundingVolume3D
{
IBV3D GetBV();
}
interface IUpdatable
{
void update();
}
interface IDrawable
{
void draw();
}
interface IGUI extends IDrawable
{
//void draw();
void draw(float x, float y);
}
interface IHit2D
{
boolean Hit(float x, float y);
}
interface IHit3D
{
boolean Hit(float x, float y, float z);
}
interface ITranslate
{
void Translate(PVector dv);
}
interface HasOrigin
{
PVector GetOrigin();
}
interface IClickable
{
void mousePressed();
void mouseReleased();
}
interface IDraggable
{
void mouseDragged();
}
AABB
////////////////////////////////////////////////////
//axis-aligned bounding box
interface IAABBMinMax2D extends IBV2D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
//processingの場合は2Dも3DもPVectorでまかなえる
interface IAABBMinMax3D extends IBV3D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
interface IAABBWH2D extends IBV2D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
}
interface IAABBWHD3D extends IBV3D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
float GetDepth();
}
//center radius
interface IAABBCR2D extends IBV2D
{
PVector GetCV();
float GetRX();
float GetRY();
}
interface IAABBCR3D extends IBV3D
{
PVector GetCV();
float GetRX();
float GetRY();
float GetRZ();
}
class AABBMinMax2D implements IAABBMinMax2D {
PVector LTV, RBV;
AABBMinMax2D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBMinMax3D implements IAABBMinMax3D {
PVector LTV, RBV;
AABBMinMax3D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
class AABBWH2D implements IAABBWH2D {
PVector LTV;
float width, height;
AABBWH2D(PVector LTV, float width, float height) {
this.LTV = LTV;
this.width = width;
this.height = height;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBWHD3D implements IAABBWHD3D {
PVector LTV;
float width, height, depth;
AABBWHD3D(PVector LTV, float width, float height, float depth) {
this.LTV = LTV;
this.width = width;
this.height = height;
this.depth = depth;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
public float GetDepth() { return this.depth; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
class AABBCR2D implements IAABBCR2D {
PVector CV;
float rx;
float ry;
AABBCR2D(PVector CV, float rx, float ry) {
this.CV = CV;
this.rx = rx;
this.ry = ry;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBCR3D implements IAABBCR3D {
PVector CV;
float rx;
float ry;
float rz;
AABBCR3D(PVector CV, float rx, float ry, float rz) {
this.CV = CV;
this.rx=rx;
this.ry=ry;
this.rz=rz;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
public float GetRZ() { return this.rz; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
///////////////////////////////////////////////////////////////////////////
MinMaxIndex extremePointsAlongDirection(PVector dir, List<PVector> pt)
{
MinMaxIndex minmax = new MinMaxIndex(0, 0);
float minproj = Float.MAX_VALUE;
float maxproj = -Float.MAX_VALUE;
for (int i = 0; i < pt.size(); i++) {
// Project vector from origin to point onto direction vector
float proj = pt.get(i).dot(dir);
// Keep track of least distant point along direction vector
if (proj < minproj) {
minproj = proj;
minmax.setMin(i);
}
// Keep track of most distant point along direction vector
if (proj > maxproj) {
maxproj = proj;
minmax.setMax(i);
}
}
return minmax;
}
AABBMinMax2D createAABBMinMax2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBMinMax2D(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y));
//return new AABBMinMax2D(pt.get(minmaxX.getMin()), pt.get(minmaxY.getMax()));
}
AABBMinMax3D createAABBMinMax3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBMinMax3D(new PVector(minx.x,miny.y,minz.z), new PVector(maxx.x,maxy.y,maxz.z));
//return new AABBMinMax3D(pt.get(minmaxX.getMin()), pt.get(minmaxZ.getMax()));
}
AABBWH2D createAABBWH2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBWH2D(new PVector(minx.x,miny.y), abs(maxx.x - minx.x), abs(maxy.y - miny.y));
//return new AABBWH2D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()));
}
AABBWHD3D createAABBWHD3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBWHD3D(new PVector(minx.x, miny.y, minz.z), abs(maxx.x - minx.x), abs(maxy.y - miny.y), abs(maxz.z - minz.z));
//return new AABBWHD3D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()), abs(minmaxZ.getMax() - minmaxZ.getMin()));
}
AABBCR2D createAABBCR2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
PVector center = PVector.add(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
return new AABBCR2D(center, radiusX, radiusY);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//return new AABBCR2D(center, radiusX, radiusY);
}
AABBCR3D createAABBCR3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
PVector center = PVector.add(new PVector(minx.x, miny.y, minz.z), new PVector(maxx.x, maxy.y, maxz.z)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
float radiusZ = abs(maxz.z - minz.z) * 0.5f;
return new AABBCR3D(center, radiusX, radiusY, radiusZ);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//float radiusZ = abs(minmaxZ.getMax() - minmaxZ.getMin()) * 0.5f;
//return new AABBCR3D(center, radiusX, radiusY, radiusZ);
}
Hit
// For AABB defined with min-max vectors
boolean checkHit(IAABBMinMax2D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = aabb.GetRBV();
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y;
}
boolean checkHit(IAABBMinMax3D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = aabb.GetRBV();
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z && point.z <= max.z;
}
// For AABB defined with a vector and dimensions
boolean checkHit(IAABBWH2D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = PVector.add(min, new PVector(aabb.GetWidth(), aabb.GetHeight()));
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y;
}
boolean checkHit(IAABBWHD3D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = PVector.add(min, new PVector(aabb.GetWidth(), aabb.GetHeight(), aabb.GetDepth()));
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z && point.z <= max.z;
}
// For AABB defined with center and radius
boolean checkHit(IAABBCR2D aabb, PVector point) {
PVector center = aabb.GetCV();
float rx = aabb.GetRX();
float ry = aabb.GetRY();
return point.x >= center.x - rx && point.x <= center.x + rx && point.y >= center.y - ry && point.y <= center.y + ry;
}
boolean checkHit(IAABBCR3D aabb, PVector point) {
PVector center = aabb.GetCV();
float rx = aabb.GetRX();
float ry = aabb.GetRY();
float rz = aabb.GetRZ();
return point.x >= center.x - rx && point.x <= center.x + rx && point.y >= center.y - ry && point.y <= center.y + ry && point.z >= center.z - rz && point.z <= center.z + rz;
}
Util
class MinMaxIndex {
private int min;
private int max;
// Constructor
MinMaxIndex(int min, int max) {
this.min = min;
this.max = max;
}
// Accessors
int getMin() { return min; }
void setMin(int min) { this.min = min; }
int getMax() { return max; }
void setMax(int max) { this.max = max; }
}
Sphere追加
GenerateBoundingVolumeを関数型インターフェースへ。
DrawBoundingVolume系は極めて雑。
main
import java.util.Collections;
import java.util.Comparator;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;
import java.util.Stack;
import java.util.Arrays;
import processing.svg.*;
import java.util.List;
import java.util.Collection;
import java.util.stream.Collectors;
import processing.opengl.*;
void setup()
{
size(500,500);
background(255);
var o1 = new Object2D();
var o2 = new Object2D();
var o3 = new Object2D();
this.Objects.add(o1);
this.Objects.add(o2);
this.Objects.add(o3);
}
void draw()
{
background(255);
noFill();
strokeWeight(1);
for(var obj : this.Objects)
{
if(obj instanceof IUpdatable)
{
((IUpdatable)obj).update();
}
if(obj instanceof IDrawable)
{
((IDrawable)obj).draw();
}
}
}
//全てのオブジェクト。このリストはGUI機能を持つオブジェクトを含むことがある。
List<IObject> Objects = new ArrayList<IObject>();
IObject CurrentObject = null;
public interface GenerateBV2DMethod {
IBV2D exe(List<PVector> coords);
//AABBMinMax2D exe(List<PVector> coords);
}
class Object2D implements IObject, HasBoundingVolume2D, IUpdatable, IDrawable
{
IBV2D BV;
IBV2D GetBV()
{
return this.BV;
}
List<PVector> coordinates = new ArrayList<PVector>();
GenerateBV2DMethod GenBVMethod;
void GenBV()
{
var aabb = this.GenBVMethod.exe(this.coordinates);
this.BV = aabb;
}
Object2D()
{
this.coordinates = makeRandomCoords(10, 100);
//this.GenBVMethod = (List<PVector> coords) -> createAABBMinMax2D(coords);
this.GenBVMethod = (List<PVector> coords) -> createBVCircleLoose(coords.get(0),coords);
this.GenBV();
}
void draw()
{
drawCoords();
drawBV();
}
void update()
{
//updateBV();
//完全再計算
//this.BV = createAABBMinMax2D(this.coordinates);
this.GenBV();
}
void drawBV()
{
if(this.BV instanceof IAABBMinMax2D)
{
IAABBMinMax2D aabbmm = (IAABBMinMax2D)this.BV;
drawAABBMinMax2D(aabbmm);
}
else if(this.BV instanceof IBVCircle2D)
{
IBVCircle2D bvc = (IBVCircle2D)this.BV;
drawBVCircle2D(bvc);
}
}
void updateBV()
{
}
void drawCoords()
{
for(var v : this.coordinates)
{
circle(v.x,v.y,5);
}
}
}
PVector pprev;
PVector prev;
PVector current;
PVector dv = new PVector(0,0);
void mousePressed()
{
pprev = new PVector(mouseX,mouseY);
prev = new PVector(mouseX,mouseY);
current = new PVector(mouseX,mouseY);
for(int i = 0; i<this.Objects.size(); i++)
{
IObject obj = this.Objects.get(i);
if(obj instanceof HasBoundingVolume2D)
{
var volume = ((HasBoundingVolume2D)obj).GetBV();
if(volume.Hit(mouseX,mouseY))
{
CurrentObject = obj;
}
}
}
}
//ボタンが押されていない時
void mouseMoved(){
}
//ボタンが押されている時
void mouseDragged(){
if(pprev==null){return;}
pprev = prev.copy();
if(prev==null){return;}
prev = current.copy();
current.x = mouseX;
current.y = mouseY;
dv = PVector.sub(current,prev);
if(CurrentObject!=null && CurrentObject instanceof Object2D)
{
for(var v : ((Object2D)CurrentObject).coordinates)
{
v.add(dv);
}
}
}
void mouseReleased()
{
pprev = null;
prev = null;
current = null;
CurrentObject=null;
}
interface IObject{}
//これらにHit()を持たせるか否か
//p77
//bounding volume
interface IBV2D extends IHit2D{}
interface IBV3D extends IHit3D{}
interface HasBoundingVolume2D
{
IBV2D GetBV();
}
interface HasBoundingVolume3D
{
IBV3D GetBV();
}
interface IUpdatable
{
void update();
}
interface IDrawable
{
void draw();
}
interface IGUI extends IDrawable
{
//void draw();
void draw(float x, float y);
}
interface IHit2D
{
boolean Hit(float x, float y);
}
interface IHit3D
{
boolean Hit(float x, float y, float z);
}
interface ITranslate
{
void Translate(PVector dv);
}
interface HasOrigin
{
PVector GetOrigin();
}
interface IClickable
{
void mousePressed();
void mouseReleased();
}
interface IDraggable
{
void mouseDragged();
}
AABB
////////////////////////////////////////////////////
//axis-aligned bounding box
interface IAABBMinMax2D extends IBV2D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
//processingの場合は2Dも3DもPVectorでまかなえる
interface IAABBMinMax3D extends IBV3D
{
PVector GetLTV();//left top vector
PVector GetRBV();//right bottom vector
}
interface IAABBWH2D extends IBV2D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
}
interface IAABBWHD3D extends IBV3D
{
PVector GetLTV();
float GetWidth();
float GetHeight();
float GetDepth();
}
//center radius
interface IAABBCR2D extends IBV2D
{
PVector GetCV();
float GetRX();
float GetRY();
}
interface IAABBCR3D extends IBV3D
{
PVector GetCV();
float GetRX();
float GetRY();
float GetRZ();
}
class AABBMinMax2D implements IAABBMinMax2D {
PVector LTV, RBV;
AABBMinMax2D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBMinMax3D implements IAABBMinMax3D {
PVector LTV, RBV;
AABBMinMax3D(PVector LTV, PVector RBV) {
this.LTV = LTV;
this.RBV = RBV;
}
public PVector GetLTV() { return this.LTV; }
public PVector GetRBV() { return this.RBV; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
class AABBWH2D implements IAABBWH2D {
PVector LTV;
float width, height;
AABBWH2D(PVector LTV, float width, float height) {
this.LTV = LTV;
this.width = width;
this.height = height;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBWHD3D implements IAABBWHD3D {
PVector LTV;
float width, height, depth;
AABBWHD3D(PVector LTV, float width, float height, float depth) {
this.LTV = LTV;
this.width = width;
this.height = height;
this.depth = depth;
}
public PVector GetLTV() { return this.LTV; }
public float GetWidth() { return this.width; }
public float GetHeight() { return this.height; }
public float GetDepth() { return this.depth; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
class AABBCR2D implements IAABBCR2D {
PVector CV;
float rx;
float ry;
AABBCR2D(PVector CV, float rx, float ry) {
this.CV = CV;
this.rx = rx;
this.ry = ry;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
boolean Hit(float x, float y) {
return checkHit(this, new PVector(x,y)); }
}
class AABBCR3D implements IAABBCR3D {
PVector CV;
float rx;
float ry;
float rz;
AABBCR3D(PVector CV, float rx, float ry, float rz) {
this.CV = CV;
this.rx=rx;
this.ry=ry;
this.rz=rz;
}
public PVector GetCV() { return this.CV; }
public float GetRX() { return this.rx; }
public float GetRY() { return this.ry; }
public float GetRZ() { return this.rz; }
boolean Hit(float x, float y, float z) {
return checkHit(this, new PVector(x,y,z)); }
}
///////////////////////////////////////////////////////////////////////////
MinMaxIndex extremePointsAlongDirection(PVector dir, List<PVector> pt)
{
MinMaxIndex minmax = new MinMaxIndex(0, 0);
float minproj = Float.MAX_VALUE;
float maxproj = -Float.MAX_VALUE;
for (int i = 0; i < pt.size(); i++) {
// Project vector from origin to point onto direction vector
float proj = pt.get(i).dot(dir);
// Keep track of least distant point along direction vector
if (proj < minproj) {
minproj = proj;
minmax.setMin(i);
}
// Keep track of most distant point along direction vector
if (proj > maxproj) {
maxproj = proj;
minmax.setMax(i);
}
}
return minmax;
}
AABBMinMax2D createAABBMinMax2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBMinMax2D(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y));
//return new AABBMinMax2D(pt.get(minmaxX.getMin()), pt.get(minmaxY.getMax()));
}
void drawAABBMinMax2D(IAABBMinMax2D aabbmm)
{
var ltv = aabbmm.GetLTV();
var rbv = aabbmm.GetRBV();
var w = abs(rbv.x-ltv.x);
var h = abs(rbv.y-ltv.y);
rect(ltv.x,ltv.y,w,h);
}
AABBMinMax3D createAABBMinMax3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBMinMax3D(new PVector(minx.x,miny.y,minz.z), new PVector(maxx.x,maxy.y,maxz.z));
//return new AABBMinMax3D(pt.get(minmaxX.getMin()), pt.get(minmaxZ.getMax()));
}
AABBWH2D createAABBWH2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
return new AABBWH2D(new PVector(minx.x,miny.y), abs(maxx.x - minx.x), abs(maxy.y - miny.y));
//return new AABBWH2D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()));
}
AABBWHD3D createAABBWHD3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
return new AABBWHD3D(new PVector(minx.x, miny.y, minz.z), abs(maxx.x - minx.x), abs(maxy.y - miny.y), abs(maxz.z - minz.z));
//return new AABBWHD3D(pt.get(minmaxX.getMin()), abs(minmaxX.getMax() - minmaxX.getMin()), abs(minmaxY.getMax() - minmaxY.getMin()), abs(minmaxZ.getMax() - minmaxZ.getMin()));
}
AABBCR2D createAABBCR2D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
PVector center = PVector.add(new PVector(minx.x,miny.y), new PVector(maxx.x,maxy.y)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
return new AABBCR2D(center, radiusX, radiusY);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//return new AABBCR2D(center, radiusX, radiusY);
}
AABBCR3D createAABBCR3D(List<PVector> pt) {
MinMaxIndex minmaxX = extremePointsAlongDirection(new PVector(1, 0, 0), pt);
MinMaxIndex minmaxY = extremePointsAlongDirection(new PVector(0, 1, 0), pt);
MinMaxIndex minmaxZ = extremePointsAlongDirection(new PVector(0, 0, 1), pt);
var minx = pt.get(minmaxX.getMin());
var maxx = pt.get(minmaxX.getMax());
var miny = pt.get(minmaxY.getMin());
var maxy = pt.get(minmaxY.getMax());
var minz = pt.get(minmaxZ.getMin());
var maxz = pt.get(minmaxZ.getMax());
PVector center = PVector.add(new PVector(minx.x, miny.y, minz.z), new PVector(maxx.x, maxy.y, maxz.z)).mult(0.5f);
float radiusX = abs(maxx.x - minx.x) * 0.5f;
float radiusY = abs(maxy.y - miny.y) * 0.5f;
float radiusZ = abs(maxz.z - minz.z) * 0.5f;
return new AABBCR3D(center, radiusX, radiusY, radiusZ);
//PVector center = PVector.add(pt.get(minmaxX.getMin()), pt.get(minmaxX.getMax())).mult(0.5f);
//float radiusX = abs(minmaxX.getMax() - minmaxX.getMin()) * 0.5f;
//float radiusY = abs(minmaxY.getMax() - minmaxY.getMin()) * 0.5f;
//float radiusZ = abs(minmaxZ.getMax() - minmaxZ.getMin()) * 0.5f;
//return new AABBCR3D(center, radiusX, radiusY, radiusZ);
}
Sphere
//////////////////////////////////////////////////////////////////////////////
interface IBVCircle2D extends IBV2D
{
PVector GetCV();
void SetCV(PVector cv);
float GetRadius();
void SetRadius(float value);
}
interface IBVSphere3D extends IBV3D
{
PVector GetCV();
void SetCV(PVector cv);
float GetRadius();
void SetRadius(float value);
}
/////////////////////////////////////////////
class BVCircle2D implements IBVCircle2D {
private PVector center;
private float radius;
BVCircle2D(PVector center, float radius) {
this.center = center;
this.radius = radius;
}
public PVector GetCV() {return this.center;}
public void SetCV(PVector cv){this.center.set(cv);}
public float GetRadius() {return this.radius;}
public void SetRadius(float value) {this.radius=value;}
boolean Hit(float x, float y)
{
return checkHit(this, new PVector(x,y));
}
}
class BVSphere3D implements IBVSphere3D {
private PVector center;
private float radius;
BVSphere3D(){}
BVSphere3D(PVector center, float radius) {
this.center = center;
this.radius = radius;
}
public PVector GetCV() {
return this.center;
}
public void SetCV(PVector cv){
this.center.set(cv);
}
public float GetRadius() {
return this.radius;
}
public void SetRadius(float value) {
this.radius=value;
}
boolean Hit(float x, float y, float z)
{
return checkHit(this, new PVector(x,y,z));
}
}
////////////////////////////////////////////
//基準点から最も遠い点までの距離を計算する
float CalcuFarthestDistance(PVector origin, List<PVector> pt)
{
float farthest = 0;
for(var p : pt)
{
var length = PVector.sub(p,origin).mag();
if(farthest<=length)
{
farthest=length;
}
}
return farthest;
}
//オブジェクトが回転したとしても収まるような大きめの円、球をBVとして作成
BVCircle2D createBVCircleLoose(PVector origin, List<PVector> pt) {
var radius = CalcuFarthestDistance(origin, pt);
return new BVCircle2D(origin, radius);
}
void drawBVCircle2D(IBVCircle2D bvc)
{
ellipseMode(RADIUS);
circle(bvc.GetCV().x, bvc.GetCV().y, bvc.GetRadius());
}
BVSphere3D createBVSphereLoose(PVector origin, List<PVector> pt) {
var radius = CalcuFarthestDistance(origin, pt);
return new BVSphere3D(origin, radius);
}
Hit
boolean checkHit(IBVCircle2D circle, PVector point) {
// Get the circle's center vector and radius
PVector cv = circle.GetCV();
float radius = circle.GetRadius();
// Compute the distance from the point to the center
float dist = PVector.dist(point, cv);
// If the distance is less than or equal to the radius, the point is inside the circle
return dist <= radius;
}
boolean checkHit(IBVSphere3D sphere, PVector point) {
// Get the sphere's center vector and radius
PVector cv = sphere.GetCV();
float radius = sphere.GetRadius();
// Compute the distance from the point to the center
float dist = PVector.dist(point, cv);
// If the distance is less than or equal to the radius, the point is inside the sphere
return dist <= radius;
}
boolean TestSphereSphere(IBVSphere3D a, IBVSphere3D b) {
// Calculate squared distance between centers
PVector d = PVector.sub(a.GetCV(), b.GetCV());
float dist2 = d.magSq(); // Get the magnitude squared of vector d
// Spheres intersect if squared distance is less than squared sum of radii
float radiusSum = a.GetRadius() + b.GetRadius();
return dist2 <= radiusSum * radiusSum;
}
// For AABB defined with min-max vectors
boolean checkHit(IAABBMinMax2D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = aabb.GetRBV();
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y;
}
boolean checkHit(IAABBMinMax3D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = aabb.GetRBV();
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z && point.z <= max.z;
}
// For AABB defined with a vector and dimensions
boolean checkHit(IAABBWH2D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = PVector.add(min, new PVector(aabb.GetWidth(), aabb.GetHeight()));
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y;
}
boolean checkHit(IAABBWHD3D aabb, PVector point) {
PVector min = aabb.GetLTV();
PVector max = PVector.add(min, new PVector(aabb.GetWidth(), aabb.GetHeight(), aabb.GetDepth()));
return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z && point.z <= max.z;
}
// For AABB defined with center and radius
boolean checkHit(IAABBCR2D aabb, PVector point) {
PVector center = aabb.GetCV();
float rx = aabb.GetRX();
float ry = aabb.GetRY();
return point.x >= center.x - rx && point.x <= center.x + rx && point.y >= center.y - ry && point.y <= center.y + ry;
}
boolean checkHit(IAABBCR3D aabb, PVector point) {
PVector center = aabb.GetCV();
float rx = aabb.GetRX();
float ry = aabb.GetRY();
float rz = aabb.GetRZ();
return point.x >= center.x - rx && point.x <= center.x + rx && point.y >= center.y - ry && point.y <= center.y + ry && point.z >= center.z - rz && point.z <= center.z + rz;
}
boolean TestAABBAABB(IAABBMinMax2D a, IAABBMinMax2D b) {
// Exit with no intersection if separated along an axis
if (a.GetRBV().x < b.GetLTV().x || a.GetLTV().x > b.GetRBV().x) return false;
if (a.GetRBV().y < b.GetLTV().y || a.GetLTV().y > b.GetRBV().y) return false;
// Overlapping on all axes means AABBs are intersecting
return true;
}
boolean TestAABBAABB(IAABBMinMax3D a, IAABBMinMax3D b) {
// Exit with no intersection if separated along an axis
if (a.GetRBV().x < b.GetLTV().x || a.GetLTV().x > b.GetRBV().x) return false;
if (a.GetRBV().y < b.GetLTV().y || a.GetLTV().y > b.GetRBV().y) return false;
if (a.GetRBV().z < b.GetLTV().z || a.GetLTV().z > b.GetRBV().z) return false;
// Overlapping on all axes means AABBs are intersecting
return true;
}
boolean TestAABBAABB(IAABBWH2D a, IAABBWH2D b) {
float t;
// x axis
if ((t = a.GetLTV().x - b.GetLTV().x) > b.GetWidth() || -t > a.GetWidth())
return false;
// y axis
if ((t = a.GetLTV().y - b.GetLTV().y) > b.GetHeight() || -t > a.GetHeight())
return false;
// if not separated along any axis, AABBs are intersecting
return true;
}
boolean TestAABBAABB(IAABBWHD3D a, IAABBWHD3D b) {
float t;
// x axis
if ((t = a.GetLTV().x - b.GetLTV().x) > b.GetWidth() || -t > a.GetWidth())
return false;
// y axis
if ((t = a.GetLTV().y - b.GetLTV().y) > b.GetHeight() || -t > a.GetHeight())
return false;
// z axis
if ((t = a.GetLTV().z - b.GetLTV().z) > b.GetDepth() || -t > a.GetDepth())
return false;
// if not separated along any axis, AABBs are intersecting
return true;
}
boolean TestAABBAABB(IAABBCR2D a, IAABBCR2D b) {
// Compare the distance between centers with the sum of radii
if (abs(a.GetCV().x - b.GetCV().x) > (a.GetRX() + b.GetRX())) return false;
if (abs(a.GetCV().y - b.GetCV().y) > (a.GetRY() + b.GetRY())) return false;
// if not separated along any axis, AABBs are intersecting
return true;
}
boolean TestAABBAABB(IAABBCR3D a, IAABBCR3D b) {
// Compare the distance between centers with the sum of radii
if (abs(a.GetCV().x - b.GetCV().x) > (a.GetRX() + b.GetRX())) return false;
if (abs(a.GetCV().y - b.GetCV().y) > (a.GetRY() + b.GetRY())) return false;
if (abs(a.GetCV().z - b.GetCV().z) > (a.GetRZ() + b.GetRZ())) return false;
// if not separated along any axis, AABBs are intersecting
return true;
}
Util
class MinMaxIndex {
private int min;
private int max;
// Constructor
MinMaxIndex(int min, int max) {
this.min = min;
this.max = max;
}
// Accessors
int getMin() { return min; }
void setMin(int min) { this.min = min; }
int getMax() { return max; }
void setMax(int max) { this.max = max; }
}
List<PVector> makeRandomCoords(int count)
{
var coords = new ArrayList<PVector>();
for(int i = 0; i<count; i++)
{
var v = new PVector(random(width),random(height));
coords.add(v);
}
return coords;
}
List<PVector> makeRandomCoords(int count, float r)
{
var coords = new ArrayList<PVector>();
var cv = new PVector(random(width),random(height));
for(int i = 0; i<count; i++)
{
var v = new PVector(cv.x+random(-r,r),cv.y+random(-r,r));
coords.add(v);
}
return coords;
}
Hit Test
以下は現在選択中のBoundingBoxが、ほかのBoundingBoxに接触した時OKと表示する。
現在のコードではBoundingBoxのクリック時にCurrentObjectを設定し、Release時にCurrentObject=nullしているため、クリックおよびドラッグ時にしか判定しない。
void draw()
{
background(255);
noFill();
strokeWeight(1);
for(var obj : this.Objects)
{
if(obj instanceof IUpdatable)
{
((IUpdatable)obj).update();
}
if(obj instanceof IDrawable)
{
((IDrawable)obj).draw();
}
}
for(var obj : this.Objects)
{
if(this.CurrentObject!=null && obj!=this.CurrentObject)
{
var bv = ((Object2D)obj).GetBV();
var cbv = ((Object2D)this.CurrentObject).GetBV();
if(bv instanceof IAABBMinMax2D && cbv instanceof IAABBMinMax2D)
{
if(TestAABBAABB((IAABBMinMax2D)bv, (IAABBMinMax2D)cbv))
{
fill(0);
text("OK",0,0,20,20);
}
}
}
}
}
この記事が気に入ったらサポートをしてみませんか?