package ddddbb.game;
import java.util.List;
import java.util.Vector;
import javax.sound.sampled.Clip;
import ddddbb.comb.Cell;
import ddddbb.comb.CellComplex;
import ddddbb.comb.DCell;
import ddddbb.comb.DOp;
import ddddbb.gen.AChangeListener;
import ddddbb.gen.BoolModel;
import ddddbb.gen.Model;
import ddddbb.gen.MyChangeListener;
import ddddbb.gen.SelectedListModel;
import ddddbb.math.Camera3d;
import ddddbb.math.Camera4d;
import ddddbb.math.D3Graphics;
import ddddbb.math.Point3d;
import ddddbb.math.Point4d;
import ddddbb.math.Camera4d.ProjectionException;
import ddddbb.sound.SoundEnum;
public class Scene4d extends Model implements MyChangeListener {
public final SelectedListModel<Compound> compounds = new SelectedListModel<Compound>();
protected List<DCell> faces3d;
public final Camera3d camera3d;
public Camera4d camera4d;
private boolean showInternalFaces;
private Settings.Occlusion4dAllowance occlusion4dAllowance;
private int occlusion4dAllowanceInt;
public final BoolModel viewAbsRel = new BoolModel(true,"Cam coords");;
protected final Settings ss;
public Scene4d( final Settings ss) {
this.ss = ss;
camera3d = new Camera3d(ss.screenEyeDist,ss.eyesDistHalf,ss.barEyeFocusDelta);
new AChangeListener() {
public void stateChanged() {
Camera4d prev = camera4d;
camera4d = ss.perspective.sel();
if (camera4d==prev) return;
assert camera4d.changeListeners.isEmpty() : camera4d + ":" + camera4d.changeListeners;
//following lines do not cause propagation of changes
camera4d.setOrientation(ss.orientation4d.sel().value);
camera4d.setZoom(ss.zoom.getDouble());
if (prev!=null) {
//move ChangeListeners to new camera4d
Vector<MyChangeListener> listeners = prev.changeListeners;
prev.changeListeners = camera4d.changeListeners;
camera4d.changeListeners = listeners;
}
else {
camera4d.addChangeListener(updateFacing);
camera4d.addChangeListener(Scene4d.this);
}
changed();
}
}.addTo(ss.perspective);
new AChangeListener() {
public void stateChanged() {
camera4d.setZoom(ss.zoom.getDouble());
}
}.addTo(ss.zoom);
new AChangeListener() {
public void stateChanged() {
camera4d.setOrientation(ss.orientation4d.sel().value);
}}.addTo(ss.orientation4d);
new AChangeListener() {
public void stateChanged() {
camera3d.setOrientation(
ss.orientation3d.sel().value());
changed();
}}.addTo(ss.orientation3d);
new AChangeListener() {
public void stateChanged() {
Clip clip = SoundEnum.SHOWGOAL.clip;
if (ss.showGoal.isSelected()) {
clip.setFramePosition(0);
clip.start();
}
else {
// //SoundEnum.SHOWGOAL.clip.drain();
// if (clip.isRunning())
// SoundEnum.SHOWGOAL.clip.stop();
}
changed();
}}.addTo(ss.showGoal);
camera3d.addChangeListener(this);
compounds.addChangeListener(this);
initCompounds(ss);
}
private void initCompounds(final Settings ss) {
new AChangeListener() {
@Override
public void stateChanged() {
occlusion4dAllowance = ss.occlusion4dAllowance.sel();
occlusion4dAllowanceInt = ss.occlusion4dAllowance.selInt();
changed();
}
}.addTo(ss.occlusion4dAllowance);
ss.occlusion4dAllowance.addChangeListener(updateFacing);
new AChangeListener() {
public void stateChanged() {
showInternalFaces = ss.showInternalFaces.isSelected();
updateCompoundGrid();
}}.addTo(ss.showInternalFaces);
}
private Scene4d(Camera3d c3d,Settings ss) {
camera3d = c3d;
this.ss = ss;
}
public Scene4d cloneCamRefs() {
Scene4d res = new Scene4d(camera3d,ss);
res.camera4d = camera4d;
res.showInternalFaces = showInternalFaces;
res.occlusion4dAllowance = occlusion4dAllowance;
res.occlusion4dAllowanceInt = occlusion4dAllowanceInt;
res.initCompounds(ss);
return res;
}
public void setToDefault() {
//init(0);
}
public void setCompounds(int[][][] cs) {
compounds.notify = false;
compounds.clear();
for (int i=0;i<cs.length;i++) {
compounds.add(new Compound(DOp.clone(cs[i])));
}
updateFaces3d(compounds);
updateFacing();
compounds.notify = true;
compounds.changed();
}
public void updateCompoundGrid() {
for (Compound compound: compounds) {
compound.setShowGrid(showInternalFaces);
}
}
protected void updateFacing() {
if (faces3d==null) return;
if (occlusion4dAllowanceInt>=Settings.Occlusion4dAllowance.BACKFACE.ordinal()) {
for (DCell of : faces3d) {
of.setFacing(camera4d);
}
}
}
protected final MyChangeListener updateFacing = new MyChangeListener() {
public void stateChanged() {
updateFacing();
//changed();
}
};
protected void updateFaces3d(List<Compound> cs) {
faces3d = new Vector<DCell>();
for (Compound c : cs) {
DCell[] facets4d = c.getTopLevelFacets();
for (int i=0;i<facets4d.length;i++) {
faces3d.addAll(facets4d[i].getFacets(false));
}
}
}
public void paint(D3Graphics g3) {
g3.clear();
//not in front faces:
List<DCell> ffaces3d;
try {
for (DCell dc : faces3d) dc.proj3d2dIN(g3,camera4d);
ffaces3d = faces3d;
}
catch (ProjectionException e) {
ffaces3d = new Vector<DCell>();
for (DCell dc : faces3d) {
try {
dc.proj3d2dIN(g3,camera4d);
ffaces3d.add(dc);
} catch (ProjectionException ee) {}
}
}
// for (Compound c: cs) for (DLocation v : c.getAllFaces()[0]) {
// v.proj3d2dIN(g3,camera4d);
// }
Settings.Occlusion4dAllowance oa = occlusion4dAllowance;
if (oa == Settings.Occlusion4dAllowance.NONE) {
for (DCell df3 : ffaces3d) g3.render3dFacet(df3);
}
else if (oa==Settings.Occlusion4dAllowance.BACKFACE) {
for (DCell df3 : ffaces3d) {
if (df3.facing) g3.render3dFacet(df3);
}
}
else if (oa==Settings.Occlusion4dAllowance.COMPLETE) {
Vector<DCell> dvisibles3 = new Vector<DCell>();
for (DCell df3 : ffaces3d) {
if (df3.facing) dvisibles3.add(df3);
}
CellComplex occlusionComplex = CellComplex.occlusionCreate(dvisibles3,camera4d);
assert occlusionComplex.checkSnap();
assert occlusionComplex.outsideReferrers().size() == 0;
for (Cell f1 : occlusionComplex.getFacesOfDim(1, Main.debug.isSelected())) {
if (!f1.isInternal()) {
g3.drawLine((Point3d)f1.a().o(), (Point3d)f1.b().o());
}
}
}
}
// public void addChangeListener(MyChangeListener l) {
// super.addChangeListener(l);
// compounds.addChangeListener(l);
// camera3d.addChangeListener(l);
// }
private Point4d selectedCenter4d() {
return (Point4d)compounds.sel().center();
}
public void rotCam3d(double ph, int a1, int a2) {
Point3d p3 = new Point3d();
camera4d.proj3d(selectedCenter4d(),p3);
camera3d.rot(ph, a1, a2, p3, viewAbsRel.isSelected());
}
public void rotCam4d(double ph, int a1, int a2) {
camera4d.rot(ph, a1, a2, selectedCenter4d(), viewAbsRel.isSelected());
}
}