use of com.jme3.scene.shape.Quad in project jmonkeyengine by jMonkeyEngine.
the class MikktspaceTangentGenerator method generateTSpaces.
static boolean generateTSpaces(TSpace[] psTspace, final TriInfo[] pTriInfos, final Group[] pGroups, final int iNrActiveGroups, final int[] piTriListIn, final float fThresCos, final MikkTSpaceContext mikkTSpace) {
TSpace[] pSubGroupTspace;
SubGroup[] pUniSubGroups;
int[] pTmpMembers;
int iMaxNrFaces = 0, iUniqueTspaces = 0, g = 0, i = 0;
for (g = 0; g < iNrActiveGroups; g++) {
if (iMaxNrFaces < pGroups[g].nrFaces) {
iMaxNrFaces = pGroups[g].nrFaces;
}
}
if (iMaxNrFaces == 0) {
return true;
}
// make initial allocations
pSubGroupTspace = new TSpace[iMaxNrFaces];
pUniSubGroups = new SubGroup[iMaxNrFaces];
pTmpMembers = new int[iMaxNrFaces];
iUniqueTspaces = 0;
for (g = 0; g < iNrActiveGroups; g++) {
final Group pGroup = pGroups[g];
int iUniqueSubGroups = 0, s = 0;
for (// triangles
i = 0; // triangles
i < pGroup.nrFaces; // triangles
i++) {
// triangle number
final int f = pGroup.faceIndices.get(i);
int index = -1, iVertIndex = -1, iOF_1 = -1, iMembers = 0, j = 0, l = 0;
SubGroup tmp_group = new SubGroup();
boolean bFound;
Vector3f n, vOs, vOt;
if (pTriInfos[f].assignedGroup[0] == pGroup) {
index = 0;
} else if (pTriInfos[f].assignedGroup[1] == pGroup) {
index = 1;
} else if (pTriInfos[f].assignedGroup[2] == pGroup) {
index = 2;
}
assert (index >= 0 && index < 3);
iVertIndex = piTriListIn[f * 3 + index];
assert (iVertIndex == pGroup.vertexRepresentitive);
// is normalized already
n = getNormal(mikkTSpace, iVertIndex);
// project
vOs = pTriInfos[f].os.subtract(n.mult(n.dot(pTriInfos[f].os)));
vOt = pTriInfos[f].ot.subtract(n.mult(n.dot(pTriInfos[f].ot)));
vOs.normalizeLocal();
vOt.normalizeLocal();
// original face number
iOF_1 = pTriInfos[f].orgFaceNumber;
iMembers = 0;
for (j = 0; j < pGroup.nrFaces; j++) {
// triangle number
final int t = pGroup.faceIndices.get(j);
final int iOF_2 = pTriInfos[t].orgFaceNumber;
// project
Vector3f vOs2 = pTriInfos[t].os.subtract(n.mult(n.dot(pTriInfos[t].os)));
Vector3f vOt2 = pTriInfos[t].ot.subtract(n.mult(n.dot(pTriInfos[t].ot)));
vOs2.normalizeLocal();
vOt2.normalizeLocal();
{
final boolean bAny = ((pTriInfos[f].flag | pTriInfos[t].flag) & GROUP_WITH_ANY) != 0;
// make sure triangles which belong to the same quad are joined.
final boolean bSameOrgFace = iOF_1 == iOF_2;
final float fCosS = vOs.dot(vOs2);
final float fCosT = vOt.dot(vOt2);
// sanity check
assert (f != t || bSameOrgFace);
if (bAny || bSameOrgFace || (fCosS > fThresCos && fCosT > fThresCos)) {
pTmpMembers[iMembers++] = t;
}
}
}
// sort pTmpMembers
tmp_group.nrFaces = iMembers;
tmp_group.triMembers = pTmpMembers;
if (iMembers > 1) {
quickSort(pTmpMembers, 0, iMembers - 1, INTERNAL_RND_SORT_SEED);
}
// look for an existing match
bFound = false;
l = 0;
while (l < iUniqueSubGroups && !bFound) {
bFound = compareSubGroups(tmp_group, pUniSubGroups[l]);
if (!bFound) {
++l;
}
}
// assign tangent space index
assert (bFound || l == iUniqueSubGroups);
// if no match was found we allocate a new subgroup
if (!bFound) {
// insert new subgroup
int[] pIndices = new int[iMembers];
pUniSubGroups[iUniqueSubGroups] = new SubGroup();
pUniSubGroups[iUniqueSubGroups].nrFaces = iMembers;
pUniSubGroups[iUniqueSubGroups].triMembers = pIndices;
System.arraycopy(tmp_group.triMembers, 0, pIndices, 0, iMembers);
//memcpy(pIndices, tmp_group.pTriMembers, iMembers*sizeof(int));
pSubGroupTspace[iUniqueSubGroups] = evalTspace(tmp_group.triMembers, iMembers, piTriListIn, pTriInfos, mikkTSpace, pGroup.vertexRepresentitive);
++iUniqueSubGroups;
}
// output tspace
{
final int iOffs = pTriInfos[f].tSpacesOffs;
final int iVert = pTriInfos[f].vertNum[index];
TSpace pTS_out = psTspace[iOffs + iVert];
assert (pTS_out.counter < 2);
assert (((pTriInfos[f].flag & ORIENT_PRESERVING) != 0) == pGroup.orientPreservering);
if (pTS_out.counter == 1) {
pTS_out.set(avgTSpace(pTS_out, pSubGroupTspace[l]));
// update counter
pTS_out.counter = 2;
pTS_out.orient = pGroup.orientPreservering;
} else {
assert (pTS_out.counter == 0);
pTS_out.set(pSubGroupTspace[l]);
// update counter
pTS_out.counter = 1;
pTS_out.orient = pGroup.orientPreservering;
}
}
}
iUniqueTspaces += iUniqueSubGroups;
}
return true;
}
use of com.jme3.scene.shape.Quad in project jmonkeyengine by jMonkeyEngine.
the class MikktspaceTangentGenerator method initTriInfo.
static void initTriInfo(TriInfo[] pTriInfos, final int[] piTriListIn, final MikkTSpaceContext mikkTSpace, final int iNrTrianglesIn) {
// generate neighbor info list
for (int f = 0; f < iNrTrianglesIn; f++) {
for (int i = 0; i < 3; i++) {
pTriInfos[f].faceNeighbors[i] = -1;
pTriInfos[f].assignedGroup[i] = null;
pTriInfos[f].os.x = 0.0f;
pTriInfos[f].os.y = 0.0f;
pTriInfos[f].os.z = 0.0f;
pTriInfos[f].ot.x = 0.0f;
pTriInfos[f].ot.y = 0.0f;
pTriInfos[f].ot.z = 0.0f;
pTriInfos[f].magS = 0;
pTriInfos[f].magT = 0;
// assumed bad
pTriInfos[f].flag |= GROUP_WITH_ANY;
}
}
// evaluate first order derivatives
for (int f = 0; f < iNrTrianglesIn; f++) {
// initial values
final Vector3f v1 = getPosition(mikkTSpace, piTriListIn[f * 3 + 0]);
final Vector3f v2 = getPosition(mikkTSpace, piTriListIn[f * 3 + 1]);
final Vector3f v3 = getPosition(mikkTSpace, piTriListIn[f * 3 + 2]);
final Vector3f t1 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 0]);
final Vector3f t2 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 1]);
final Vector3f t3 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 2]);
final float t21x = t2.x - t1.x;
final float t21y = t2.y - t1.y;
final float t31x = t3.x - t1.x;
final float t31y = t3.y - t1.y;
final Vector3f d1 = v2.subtract(v1);
final Vector3f d2 = v3.subtract(v1);
final float fSignedAreaSTx2 = t21x * t31y - t21y * t31x;
//assert(fSignedAreaSTx2!=0);
// eq 18
Vector3f vOs = d1.mult(t31y).subtract(d2.mult(t21y));
// eq 19
Vector3f vOt = d1.mult(-t31x).add(d2.mult(t21x));
pTriInfos[f].flag |= (fSignedAreaSTx2 > 0 ? ORIENT_PRESERVING : 0);
if (isNotZero(fSignedAreaSTx2)) {
final float fAbsArea = Math.abs(fSignedAreaSTx2);
final float fLenOs = vOs.length();
final float fLenOt = vOt.length();
final float fS = (pTriInfos[f].flag & ORIENT_PRESERVING) == 0 ? (-1.0f) : 1.0f;
if (isNotZero(fLenOs)) {
pTriInfos[f].os = vOs.multLocal(fS / fLenOs);
}
if (isNotZero(fLenOt)) {
pTriInfos[f].ot = vOt.multLocal(fS / fLenOt);
}
// evaluate magnitudes prior to normalization of vOs and vOt
pTriInfos[f].magS = fLenOs / fAbsArea;
pTriInfos[f].magT = fLenOt / fAbsArea;
// if this is a good triangle
if (isNotZero(pTriInfos[f].magS) && isNotZero(pTriInfos[f].magT)) {
pTriInfos[f].flag &= (~GROUP_WITH_ANY);
}
}
}
// force otherwise healthy quads to a fixed orientation
int t = 0;
while (t < (iNrTrianglesIn - 1)) {
final int iFO_a = pTriInfos[t].orgFaceNumber;
final int iFO_b = pTriInfos[t + 1].orgFaceNumber;
if (iFO_a == iFO_b) {
// this is a quad
final boolean bIsDeg_a = (pTriInfos[t].flag & MARK_DEGENERATE) != 0;
final boolean bIsDeg_b = (pTriInfos[t + 1].flag & MARK_DEGENERATE) != 0;
// DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false
if ((bIsDeg_a || bIsDeg_b) == false) {
final boolean bOrientA = (pTriInfos[t].flag & ORIENT_PRESERVING) != 0;
final boolean bOrientB = (pTriInfos[t + 1].flag & ORIENT_PRESERVING) != 0;
// if this happens the quad has extremely bad mapping!!
if (bOrientA != bOrientB) {
//printf("found quad with bad mapping\n");
boolean bChooseOrientFirstTri = false;
if ((pTriInfos[t + 1].flag & GROUP_WITH_ANY) != 0) {
bChooseOrientFirstTri = true;
} else if (calcTexArea(mikkTSpace, Arrays.copyOfRange(piTriListIn, t * 3 + 0, t * 3 + 3)) >= calcTexArea(mikkTSpace, Arrays.copyOfRange(piTriListIn, (t + 1) * 3 + 0, (t + 1) * 3 + 3))) {
bChooseOrientFirstTri = true;
}
// force match
{
final int t0 = bChooseOrientFirstTri ? t : (t + 1);
final int t1 = bChooseOrientFirstTri ? (t + 1) : t;
// clear first
pTriInfos[t1].flag &= (~ORIENT_PRESERVING);
// copy bit
pTriInfos[t1].flag |= (pTriInfos[t0].flag & ORIENT_PRESERVING);
}
}
}
t += 2;
} else {
++t;
}
}
// match up edge pairs
{
//Edge * pEdges = (Edge *) malloc(sizeof(Edge)*iNrTrianglesIn*3);
Edge[] pEdges = new Edge[iNrTrianglesIn * 3];
//TODO nehon weird... original algorithm check if pEdges is null but it's just been allocated... weirder, it does soemthing different if the edges are null...
// if (pEdges==null)
// BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn);
// else
// {
buildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn);
// }
}
}
use of com.jme3.scene.shape.Quad in project jmonkeyengine by jMonkeyEngine.
the class MikktspaceTangentGenerator method DegenEpilogue.
static void DegenEpilogue(TSpace[] psTspace, TriInfo[] pTriInfos, int[] piTriListIn, final MikkTSpaceContext mikkTSpace, final int iNrTrianglesIn, final int iTotTris) {
// punishment for degenerate triangles is O(N^2)
for (int t = iNrTrianglesIn; t < iTotTris; t++) {
// degenerate triangles on a quad with one good triangle are skipped
// here but processed in the next loop
final boolean bSkip = (pTriInfos[t].flag & QUAD_ONE_DEGEN_TRI) != 0;
if (!bSkip) {
for (int i = 0; i < 3; i++) {
final int index1 = piTriListIn[t * 3 + i];
// search through the good triangles
boolean bNotFound = true;
int j = 0;
while (bNotFound && j < (3 * iNrTrianglesIn)) {
final int index2 = piTriListIn[j];
if (index1 == index2) {
bNotFound = false;
} else {
++j;
}
}
if (!bNotFound) {
final int iTri = j / 3;
final int iVert = j % 3;
final int iSrcVert = pTriInfos[iTri].vertNum[iVert];
final int iSrcOffs = pTriInfos[iTri].tSpacesOffs;
final int iDstVert = pTriInfos[t].vertNum[i];
final int iDstOffs = pTriInfos[t].tSpacesOffs;
// copy tspace
psTspace[iDstOffs + iDstVert] = psTspace[iSrcOffs + iSrcVert];
}
}
}
}
// deal with degenerate quads with one good triangle
for (int t = 0; t < iNrTrianglesIn; t++) {
// other triangle is degenerate
if ((pTriInfos[t].flag & QUAD_ONE_DEGEN_TRI) != 0) {
byte[] pV = pTriInfos[t].vertNum;
int iFlag = (1 << pV[0]) | (1 << pV[1]) | (1 << pV[2]);
int iMissingIndex = 0;
if ((iFlag & 2) == 0) {
iMissingIndex = 1;
} else if ((iFlag & 4) == 0) {
iMissingIndex = 2;
} else if ((iFlag & 8) == 0) {
iMissingIndex = 3;
}
int iOrgF = pTriInfos[t].orgFaceNumber;
Vector3f vDstP = getPosition(mikkTSpace, makeIndex(iOrgF, iMissingIndex));
boolean bNotFound = true;
int i = 0;
while (bNotFound && i < 3) {
final int iVert = pV[i];
final Vector3f vSrcP = getPosition(mikkTSpace, makeIndex(iOrgF, iVert));
if (vSrcP.equals(vDstP)) {
final int iOffs = pTriInfos[t].tSpacesOffs;
psTspace[iOffs + iMissingIndex] = psTspace[iOffs + iVert];
bNotFound = false;
} else {
++i;
}
}
assert (!bNotFound);
}
}
}
use of com.jme3.scene.shape.Quad in project jmonkeyengine by jMonkeyEngine.
the class TerrainGridTileLoaderTest method simpleInitApp.
@Override
public void simpleInitApp() {
File file = new File("TerrainGridTestData.zip");
if (!file.exists()) {
assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
} else {
assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
}
this.flyCam.setMoveSpeed(100f);
ScreenshotAppState state = new ScreenshotAppState();
this.stateManager.attach(state);
// TERRAIN TEXTURE material
this.mat_terrain = new Material(this.assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md");
// Parameters to material:
// regionXColorMap: X = 1..4 the texture that should be appliad to state X
// regionX: a Vector3f containing the following information:
// regionX.x: the start height of the region
// regionX.y: the end height of the region
// regionX.z: the texture scale for the region
// it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
// slopeColorMap: the texture to be used for cliffs, and steep mountain sites
// slopeTileFactor: the texture scale for slopes
// terrainSize: the total size of the terrain (used for scaling the texture)
// GRASS texture
Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat);
this.mat_terrain.setTexture("region1ColorMap", grass);
this.mat_terrain.setVector3("region1", new Vector3f(88, 200, this.grassScale));
// DIRT texture
Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat);
this.mat_terrain.setTexture("region2ColorMap", dirt);
this.mat_terrain.setVector3("region2", new Vector3f(0, 90, this.dirtScale));
// ROCK texture
Texture rock = this.assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
rock.setWrap(WrapMode.Repeat);
this.mat_terrain.setTexture("region3ColorMap", rock);
this.mat_terrain.setVector3("region3", new Vector3f(198, 260, this.rockScale));
this.mat_terrain.setTexture("region4ColorMap", rock);
this.mat_terrain.setVector3("region4", new Vector3f(198, 260, this.rockScale));
this.mat_terrain.setTexture("slopeColorMap", rock);
this.mat_terrain.setFloat("slopeTileFactor", 32);
this.mat_terrain.setFloat("terrainSize", 129);
//quad.getHeightMap(), terrain.getLocalScale()), 0
AssetTileLoader grid = new AssetTileLoader(assetManager, "testgrid", "TerrainGrid");
this.terrain = new TerrainGrid("terrain", 65, 257, grid);
this.terrain.setMaterial(this.mat_terrain);
this.terrain.setLocalTranslation(0, 0, 0);
this.terrain.setLocalScale(2f, 1f, 2f);
// try {
// BinaryExporter.getInstance().save(terrain, new File("/Users/normenhansen/Documents/Code/jme3/engine/src/test-data/TerrainGrid/"
// + "TerrainGrid.j3o"));
// } catch (IOException ex) {
// Logger.getLogger(TerrainFractalGridTest.class.getName()).log(Level.SEVERE, null, ex);
// }
this.rootNode.attachChild(this.terrain);
TerrainLodControl control = new TerrainGridLodControl(this.terrain, getCamera());
// patch size, and a multiplier
control.setLodCalculator(new DistanceLodCalculator(65, 2.7f));
this.terrain.addControl(control);
final BulletAppState bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
this.getCamera().setLocation(new Vector3f(0, 256, 0));
this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
if (usePhysics) {
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
player3 = new CharacterControl(capsuleShape, 0.5f);
player3.setJumpSpeed(20);
player3.setFallSpeed(10);
player3.setGravity(10);
player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
bulletAppState.getPhysicsSpace().add(player3);
terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) {
}
public void tileAttached(Vector3f cell, TerrainQuad quad) {
while (quad.getControl(RigidBodyControl.class) != null) {
quad.removeControl(RigidBodyControl.class);
}
quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
bulletAppState.getPhysicsSpace().add(quad);
}
public void tileDetached(Vector3f cell, TerrainQuad quad) {
if (quad.getControl(RigidBodyControl.class) != null) {
bulletAppState.getPhysicsSpace().remove(quad);
quad.removeControl(RigidBodyControl.class);
}
}
});
}
this.initKeys();
}
use of com.jme3.scene.shape.Quad in project jmonkeyengine by jMonkeyEngine.
the class TestAnisotropicFilter method simpleInitApp.
@Override
public void simpleInitApp() {
maxAniso = renderer.getLimits().get(Limits.TextureAnisotropy);
flyCam.setDragToRotate(true);
flyCam.setMoveSpeed(100);
cam.setLocation(new Vector3f(197.02617f, 4.6769195f, -194.89545f));
cam.setRotation(new Quaternion(0.07921988f, 0.8992258f, -0.18292196f, 0.38943136f));
Quad q = new Quad(1000, 1000);
q.scaleTextureCoordinates(new Vector2f(1000, 1000));
Geometry geom = new Geometry("quad", q);
geom.rotate(-FastMath.HALF_PI, 0, 0);
geom.setMaterial(createCheckerBoardMaterial(assetManager));
rootNode.attachChild(geom);
inputManager.addMapping("higher", new KeyTrigger(KeyInput.KEY_1));
inputManager.addMapping("lower", new KeyTrigger(KeyInput.KEY_2));
inputManager.addListener(this, "higher");
inputManager.addListener(this, "lower");
}
Aggregations