I have two java files:
when i rotate the sphere horizontally, the chasecamera works correctly.
But when i rotate the sphere vertically, the chasecamera works wrongly sometimes.
The three axes from one side to another side suddenly.
The first one is :
public class CustomSphereTest extends SimpleApplication {
public boolean updateState = false; //用户点击按钮后,需要更新导航校正三维展示球
CustomSphereStateTest state = null;
public static void main(String[] args) {
CustomSphereTest app = new CustomSphereTest();
app.start();
}
@Override
public void simpleInitApp() {
flyCam.setEnabled(false);
// chaseCam.setInvertVerticalAxis(true);
// chaseCam.setDragToRotate(true);
// chaseCam.setSmoothMotion(true);
ChaseCamera chaseCam = new ChaseCamera(cam, rootNode, inputManager);
chaseCam.setRotationSpeed(7); //Rubby 默认速度为1很慢,需要更快的。
chaseCam.setMinDistance(1f); //camera 与 the target 之间距离。(此值越小,说明越可以放大).否则使用默认值,有时候无法继续缩放,扩大
chaseCam.setMaxDistance(1000f); //camera 与 the target 之间距离。(此值越大,说明越可以缩小).否则使用默认值,有时候无法继续缩放,扩大
chaseCam.setMinVerticalRotation(-FastMath.PI*2);
chaseCam.setMaxVerticalRotation(FastMath.PI*2); //可以旋转的最大角度
// chaseCam.setDownRotateOnCloseViewOnly(false);
//light
AmbientLight ambient = new AmbientLight();
rootNode.addLight(ambient);
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(1.4f, -1.4f, -1.4f));
rootNode.addLight(sun);
//Real...
state = new CustomSphereStateTest(1.0f);
this.stateManager.attach(state);
}
@Override
public void simpleUpdate(float tpf) {
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
}
The second one is:
public class CustomSphereStateTest extends AbstractAppState{
private SimpleApplication app;
private Camera cam;
private Node rootNode;
private AssetManager assetManager;
BitmapFont guiFont;
//属性值
private boolean isThreeAxes = false; //是否是三轴坐标系
private ColorRGBA otherColor = ColorRGBA.White;
private ColorRGBA colorX = ColorRGBA.Red; //JME3坐标系中X轴
private ColorRGBA colorY = ColorRGBA.Green; //JME3坐标系中Y轴
private ColorRGBA colorZ = ColorRGBA.Blue; //JME3坐标系中Z轴
public static final int Axis_X =1; //JME3坐标系中X轴
public static final int Axis_Y =2; //JME3坐标系中Y轴
public static final int Axis_Z =3; //JME3坐标系中Z轴
float xStep = -1.0f; //初始为无效值
float yStep = -1.0f;
float zStep = -1.0f;
float markOffset =0.2f; //坐标轴上的标记,偏移大小
float textOffset =0.6f; //坐标轴上文字 偏移大小
float textSize = 0.4f; //文字的字体大小
float radius; //用户传入的半径值,此值太大,会影响显示
float scale; //需要将用户传入的半径值进行缩放,使之永远位于0~10之间
//TODO 记录用户传入的数据点值[],并进行缩放
public boolean isIsThreeAxes() {
return isThreeAxes;
}
public void setIsThreeAxes(boolean isThreeAxes) {
this.isThreeAxes = isThreeAxes;
}
public ColorRGBA getOtherColor() {
return otherColor;
}
public void setOtherColor(ColorRGBA otherColor) {
this.otherColor = otherColor;
}
public ColorRGBA getColorX() {
return colorX;
}
public void setColorX(ColorRGBA colorX) {
this.colorX = colorX;
}
public ColorRGBA getColorY() {
return colorY;
}
public void setColorY(ColorRGBA colorY) {
this.colorY = colorY;
}
public ColorRGBA getColorZ() {
return colorZ;
}
public void setColorZ(ColorRGBA colorZ) {
this.colorZ = colorZ;
}
public float getxStep() {
return xStep;
}
public void setxStep(float xStep) {
this.xStep = xStep;
}
public float getyStep() {
return yStep;
}
public void setyStep(float yStep) {
this.yStep = yStep;
}
public float getzStep() {
return zStep;
}
public void setzStep(float zStep) {
this.zStep = zStep;
}
public float getMarkOffset() {
return markOffset;
}
public void setMarkOffset(float markOffset) {
this.markOffset = markOffset;
}
public float getTextOffset() {
return textOffset;
}
public void setTextOffset(float textOffset) {
this.textOffset = textOffset;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
public float getRadius() {
return radius*scale;
}
public void setRadius(float inRadius) {
this.radius = 8.0f;
this.scale = inRadius/this.radius;
}
public CustomSphereStateTest( float inRadius){
super();
setRadius(inRadius);
}
@Override
public void initialize(AppStateManager stateManager, Application app) {//将此加入到StateManager才会调用此函数初始化
super.initialize(stateManager, app); //To change body of generated methods, choose Tools | Templates.
this.app = (SimpleApplication)app;
this.cam = this.app.getCamera();
this.rootNode = this.app.getRootNode();
this.assetManager = this.app.getAssetManager();
guiFont = this.assetManager.loadFont("Interface/Fonts/Default.fnt");
//创建模型
this.createColoredSphere(16,32,radius );//半径为5
this.createAxes(2*radius); //坐标轴为2*5
}
@Override
public void update(float tpf) {
super.update(tpf); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void cleanup() {
super.cleanup(); //To change body of generated methods, choose Tools | Templates.
rootNode.detachAllChildren();
}
private void createColoredSphere(int zSamples,int radialSamples,float radius ){
Sphere b = new Sphere( zSamples, radialSamples, radius);
Geometry geom = new Geometry("Sphere", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.White);
// mat.setBoolean("VertexColor", true); //Rubby 顶点作色
//mat.getAdditionalRenderState().setWireframe(true); //显示三角形线框
// setColorData(b,zSamples,radialSamples); //TODO 顶点作色的数据,新的可能并不需要
geom.setMaterial(mat);
//TODO 用户可以控制是否开启 三角线框的展示
Sphere b2= new Sphere( zSamples, radialSamples, radius);
// b2.setMode(Mesh.Mode.Triangles);
Geometry geom2= new Geometry("Sphere2", b2);
Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
ColorRGBA gray = new ColorRGBA(0.3f,0.3f,0.3f,0.3f);
mat2.setColor("Color", gray);
mat2.getAdditionalRenderState().setWireframe(true); //显示三角形线框
geom2.setMaterial(mat2);
// BoundingSphere bs = new BoundingSphere(radius, new Vector3f(0.0f,0.0f,0.0f));
rootNode.attachChild(geom2);
rootNode.attachChild(geom);
}
//创建坐标轴:按照jme3的坐标系
private void createAxes(float length){ //length 是2*radius的值
Vector3f [] vertices = new Vector3f[4];
float half = length/2.0f;
vertices[0] = new Vector3f(-half,-half,-half); //坐标轴原点 (-5,-5,-5)
vertices[1] = new Vector3f(half,-half,-half);//x(JME3)
vertices[2] = new Vector3f(-half,half,-half);//Y(JME3)
vertices[3] = new Vector3f(-half,-half,half);//Z(JME3)
Line x = new Line( vertices[0], vertices[1]);
Line y = new Line( vertices[0], vertices[2]);
Line z = new Line( vertices[0], vertices[3]);
//先创建三个轴. 创建markLine,创建mark text,创建名称(X,Y,Z)
Geometry geomX = new Geometry("LineX", x);
Material matX = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matX.setColor("Color", ColorRGBA.Red);
geomX.setMaterial(matX);
rootNode.attachChild(geomX);
createMarkLine(vertices[0],vertices[1],CustomSphereStateTest.Axis_X);
Geometry geomY = new Geometry("LineY", y);
Material matY = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matY.setColor("Color", ColorRGBA.Green);
geomY.setMaterial(matY);
rootNode.attachChild(geomY);
createMarkLine(vertices[0],vertices[2],CustomSphereStateTest.Axis_Y);
Geometry geomZ = new Geometry("LineZ", z);
Material matZ = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matZ.setColor("Color", ColorRGBA.Blue);
geomZ.setMaterial(matZ);
rootNode.attachChild(geomZ);
createMarkLine(vertices[0],vertices[3],CustomSphereStateTest.Axis_Z);
//其它九条轴
if(isThreeAxes == false){
//line1
Vector3f a = new Vector3f(-half,-half,half);
Vector3f b = new Vector3f(half,-half,half);
Geometry geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line2
a = new Vector3f(half,-half,half);
b = new Vector3f(half,-half,-half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line3
a = new Vector3f(-half,half,half);
b = new Vector3f(-half,-half,half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);;
//line4
a = new Vector3f(half,-half,half);
b = new Vector3f(half,half,half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line5
a = new Vector3f(half,-half,-half);
b = new Vector3f(half,half,-half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line6
a = new Vector3f(-half,half,half);
b = new Vector3f(-half,half,-half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line7
a = new Vector3f(-half,half,half);
b = new Vector3f(half,half,half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line8
a = new Vector3f(half,half,half);
b = new Vector3f(half,half,-half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
//line9
a = new Vector3f(half,half,-half);
b = new Vector3f(-half,half,-half);
geom = createLine(a,b,otherColor);
rootNode.attachChild(geom);
}
}
private Geometry createLine(Vector3f a, Vector3f b, ColorRGBA color){
Line line = new Line( a, b);
Geometry geom = new Geometry("Axes-others", line);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
geom.setMaterial(mat);
return geom;
}
private void createMarkLine(Vector3f start,Vector3f end,int type){
if(CustomSphereStateTest.Axis_X == type){
float xStart =start.x;
float xEnd = end.x;
if(this.xStep<0){
this.xStep = (end.x)/2;
}
float index = xStart;
float y = start.y;
float z = start.z;
for(;index <=0.0;index= index+this.xStep){
Vector3f a = new Vector3f(index,y,z);
Vector3f b = new Vector3f(index,y,z-this.markOffset);
Geometry geom = this.createLine(a,b, colorX);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(index,y,z-this.textOffset));
this.rootNode.attachChild(bitmapText);
}
index =0;
for(;index <=xEnd;index= index+this.xStep){
Vector3f a = new Vector3f(index,y,z);
Vector3f b = new Vector3f(index,y,z-this.markOffset);
Geometry geom = this.createLine(a,b, colorX);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(index,y,z-this.textOffset));
this.rootNode.attachChild(bitmapText);
}
}else if(CustomSphereStateTest.Axis_Y == type){
float yStart =start.y;
float yEnd = end.y;
if(this.yStep<0){
this.yStep = (end.y)/2;
}
float index = yStart;
float x = start.x;
float z = start.z;
for(;index <=0.0;index= index+this.yStep){
Vector3f a = new Vector3f(x,index,z);
Vector3f b = new Vector3f(x-this.markOffset,index,z);
Geometry geom = this.createLine(a,b, colorY);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(x-this.textOffset,index+0.5f,z));//由于怕坐标轴标记重叠,所以Y轴标记往上移动0.3
this.rootNode.attachChild(bitmapText);
}
index =0;
for(;index <=yEnd;index= index+this.xStep){
Vector3f a = new Vector3f(x,index,z);
Vector3f b = new Vector3f(x-this.markOffset,index,z);
Geometry geom = this.createLine(a,b, colorY);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(x-this.textOffset,index+0.5f,z));
this.rootNode.attachChild(bitmapText);
}
}else if(CustomSphereStateTest.Axis_Z == type){
//由于用户坐标系问题,所以Z轴的marktext 要取反
float zStart =start.z;
float zEnd = end.z;
if(this.zStep<0){
this.zStep = (end.z)/2;
}
float index = zStart;
float x = start.x;
float y = start.y;
for(;index <=0.0;index= index+this.zStep){
Vector3f a = new Vector3f(x,y,index);
Vector3f b = new Vector3f(x-this.markOffset,y,index);
Geometry geom = this.createLine(a,b, colorZ);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(x-this.textOffset,y,index));
this.rootNode.attachChild(bitmapText);
}
index =0;
for(;index <=zEnd;index= index+this.zStep){
Vector3f a = new Vector3f(x,y,index);
Vector3f b = new Vector3f(x-this.markOffset,y,index);
Geometry geom = this.createLine(a,b, colorZ);
this.rootNode.attachChild(geom);
BitmapText bitmapText =this.createBitmapText(index*this.scale+"", new Vector3f(x-this.textOffset,y,index));
this.rootNode.attachChild(bitmapText);
}
}
}
private BitmapText createBitmapText(String str, Vector3f location){
BitmapText text = new BitmapText(guiFont);
text.setText(str);
text.setSize(textSize);//TODO 文本字体大小
text.setLocalTranslation(location); //将其转移到指定位置
//让其始终面向屏幕.否则会看不到
BillboardControl control = new BillboardControl();
text.addControl(control);
return text;
}
private void setColorData(Sphere sphere ,int zSamples,int radialSamples) {
int triCount;
triCount = 2 * (zSamples - 2) * radialSamples+2; //这么多个三角形+2
int vertCount = (zSamples - 2) * (radialSamples + 1) + 2; //顶点数目
float[] colorArray = new float[vertCount*4];
int colorIndex =0;
for(int i=0; i<zSamples - 2; i++){ //红色渐渐加强
for(int j=0; j<radialSamples + 1;j++){
colorArray[colorIndex++] = ( 1.0f/(zSamples-2) )*i;
colorArray[colorIndex++]= 0.0f;
colorArray[colorIndex++]= 0.0f;
colorArray[colorIndex++]= 1.0f;
}
}
// south pole triangles: green // Z为-radius
{
colorArray[colorIndex++] = 0.0f;
colorArray[colorIndex++]= 1.0f;
colorArray[colorIndex++]= 0.0f;
colorArray[colorIndex++]= 1.0f;
}
// north pole triangles: blue // Z为+radius
{
colorArray[colorIndex++] = 0.0f;
colorArray[colorIndex++]= 0.0f;
colorArray[colorIndex++]= 1.0f;
colorArray[colorIndex++]= 1.0f;
}
sphere.setBuffer(VertexBuffer.Type.Color, 4, colorArray); //每个颜色有4个float值。
}
}