Skip to content

Commit

Permalink
Allow saving geometry data as OBJ.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuetschard committed Aug 2, 2017
1 parent 7b66505 commit dc07b4a
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 1 deletion.
112 changes: 112 additions & 0 deletions gapic/src/main/com/google/gapid/glviewer/geo/ObjWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gapid.glviewer.geo;

import java.io.IOException;
import java.io.Writer;

/**
* Writes {@link Model models} to OBJ files.
*/
public class ObjWriter {
private ObjWriter() {
}

public static void write(Writer out, Model model) throws IOException {
// TODO: could possibly make the OBJ smaller by deduping vertices and normals.
writePositions(out, model.getPositions());
writeNormals(out, model.getNormals());
out.write("s 1\n");
switch (model.getPrimitive()) {
case Points: writePoints(out, model.getIndices()); break;
case Lines: writeLines(out, model.getIndices()); break;
case LineStrip: writeLineStrip(out, model.getIndices()); break;
case LineLoop: writeLineLoop(out, model.getIndices()); break;
case Triangles: writeTriangles(out, model.getIndices()); break;
case TriangleStrip: writeTriangleStrip(out, model.getIndices()); break;
case TriangleFan: writeTriangleFan(out, model.getIndices()); break;
default: throw new IOException("Unsupported draw primitive: " + model.getPrimitive());
}
}

private static void writePositions(Writer out, float[] pos) throws IOException {
for (int i = 2; i < pos.length; i += 3) {
out.write("v " + pos[i - 2] + " " + pos[i - 1] + " " + pos[i - 0] + "\n");
}
}

private static void writeNormals(Writer out, float[] normals) throws IOException {
for (int i = 2; i < normals.length; i += 3) {
out.write("vn " + normals[i - 2] + " " + normals[i - 1] + " " + normals[i - 0] + "\n");
}
}

private static void writePoints(Writer out, int[] indices) throws IOException {
for (int i : indices) {
out.write("p " + (i + 1) + "\n");
}
}

private static void writeLines(Writer out, int[] indices) throws IOException {
for (int i = 1; i < indices.length; i += 2) {
writeLine(out, indices[i - 1], indices[i - 0]);
}
}

private static void writeLineStrip(Writer out, int[] indices) throws IOException {
for (int i = 1; i < indices.length; i++) {
writeLine(out, indices[i - 1], indices[i]);
}
}

private static void writeLineLoop(Writer out, int[] indices) throws IOException {
for (int i = 1; i < indices.length; i++) {
writeLine(out, indices[i - 1], indices[i]);
}
writeLine(out, indices[indices.length - 1], 0);
}

private static void writeLine(Writer out, int a, int b) throws IOException {
out.write("l " + (a + 1) + " " + (b + 1) + "\n");
}

private static void writeTriangles(Writer out, int[] indices) throws IOException {
for (int i = 2; i < indices.length; i += 3) {
writeTriangle(out, indices[i - 2], indices[i - 1], indices[i - 0]);
}
}

private static void writeTriangleStrip(Writer out, int[] indices) throws IOException {
for (int i = 2; i < indices.length; i += 3) {
writeTriangle(out, indices[i - 2], indices[i - 1], indices[i - 0]);
if ((i += 3) >= indices.length) {
break;
}
writeTriangle(out, indices[i - 1], indices[i - 2], indices[i - 0]);
}
}

private static void writeTriangleFan(Writer out, int[] indices) throws IOException {
for (int i = 2; i < indices.length; i++) {
writeTriangle(out, indices[0], indices[i - 1], indices[i]);
}
}

private static void writeTriangle(Writer out, int a, int b, int c) throws IOException {
out.write("f " + (a + 1) + "//" + (a + 1) + " " + (b + 1) + "//" + (b + 1) +
" " + (c + 1) + "//" + (c + 1) + "\n");
}
}
35 changes: 34 additions & 1 deletion gapic/src/main/com/google/gapid/views/GeometryView.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static com.google.gapid.widgets.Widgets.createToolItem;
import static com.google.gapid.widgets.Widgets.exclusiveSelection;
import static java.util.Collections.emptyList;
import static java.util.logging.Level.WARNING;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
Expand All @@ -36,6 +37,7 @@
import com.google.gapid.glviewer.camera.CylindricalCameraModel;
import com.google.gapid.glviewer.camera.IsoSurfaceCameraModel;
import com.google.gapid.glviewer.geo.Model;
import com.google.gapid.glviewer.geo.ObjWriter;
import com.google.gapid.models.AtomStream;
import com.google.gapid.models.AtomStream.AtomIndex;
import com.google.gapid.models.Capture;
Expand All @@ -54,8 +56,8 @@
import com.google.gapid.util.Loadable;
import com.google.gapid.util.Messages;
import com.google.gapid.util.Streams;
import com.google.gapid.widgets.ScenePanel;
import com.google.gapid.widgets.LoadablePanel;
import com.google.gapid.widgets.ScenePanel;
import com.google.gapid.widgets.Theme;
import com.google.gapid.widgets.Widgets;
import com.google.protobuf.ByteString;
Expand All @@ -65,9 +67,14 @@
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
Expand Down Expand Up @@ -111,6 +118,7 @@ public class GeometryView extends Composite implements Tab, Capture.Listener, At
private Geometry.DisplayMode displayMode = Geometry.DisplayMode.TRIANGLES;
private Geometry.DisplayMode desiredDisplayMode = Geometry.DisplayMode.TRIANGLES;
private ToolItem renderAsTriangles, renderAsLines, renderAsPoints;
private ToolItem saveItem;

