BlueMap/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Model.java

150 lines
4.9 KiB
Java

/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.flowpowered.math.imaginary.Quaternionf;
import com.flowpowered.math.matrix.Matrix3f;
import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector3f;
import de.bluecolored.bluemap.core.threejs.BufferGeometry;
public class Model {
private List<Face> faces;
public Model() {
this.faces = new ArrayList<>();
}
/**
* Merges the given Model into this model<br>
* Faces are not cloned: So changes to the faces of the previous model will mirror in this model, but adding and removing faces will not.
*/
public void merge(Model model){
faces.addAll(model.getFaces());
}
public void addFace(Face face){
faces.add(face);
}
public void removeFace(Face face){
faces.remove(face);
}
public Collection<Face> getFaces(){
return faces;
}
public void rotate(Quaternionf rotation){
for (Face f : faces){
f.rotate(rotation);
}
}
public void transform(Matrix3f transformation){
for (Face f : faces){
f.transform(transformation);
}
}
public void translate(Vector3f translation){
for (Face f : faces){
f.translate(translation);
}
}
public BufferGeometry toBufferGeometry() {
//sort faces by material index
faces.sort((f1, f2) -> (int) Math.signum(f1.getMaterialIndex() - f2.getMaterialIndex()));
//reorganize all faces into arrays and create material-groups
int count = faces.size();
List<BufferGeometry.MaterialGroup> groups = new ArrayList<>();
int groupStart = 0;
int currentMaterialIndex = -1;
if (count > 0) currentMaterialIndex = faces.get(0).getMaterialIndex();
float[] position = new float[count * 3 * 3];
float[] normal = new float[count * 3 * 3];
float[] color = new float[count * 3 * 3];
float[] uv = new float[count * 2 * 3];
for (int itemIndex = 0; itemIndex < count; itemIndex++){
Face f = faces.get(itemIndex);
if (currentMaterialIndex != f.getMaterialIndex()){
groups.add(new BufferGeometry.MaterialGroup(currentMaterialIndex, groupStart * 3, (itemIndex - groupStart) * 3));
groupStart = itemIndex;
currentMaterialIndex = f.getMaterialIndex();
}
addVector3fToArray( position, f.getP1(), (itemIndex * 3 + 0) * 3 );
addVector3fToArray( normal, f.getN1(), (itemIndex * 3 + 0) * 3 );
addVector3fToArray( color, f.getC1(), (itemIndex * 3 + 0) * 3 );
addVector2fToArray( uv, f.getUv1(), (itemIndex * 3 + 0) * 2 );
addVector3fToArray( position, f.getP2(), (itemIndex * 3 + 1) * 3 );
addVector3fToArray( normal, f.getN2(), (itemIndex * 3 + 1) * 3 );
addVector3fToArray( color, f.getC2(), (itemIndex * 3 + 1) * 3 );
addVector2fToArray( uv, f.getUv2(), (itemIndex * 3 + 1) * 2 );
addVector3fToArray( position, f.getP3(), (itemIndex * 3 + 2) * 3 );
addVector3fToArray( normal, f.getN3(), (itemIndex * 3 + 2) * 3 );
addVector3fToArray( color, f.getC3(), (itemIndex * 3 + 2) * 3 );
addVector2fToArray( uv, f.getUv3(), (itemIndex * 3 + 2) * 2 );
}
groups.add(new BufferGeometry.MaterialGroup(currentMaterialIndex, groupStart * 3, (count - groupStart) * 3));
return new BufferGeometry(
position,
normal,
color,
uv,
groups.toArray(new BufferGeometry.MaterialGroup[groups.size()])
);
}
private void addVector3fToArray(float[] array, Vector3f v, int startIndex){
array[startIndex] = v.getX();
array[startIndex + 1] = v.getY();
array[startIndex + 2] = v.getZ();
}
private void addVector2fToArray(float[] array, Vector2f v, int startIndex){
array[startIndex] = v.getX();
array[startIndex + 1] = v.getY();
}
}