mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-03 00:38:53 +00:00
657 lines
22 KiB
Java
657 lines
22 KiB
Java
package ru.ytkab0bp.slicebeam.render;
|
|
|
|
import static android.opengl.GLES30.*;
|
|
import static ru.ytkab0bp.slicebeam.utils.DebugUtils.assertTrue;
|
|
|
|
import android.graphics.Color;
|
|
import android.opengl.GLSurfaceView;
|
|
import android.util.Log;
|
|
|
|
import androidx.core.graphics.ColorUtils;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
|
import javax.microedition.khronos.opengles.GL10;
|
|
|
|
import ru.ytkab0bp.slicebeam.R;
|
|
import ru.ytkab0bp.slicebeam.SliceBeam;
|
|
import ru.ytkab0bp.slicebeam.events.ObjectsListChangedEvent;
|
|
import ru.ytkab0bp.slicebeam.events.SelectedObjectChangedEvent;
|
|
import ru.ytkab0bp.slicebeam.slic3r.Bed3D;
|
|
import ru.ytkab0bp.slicebeam.slic3r.GCodeProcessorResult;
|
|
import ru.ytkab0bp.slicebeam.slic3r.GCodeViewer;
|
|
import ru.ytkab0bp.slicebeam.slic3r.GLModel;
|
|
import ru.ytkab0bp.slicebeam.slic3r.GLShaderProgram;
|
|
import ru.ytkab0bp.slicebeam.slic3r.GLShadersManager;
|
|
import ru.ytkab0bp.slicebeam.slic3r.Model;
|
|
import ru.ytkab0bp.slicebeam.slic3r.Slic3rUtils;
|
|
import ru.ytkab0bp.slicebeam.theme.ThemesRepo;
|
|
import ru.ytkab0bp.slicebeam.utils.DoubleMatrix;
|
|
import ru.ytkab0bp.slicebeam.utils.Prefs;
|
|
import ru.ytkab0bp.slicebeam.utils.Vec3d;
|
|
import ru.ytkab0bp.slicebeam.utils.ViewUtils;
|
|
import ru.ytkab0bp.slicebeam.view.GLView;
|
|
|
|
public class GLRenderer implements GLSurfaceView.Renderer {
|
|
private final static float FOV = 60f;
|
|
private final static float NEAR_PLANE = 10f;
|
|
private final static float FAR_PLANE = 1000f;
|
|
|
|
private Camera camera = new Camera();
|
|
private double[] projectionMatrix = new double[16];
|
|
private double[] modelMatrix = new double[16];
|
|
private double[] normalMatrix = new double[12];
|
|
private double[] outModelMatrix = new double[16];
|
|
|
|
private int viewportWidth, viewportHeight;
|
|
|
|
private boolean cameraIsDirty = true;
|
|
|
|
// Instance values, should be released
|
|
private Bed3D bed;
|
|
private int lastConfigUid;
|
|
private GLModel backgroundModel;
|
|
private GLModel selectionModel;
|
|
private List<GLModel> glModels = new ArrayList<>();
|
|
|
|
private Model model;
|
|
|
|
private GCodeProcessorResult gcodeResult;
|
|
private GCodeViewer viewer;
|
|
private boolean isViewerEnabled;
|
|
|
|
private int selectedObject = -1;
|
|
private double selX, selY, selZ;
|
|
private double selRotX, selRotY, selRotZ;
|
|
private double selScaleX = 1, selScaleY = 1, selScaleZ = 1;
|
|
|
|
private long lastDraw;
|
|
private GLView glView;
|
|
private Vec3d translate = new Vec3d();
|
|
private Vec3d rotate = new Vec3d();
|
|
private ArrayList<GLModel.HitResult> raycastHits = new ArrayList<>();
|
|
|
|
private Vec3d bbMin = new Vec3d(), bbMax = new Vec3d();
|
|
private boolean isInFlattenMode;
|
|
private ArrayList<GLModel> flattenPlanes = new ArrayList<>();
|
|
|
|
public Camera getCamera() {
|
|
return camera;
|
|
}
|
|
|
|
public Bed3D getBed() {
|
|
return bed;
|
|
}
|
|
|
|
public double[] getProjectionMatrix() {
|
|
return projectionMatrix;
|
|
}
|
|
|
|
public int getViewportWidth() {
|
|
return viewportWidth;
|
|
}
|
|
|
|
public int getViewportHeight() {
|
|
return viewportHeight;
|
|
}
|
|
|
|
public void setGCodeViewer(GCodeProcessorResult result) {
|
|
this.isViewerEnabled = result != null;
|
|
this.gcodeResult = result;
|
|
|
|
if (!isViewerEnabled && viewer != null) {
|
|
viewer.release();
|
|
viewer = null;
|
|
}
|
|
}
|
|
|
|
public GLRenderer(GLView glView) {
|
|
this.glView = glView;
|
|
}
|
|
|
|
@Override
|
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
|
|
|
|
@Override
|
|
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
|
if (bed != null) {
|
|
onDestroy();
|
|
}
|
|
onCreate();
|
|
glViewport(0, 0, viewportWidth = width, viewportHeight = height);
|
|
updateProjection();
|
|
}
|
|
|
|
public void updateProjection() {
|
|
if (bed == null || !bed.isValid()) return;
|
|
float aspectRatio = (float) viewportWidth / viewportHeight;
|
|
float invZoom = 1f / camera.getZoom();
|
|
if (Prefs.isOrthoProjectionEnabled()) {
|
|
Vec3d diff = bed.getVolumeMax().clone().add(bed.getVolumeMin().clone());
|
|
double scale = (Math.max(diff.x, diff.y) / 2f + 10f) * invZoom;
|
|
|
|
float ratioHorizontal = aspectRatio > 1 ? aspectRatio : 1;
|
|
float ratioVertical = aspectRatio < 1 ? 1f / aspectRatio : 1;
|
|
DoubleMatrix.orthoM(projectionMatrix, 0, -scale * ratioHorizontal, scale * ratioHorizontal, -scale * ratioVertical, scale * ratioVertical, NEAR_PLANE, FAR_PLANE);
|
|
} else {
|
|
DoubleMatrix.perspectiveM(projectionMatrix, 0, FOV * invZoom * (viewportWidth > viewportHeight ? 1 / aspectRatio : 1), aspectRatio, NEAR_PLANE, FAR_PLANE);
|
|
}
|
|
}
|
|
|
|
public int getSelectedObject() {
|
|
return selectedObject;
|
|
}
|
|
|
|
public void invalidateGlModel(int i) {
|
|
if (model == null) return;
|
|
if (i < glModels.size()) {
|
|
GLModel glModel = glModels.get(i);
|
|
glModel.reset();
|
|
glModel.initFrom(model, i);
|
|
}
|
|
}
|
|
|
|
public void invalidateSelectionObject() {
|
|
if (selectionModel != null) {
|
|
selectionModel.reset();
|
|
}
|
|
}
|
|
|
|
public void resetGlModels() {
|
|
if (model == null) return;
|
|
for (int i = 0; i < model.getObjectsCount(); i++) {
|
|
if (i >= glModels.size()) continue;
|
|
|
|
GLModel glModel = glModels.get(i);
|
|
glModel.reset();
|
|
glModel.initFrom(model, i);
|
|
}
|
|
}
|
|
|
|
public boolean invalidateFlattenMode() {
|
|
if (isInFlattenMode) {
|
|
setInFlattenMode(true);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean resetFlattenMode() {
|
|
if (isInFlattenMode) {
|
|
setInFlattenMode(false);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void setInFlattenMode(boolean inFlattenMode) {
|
|
isInFlattenMode = inFlattenMode;
|
|
|
|
for (int i = 0, c = flattenPlanes.size(); i < c; i++) {
|
|
flattenPlanes.get(i).release();
|
|
}
|
|
flattenPlanes.clear();
|
|
|
|
if (isInFlattenMode) {
|
|
List<GLModel> planes = model.createFlattenPlanes(selectedObject);
|
|
flattenPlanes.addAll(planes);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onDrawFrame(GL10 gl) {
|
|
if (backgroundModel == null) return; // Not initialized yet
|
|
long dt = Math.min(System.currentTimeMillis() - lastDraw, 16);
|
|
lastDraw = System.currentTimeMillis();
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(GL_BACK);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
GLShaderProgram shader = GLShadersManager.get(GLShadersManager.SHADER_BACKGROUND);
|
|
shader.startUsing();
|
|
shader.setUniformColor("top_color", ThemesRepo.getColor(R.attr.backgroundColorTop));
|
|
shader.setUniformColor("bottom_color", ThemesRepo.getColor(R.attr.backgroundColorBottom));
|
|
backgroundModel.render();
|
|
shader.stopUsing();
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
boolean bottom = Prefs.isOrthoProjectionEnabled() ? camera.getDirForward().z > 0 : camera.getDirToBed().z > 0;
|
|
if (lastConfigUid != SliceBeam.CONFIG_UID) {
|
|
configureBed();
|
|
}
|
|
if (bed.isValid()) {
|
|
bed.render(bottom, camera.getViewModelMatrix(), projectionMatrix, 1f / camera.getZoom());
|
|
}
|
|
|
|
if (isViewerEnabled) {
|
|
if (viewer == null) {
|
|
viewer = new GCodeViewer();
|
|
viewer.initGL();
|
|
viewer.setThemeColors();
|
|
viewer.load(gcodeResult);
|
|
}
|
|
|
|
viewer.render(camera.getViewModelMatrix(), projectionMatrix);
|
|
}
|
|
if (viewer == null && model != null) {
|
|
shader = GLShadersManager.get(GLShadersManager.SHADER_GOURAUD_LIGHT);
|
|
shader.startUsing();
|
|
int color = ThemesRepo.getColor(android.R.attr.colorAccent);
|
|
int hoverColor = ThemesRepo.getColor(R.attr.modelHoverColor);
|
|
|
|
for (int i = 0; i < model.getObjectsCount(); i++) {
|
|
boolean left = model.isLeftHanded(i);
|
|
if (left) {
|
|
glFrontFace(GL_CW);
|
|
}
|
|
|
|
boolean selected = i == selectedObject;
|
|
|
|
shader.setUniform("emission_factor", 0.05f);
|
|
DoubleMatrix.setIdentityM(modelMatrix, 0);
|
|
if (selected) {
|
|
DoubleMatrix.translateM(modelMatrix, 0, selX, selY, selZ);
|
|
|
|
model.getTranslation(i, translate);
|
|
model.getRotation(i, rotate);
|
|
DoubleMatrix.translateM(modelMatrix, 0, translate.x, translate.y, translate.z);
|
|
DoubleMatrix.rotateM(modelMatrix, 0, selRotX, 1, 0, 0);
|
|
DoubleMatrix.rotateM(modelMatrix, 0, selRotY, 0, 1, 0);
|
|
DoubleMatrix.rotateM(modelMatrix, 0, selRotZ, 0, 0, 1);
|
|
DoubleMatrix.scaleM(modelMatrix, 0, selScaleX, selScaleY, selScaleZ);
|
|
DoubleMatrix.translateM(modelMatrix, 0, -translate.x, -translate.y, -translate.z);
|
|
}
|
|
DoubleMatrix.multiplyMM(outModelMatrix, 0, camera.getViewModelMatrix(), 0, modelMatrix, 0);
|
|
|
|
shader.setUniformMatrix4fv("view_model_matrix", outModelMatrix);
|
|
shader.setUniformMatrix4fv("projection_matrix", projectionMatrix);
|
|
|
|
Slic3rUtils.calcViewNormalMatrix(camera.getViewModelMatrix(), modelMatrix, normalMatrix);
|
|
shader.setUniformMatrix3fv("view_normal_matrix", normalMatrix);
|
|
|
|
shader.setUniform("volume_mirrored", left);
|
|
|
|
if (glModels.size() < i + 1) {
|
|
GLModel glModel = new GLModel();
|
|
glModel.initFrom(model, i);
|
|
glModels.add(glModel);
|
|
}
|
|
GLModel glModel = glModels.get(i);
|
|
boolean hovering = glModel.isHovering || selectedObject == i;
|
|
// FIXME: Render is lagging out with hover progress
|
|
// if (hovering && glModel.hoverProgress < 1) {
|
|
// glModel.hoverProgress = Math.min(glModel.hoverProgress + dt / 50f, 1);
|
|
// glView.queueEvent(() -> glView.requestRender());
|
|
// } else if (!hovering && glModel.hoverProgress > 0) {
|
|
// glModel.hoverProgress = Math.max(glModel.hoverProgress - dt / 50f, 0);
|
|
// glView.queueEvent(() -> glView.requestRender());
|
|
// }
|
|
glModel.setColor(ColorUtils.blendARGB(color, hoverColor, hovering ? 1 : 0));
|
|
glModel.render();
|
|
|
|
if (left) {
|
|
glFrontFace(GL_CCW);
|
|
}
|
|
|
|
if (selected) {
|
|
shader.stopUsing();
|
|
|
|
GLShaderProgram flat = GLShadersManager.get(GLShadersManager.SHADER_FLAT);
|
|
glLineWidth(ViewUtils.dp(1.5f));
|
|
|
|
flat.startUsing();
|
|
flat.setUniformMatrix4fv("view_model_matrix", outModelMatrix);
|
|
flat.setUniformMatrix4fv("projection_matrix", projectionMatrix);
|
|
|
|
if (selectionModel == null) {
|
|
selectionModel = new GLModel();
|
|
}
|
|
selectionModel.initBoundingBox(model, i);
|
|
selectionModel.setColor(hoverColor);
|
|
selectionModel.render();
|
|
|
|
flat.stopUsing();
|
|
|
|
shader.startUsing();
|
|
}
|
|
|
|
if (isInFlattenMode) {
|
|
shader.stopUsing();
|
|
|
|
GLShaderProgram flat = GLShadersManager.get(GLShadersManager.SHADER_FLAT);
|
|
|
|
flat.startUsing();
|
|
glEnable(GL_BLEND);
|
|
flat.setUniformMatrix4fv("view_model_matrix", outModelMatrix);
|
|
flat.setUniformMatrix4fv("projection_matrix", projectionMatrix);
|
|
|
|
for (GLModel plane : flattenPlanes) {
|
|
boolean hoveringPlane = plane.isHovering;
|
|
int clr = ColorUtils.blendARGB(hoverColor, color, hoveringPlane ? 1 : 0);
|
|
plane.setColor(ColorUtils.setAlphaComponent(clr, (int) (Color.alpha(clr) * 0.75f)));
|
|
plane.render();
|
|
}
|
|
|
|
glDisable(GL_BLEND);
|
|
flat.stopUsing();
|
|
|
|
shader.startUsing();
|
|
}
|
|
}
|
|
shader.stopUsing();
|
|
}
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_CULL_FACE);
|
|
}
|
|
|
|
public boolean deleteObject(int i) {
|
|
if (model == null) return false;
|
|
assertTrue(i >= 0 && i < model.getObjectsCount());
|
|
|
|
model.deleteObject(i);
|
|
if (glModels.size() > i) {
|
|
glModels.remove(i).release();
|
|
}
|
|
if (i == selectedObject) {
|
|
selectedObject = -1;
|
|
selX = selY = selZ = 0;
|
|
selRotX = selRotY = selRotZ = 0;
|
|
selScaleX = selScaleY = selScaleZ = 1;
|
|
SliceBeam.EVENT_BUS.fireEvent(new SelectedObjectChangedEvent());
|
|
}
|
|
|
|
if (model.getObjectsCount() == 0) {
|
|
model.release();
|
|
model = null;
|
|
}
|
|
SliceBeam.EVENT_BUS.fireEvent(new ObjectsListChangedEvent());
|
|
return true;
|
|
}
|
|
|
|
public int raycastObjectIndex(float x, float y) {
|
|
if (model == null) return -1;
|
|
double minDistance = Double.MAX_VALUE;
|
|
int j = -1;
|
|
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
|
if (i >= glModels.size()) continue;
|
|
|
|
GLModel glModel = glModels.get(i);
|
|
glModel.getRaycaster().raycast(this, raycastHits, x, y);
|
|
|
|
boolean hovered = !raycastHits.isEmpty();
|
|
if (hovered) {
|
|
double distance = raycastHits.get(0).position.distance(camera.position);
|
|
if (distance < minDistance) {
|
|
minDistance = distance;
|
|
j = i;
|
|
}
|
|
}
|
|
}
|
|
return j;
|
|
}
|
|
|
|
public boolean onClick(float x, float y) {
|
|
if (model == null || isViewerEnabled) return false;
|
|
|
|
int j = raycastObjectIndex(x, y);
|
|
|
|
if (isInFlattenMode && (j == selectedObject || j == -1)) {
|
|
int minPlane = -1;
|
|
double minDistancePlane = Double.MAX_VALUE;
|
|
|
|
for (int i = 0, c = flattenPlanes.size(); i < c; i++) {
|
|
GLModel glModel = flattenPlanes.get(i);
|
|
glModel.getRaycaster().raycast(this, raycastHits, x, y);
|
|
|
|
double minDistanceRay = Double.MAX_VALUE;
|
|
if (!raycastHits.isEmpty()) {
|
|
for (GLModel.HitResult res : raycastHits) {
|
|
double distance = res.position.distance(camera.position);
|
|
if (distance < minDistanceRay) {
|
|
minDistanceRay = distance;
|
|
}
|
|
}
|
|
}
|
|
if (minDistanceRay < minDistancePlane) {
|
|
minDistancePlane = minDistanceRay;
|
|
minPlane = i;
|
|
}
|
|
}
|
|
|
|
if (minPlane != -1) {
|
|
GLModel glModel = flattenPlanes.get(minPlane);
|
|
model.flattenRotate(selectedObject, glModel);
|
|
model.ensureOnBed(selectedObject);
|
|
|
|
invalidateGlModel(selectedObject);
|
|
for (int k = 0, l = flattenPlanes.size(); k < l; k++) {
|
|
flattenPlanes.get(k).release();
|
|
}
|
|
flattenPlanes.clear();
|
|
|
|
selectedObject = -1;
|
|
SliceBeam.EVENT_BUS.fireEvent(new SelectedObjectChangedEvent());
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
boolean render = j != selectedObject || j != -1;
|
|
selectedObject = j == selectedObject ? -1 : j;
|
|
if (render) {
|
|
if (isInFlattenMode) {
|
|
setInFlattenMode(false);
|
|
}
|
|
if (selectedObject == -1) {
|
|
selX = selY = selZ = 0;
|
|
selRotX = selRotY = selRotZ = 0;
|
|
selScaleX = selScaleY = selScaleZ = 1;
|
|
}
|
|
SliceBeam.EVENT_BUS.fireEvent(new SelectedObjectChangedEvent());
|
|
}
|
|
return render;
|
|
}
|
|
|
|
public boolean hover(float x, float y) {
|
|
if (model == null || isViewerEnabled) return false;
|
|
|
|
boolean render = false;
|
|
double minDistance = Double.MAX_VALUE;
|
|
GLModel minModel = null;
|
|
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
|
if (i >= glModels.size()) continue;
|
|
|
|
GLModel glModel = glModels.get(i);
|
|
glModel.getRaycaster().raycast(this, raycastHits, x, y);
|
|
|
|
boolean hovered = !raycastHits.isEmpty();
|
|
if (hovered) {
|
|
double distance = raycastHits.get(0).position.distance(camera.position);
|
|
if (distance < minDistance) {
|
|
minDistance = distance;
|
|
minModel = glModel;
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
|
if (i >= glModels.size()) continue;
|
|
|
|
GLModel glModel = glModels.get(i);
|
|
|
|
boolean hovered = minModel == glModel;
|
|
if (glModel.isHovering && !hovered) {
|
|
glModel.isHovering = false;
|
|
render = true;
|
|
} else if (!glModel.isHovering && hovered) {
|
|
glModel.isHovering = true;
|
|
render = true;
|
|
}
|
|
}
|
|
|
|
if (isInFlattenMode) {
|
|
int minPlane = -1;
|
|
double minDistancePlane = Double.MAX_VALUE;
|
|
|
|
for (int i = 0, c = flattenPlanes.size(); i < c; i++) {
|
|
GLModel glModel = flattenPlanes.get(i);
|
|
glModel.getRaycaster().raycast(this, raycastHits, x, y);
|
|
|
|
double minDistanceRay = Double.MAX_VALUE;
|
|
if (!raycastHits.isEmpty()) {
|
|
for (GLModel.HitResult res : raycastHits) {
|
|
double distance = res.position.distance(camera.position);
|
|
if (distance < minDistanceRay) {
|
|
minDistanceRay = distance;
|
|
}
|
|
}
|
|
}
|
|
if (minDistanceRay < minDistancePlane) {
|
|
minDistancePlane = minDistanceRay;
|
|
minPlane = i;
|
|
}
|
|
}
|
|
|
|
if (minPlane != -1) {
|
|
for (int i = 0; i < flattenPlanes.size(); i++) {
|
|
flattenPlanes.get(i).isHovering = i == minPlane;
|
|
}
|
|
render = true;
|
|
} else {
|
|
for (int i = 0; i < flattenPlanes.size(); i++) {
|
|
if (flattenPlanes.get(i).isHovering) {
|
|
flattenPlanes.get(i).isHovering = false;
|
|
render = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return render;
|
|
}
|
|
|
|
public boolean stopHover() {
|
|
if (model == null) return false;
|
|
|
|
boolean render = false;
|
|
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
|
if (i >= glModels.size()) continue;
|
|
|
|
GLModel glModel = glModels.get(i);
|
|
if (glModel.isHovering) {
|
|
glModel.isHovering = false;
|
|
render = true;
|
|
}
|
|
}
|
|
return render;
|
|
}
|
|
|
|
public void setSelectionRotation(double x, double y, double z) {
|
|
selRotX = x;
|
|
selRotY = y;
|
|
selRotZ = z;
|
|
}
|
|
|
|
public void setSelectionScale(double x, double y, double z) {
|
|
selScaleX = x;
|
|
selScaleY = y;
|
|
selScaleZ = z;
|
|
}
|
|
|
|
public void setSelectionTranslation(double x, double y, double z) {
|
|
selX = x;
|
|
selY = y;
|
|
selZ = z;
|
|
}
|
|
|
|
public void setModel(Model model) {
|
|
this.model = model;
|
|
resetGlModels();
|
|
}
|
|
|
|
public Model getModel() {
|
|
return model;
|
|
}
|
|
|
|
public GCodeProcessorResult getGcodeResult() {
|
|
return gcodeResult;
|
|
}
|
|
|
|
public GCodeViewer getViewer() {
|
|
return viewer;
|
|
}
|
|
|
|
private void configureBed() {
|
|
try {
|
|
lastConfigUid = SliceBeam.CONFIG_UID;
|
|
SliceBeam.genCurrentConfig();
|
|
bed.configure(SliceBeam.getCurrentConfigFile());
|
|
} catch (Exception e) {
|
|
Log.e("GLRenderer", "Failed to update config", e);
|
|
}
|
|
}
|
|
|
|
private void onCreate() {
|
|
bed = new Bed3D();
|
|
configureBed();
|
|
|
|
backgroundModel = new GLModel();
|
|
backgroundModel.initBackgroundTriangles();
|
|
if (!bed.isValid()) return;
|
|
|
|
if (cameraIsDirty) {
|
|
Vec3d min = bed.getVolumeMin(), max = bed.getVolumeMax();
|
|
Vec3d center = min.center(max);
|
|
camera.origin.set(center);
|
|
camera.origin.z = 0;
|
|
|
|
camera.position.x = center.x - center.z * 2;
|
|
camera.position.y = center.y - center.z * 2;
|
|
camera.position.z = min.z + Math.sqrt(center.z * center.z * 8);
|
|
cameraIsDirty = false;
|
|
}
|
|
if (isViewerEnabled) {
|
|
viewer = new GCodeViewer();
|
|
viewer.initGL();
|
|
viewer.setThemeColors();
|
|
viewer.load(gcodeResult);
|
|
}
|
|
}
|
|
|
|
public void onDestroy() {
|
|
GLShadersManager.clearShaders();
|
|
if (backgroundModel != null) {
|
|
backgroundModel.release();
|
|
backgroundModel = null;
|
|
}
|
|
if (selectionModel != null) {
|
|
selectionModel.release();
|
|
selectionModel = null;
|
|
}
|
|
if (bed != null) {
|
|
bed.release();
|
|
bed = null;
|
|
}
|
|
if (viewer != null) {
|
|
viewer.release();
|
|
viewer = null;
|
|
}
|
|
for (int i = 0; i < glModels.size(); i++) {
|
|
glModels.get(i).release();
|
|
}
|
|
glModels.clear();
|
|
|
|
isInFlattenMode = false;
|
|
for (int i = 0; i < flattenPlanes.size(); i++) {
|
|
flattenPlanes.get(i).release();
|
|
}
|
|
flattenPlanes.clear();
|
|
}
|
|
}
|