Skip to content

Commit

Permalink
RenderMesh - Added JMH benchmark for rendering
Browse files Browse the repository at this point in the history
VertexMesh - addShape()
PackedBigArrayPoint3D_F64 - appendAll()
  • Loading branch information
lessthanoptimal committed May 12, 2023
1 parent af2b897 commit c616f21
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 9 deletions.
1 change: 0 additions & 1 deletion change.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Version : 0.43
- Scene Reconstruction
- TODO Robust optimization
- TODO 3D reconstruction to 3D mesh
- TODO Support STL format
- SLAM
- TODO traditional monocular SLAM
- Regression
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2023, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* 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 boofcv.visualize;

import boofcv.alg.geo.PerspectiveOps;
import boofcv.struct.calib.CameraPinhole;
import boofcv.struct.mesh.VertexMesh;
import georegression.struct.point.Point2D_F64;
import georegression.struct.point.Point3D_F64;
import org.ddogleg.struct.DogArray;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 2)
@Measurement(iterations = 2)
@State(Scope.Benchmark)
@Fork(value = 1)
public class BenchmarkRenderMesh {
VertexMesh mesh = new VertexMesh();

RenderMesh renderer = new RenderMesh();

@Setup public void setup() {
var intrinsics = new CameraPinhole();
PerspectiveOps.createIntrinsic(400, 300, 80, -1, intrinsics);

// Randomly generate square shapes of different sizes and distances
var rand = new Random(2342);

createFlatSquareScene(intrinsics, rand);

renderer.getIntrinsics().setTo(intrinsics);
}

private void createFlatSquareScene( CameraPinhole intrinsics, Random rand ) {
mesh.reset();
var norm = new Point2D_F64();
var shape = new DogArray<>(Point3D_F64::new);
shape.resize(4);
for (int i = 0; i < 5000; i++) {
// select pixels that it should appear at
double x0 = rand.nextDouble()*intrinsics.width*0.6;
double y0 = rand.nextDouble()*intrinsics.height*0.6;
double x1 = x0 + 10 + rand.nextDouble()*intrinsics.width*0.35;
double y1 = y0 + 10 + rand.nextDouble()*intrinsics.height*0.35;

// Randomly select the bepth
double z = 0.5 + rand.nextDouble();

// convert into a 3D point
PerspectiveOps.convertPixelToNorm(intrinsics, x0, y0, norm);
x0 = norm.x*z;
y0 = norm.x*z;
PerspectiveOps.convertPixelToNorm(intrinsics, x1, y1, norm);
x1 = norm.x*z;
y1 = norm.x*z;

// Create the shape
shape.get(0).setTo(x0, y0, z);
shape.get(1).setTo(x1, y0, z);
shape.get(2).setTo(x1, y1, z);
shape.get(3).setTo(x0, y1, z);

mesh.addShape(shape.toList());
}
}

/**
* Simple scenario with planar squares
*/
@Benchmark public void planarSquares(){
renderer.render(mesh);
}

public static void main( String[] args ) throws RunnerException {
Options opt = new OptionsBuilder()
.include(BenchmarkRenderMesh.class.getSimpleName())
.warmupTime(TimeValue.seconds(1))
.measurementTime(TimeValue.seconds(1))
.build();

new Runner(opt).run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public class RenderMesh implements VerbosePrint {
*/
public void render( VertexMesh mesh ) {
// Sanity check to see if intrinsics has been configured
BoofMiscOps.checkTrue(intrinsics.width > 0 && intrinsics.height > 0);
BoofMiscOps.checkTrue(intrinsics.width > 0 && intrinsics.height > 0, "Intrinsics not set");

// Initialize output images
initializeImages();
Expand Down
16 changes: 16 additions & 0 deletions main/boofcv-types/src/main/java/boofcv/struct/mesh/VertexMesh.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.ddogleg.struct.DogArray_I32;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
* Specifies a 3D mesh. BigArray types are used since a 3D mesh can have a very large number of points in it.
*
Expand Down Expand Up @@ -74,6 +76,20 @@ public void getShape( int which, DogArray<Point3D_F64> output ) {
}
}

/**
* Adds a new shape with the specified vertexes.
*/
public void addShape( List<Point3D_F64> shape ) {
// All the vertexes for this shape will reference newly added vertexes
int idx0 = vertexes.size();
for (int i = 0; i < shape.size(); i++) {
indexes.add(idx0 + i);
}

offsets.add(idx0 + shape.size());
vertexes.appendAll(shape);
}

public VertexMesh setTo( VertexMesh src ) {
this.vertexes.setTo(src.vertexes);
this.indexes.setTo(src.indexes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.ddogleg.struct.BigDogArray_F64;
import org.ddogleg.struct.BigDogGrowth;

import java.util.Collection;

/**
* Packed array of {@link Point3D_F64}. Internally the point is stored in an interleaved format.
*
Expand Down Expand Up @@ -101,6 +103,19 @@ public void append( GeoTuple3D_F64<?> element ) {
append(element.x, element.y, element.z);
}

/**
* Adds all the points in the collection
*/
public <T extends GeoTuple3D_F64<T>> void appendAll( Collection<T> collection ) {
// Preallocate memory for all the items in the list
reserve(collection.size());

// Add each element in the list
for (T p : collection) { // lint:forbidden ignore_line"
append(p);
}
}

@Override public void append( Point3D_F64 element ) {
dog.add(element.x);
dog.add(element.y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,51 @@
package boofcv.struct.mesh;

import boofcv.testing.BoofStandardJUnit;
import georegression.struct.point.Point3D_F64;
import org.ddogleg.struct.DogArray;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestVertexMesh extends BoofStandardJUnit {
@Test void setTo() {checkSetTo(VertexMesh.class, true);}

@Test void reset() throws Exception {checkReset(VertexMesh.class, "reset");}

@Test void addShape() {
List<Point3D_F64> shapeA = createRandomShape(3);
List<Point3D_F64> shapeB = createRandomShape(4);

var alg = new VertexMesh();
alg.addShape(shapeA);
alg.addShape(shapeB);

assertEquals(2, alg.size());
assertEquals(shapeA.size() + shapeB.size(), alg.vertexes.size());
assertEquals(alg.vertexes.size(), alg.indexes.size());

var found = new DogArray<>(Point3D_F64::new);
alg.getShape(0, found);
assertIdentical(shapeA, found.toList());
alg.getShape(1, found);
assertIdentical(shapeB, found.toList());
}

private List<Point3D_F64> createRandomShape( int count ) {
var shape = new ArrayList<Point3D_F64>();
for (int i = 0; i < count; i++) {
shape.add(new Point3D_F64(rand.nextGaussian(), rand.nextGaussian(), rand.nextGaussian()));
}
return shape;
}

private void assertIdentical( List<Point3D_F64> a, List<Point3D_F64> b ) {
assertEquals(a.size(), b.size());
for (int i = 0; i < a.size(); i++) {
assertEquals(0.0, a.get(i).distance(b.get(i)));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Peter Abeles. All Rights Reserved.
* Copyright (c) 2023, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
Expand All @@ -22,13 +22,13 @@
import georegression.struct.point.Point3D_F64;
import org.ddogleg.struct.BigDogGrowth;
import org.ejml.UtilEjml;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

/**
* @author Peter Abeles
*/
public class TestPackedBigArrayPoint3D_F64 extends GenericPackedArrayChecks<Point3D_F64> {

@Override protected PackedArray<Point3D_F64> createAlg() {
Expand All @@ -37,9 +37,9 @@ public class TestPackedBigArrayPoint3D_F64 extends GenericPackedArrayChecks<Poin

@Override protected Point3D_F64 createRandomPoint() {
var point = new Point3D_F64();
point.x = (double) rand.nextGaussian();
point.y = (double) rand.nextGaussian();
point.z = (double) rand.nextGaussian();
point.x = (double)rand.nextGaussian();
point.y = (double)rand.nextGaussian();
point.z = (double)rand.nextGaussian();
return point;
}

Expand All @@ -50,4 +50,20 @@ public class TestPackedBigArrayPoint3D_F64 extends GenericPackedArrayChecks<Poin
@Override protected void checkNotEquals( Point3D_F64 a, Point3D_F64 b ) {
assertNotEquals(0.0, a.distance(b), UtilEjml.TEST_F64);
}

@Test public void appendAll() {
var points = new ArrayList<Point3D_F64>();
points.add(new Point3D_F64(1, 2, 3));
points.add(new Point3D_F64(-1, -2, -3));
points.add(new Point3D_F64(3, 4, 5));

var alg = new PackedBigArrayPoint3D_F64();
alg.appendAll(points);

assertEquals(points.size(), alg.size);

for (int i = 0; i < points.size(); i++) {
assertEquals(0.0, points.get(i).distance(alg.getTemp(i)));
}
}
}

0 comments on commit c616f21

Please sign in to comment.