public GeometryView(Composite parent, Client client, Models models, Widgets widgets) {
super(parent, SWT.NONE);
Expand Down Expand Up @@ -138,6 +146,7 @@ public GeometryView(Composite parent, Client client, Models models, Widgets widg

originalModelItem.setEnabled(false);
facetedModelItem.setEnabled(false);
saveItem.setEnabled(false);
}

private ToolBar createToolbar(Theme theme) {
Expand Down Expand Up @@ -191,6 +200,26 @@ private ToolBar createToolbar(Theme theme) {
createToggleToolItem(bar, theme.normals(), e -> {
setSceneData(data.withShading(GeometryScene.Shading.NORMALS));
}, "Render normals"));
createSeparator(bar);
saveItem = createToolItem(bar, theme.save(), e -> {
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setText("Save model to...");
dialog.setFilterNames(new String[] { "OBJ Files (*.obj)" });
dialog.setFilterExtensions(new String[] { "*.obj" });
dialog.setOverwrite(true);
String objFile = dialog.open();
if (objFile != null) {
try (Writer out = new FileWriter(objFile)) {
ObjWriter.write(out, originalModelItem.getSelection() ? originalModel : facetedModel);
} catch (IOException ex) {
LOG.log(WARNING, "Failed to save model as OBJ", e);
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR);
mb.setText("Failed to save model...");
mb.setMessage("Failed to save OBJ: " + ex.getMessage());
mb.open();
}
}
}, "Save model as OBJ");
return bar;
}

Expand Down Expand Up @@ -231,11 +260,13 @@ private void updateModels(boolean assumeLoading) {
AtomIndex atom = models.atoms.getSelectedAtoms();
if (atom == null) {
loading.showMessage(Info, Messages.SELECT_DRAW_CALL);
saveItem.setEnabled(false);
} else {
fetchMeshes(atom);
}
} else {
loading.showMessage(Info, Messages.LOADING_CAPTURE);
saveItem.setEnabled(false);
}
}

Expand Down Expand Up @@ -331,6 +362,7 @@ private static float[] byteStringToFloatArray(ByteString bytes) {
protected void update(List<Model> modelList) {
if (modelList.isEmpty()) {
loading.showMessage(Info, Messages.SELECT_DRAW_CALL);
saveItem.setEnabled(false);
return;
}

Expand All @@ -339,6 +371,7 @@ protected void update(List<Model> modelList) {
loading.stopLoading();
originalModelItem.setEnabled(originalModel != null);
facetedModelItem.setEnabled(facetedModel != null);
saveItem.setEnabled(true);
if (originalModel != null) {
setModel(originalModel);
originalModelItem.setSelection(true);
Expand Down
1 change: 1 addition & 0 deletions gapic/src/main/com/google/gapid/widgets/ImagePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ protected void updateBackgroundMode(BackgroundMode mode, Theme theme) {

protected void save() {
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setText("Save image to...");
dialog.setFilterNames(new String[] { "PNG Images" });
dialog.setFilterExtensions(new String[] { "*.png" });
dialog.setOverwrite(true);
Expand Down

0 comments on commit dc07b4a

Please sign in to comment.