当前位置: 首页 > 面试题库 >

Android相机,永不调用onPictureTaken(byte [] imgData,Camera相机)方法和PictureCallback

袁鸿雪
2023-03-14
问题内容

我有一个自定义的相机应用程序,可以预览SurfaceView上的相机视频输出并尝试拍照,应该通过“
xzing”扫描仪API处理图片以解码图像中的任何条形码。

我的应用可以正确预览,不会引发任何错误或期望, 但是我的onPictureTaken(byte [] imgData,Camera
camera)方法和PictureCallback从未被调用,因此无法获取图像并继续进行进一步的扫描。

下面是处理Camera逻辑的实际活动代码。 onPictureTaken(byte [] imgData,Camera
camera)方法和PictureCallback都在此类(ScanVinFromBarcodeActivity.java)中,参见blow:

package com.ty.tyownerspoc.barcode;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource; 
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.ty.tyownerspoc.R;

public class ScanVinFromBarcodeActivity extends Activity {

    private Camera globalCamera;
    private int cameraId = 0;
    private TextView VINtext = null;
    private View scanButton = null;
    // bitmap from camera
    private Bitmap bmpOfTheImageFromCamera = null;
    // global flag whether a camera has been detected
    private boolean isThereACamera = false;
    // surfaceView for preview object
    private FrameLayout frameLayoutBarcodeScanner = null;
    private CameraPreview newCameraPreview = null;
    private SurfaceView surfaceViewBarcodeScanner = null;
    private int counter = 0; 
    private volatile boolean finishedPictureTask  = false;
    /*
     * This method , finds FEATURE_CAMERA, opens the camera, set parameters ,
     * add CameraPreview to layout, set camera surface holder, start preview
     */
    private void initializeGlobalCamera() {
        try {
            if (!getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_CAMERA)) {
                Toast.makeText(this, "No camera on this device",
                        Toast.LENGTH_LONG).show();
            } else { // check for front camera ,and get the ID
                cameraId = findFrontFacingCamera();
                if (cameraId < 0) {

                    Toast.makeText(this, "No front facing camera found.",
                            Toast.LENGTH_LONG).show();
                } else {

                    Log.d("ClassScanViewBarcodeActivity",
                            "camera was found , ID: " + cameraId);
                    // camera was found , set global camera flag to true
                    isThereACamera = true;
                    // OPEN
                    globalCamera = Camera.open(cameraId);

                    // pass surfaceView to CameraPreview
                    newCameraPreview = new CameraPreview(this, globalCamera);
                    // pass CameraPreview to Layout
                    frameLayoutBarcodeScanner.addView(newCameraPreview);
                    try {
                        globalCamera
                                .setPreviewDisplay(surfaceViewBarcodeScanner
                                        .getHolder());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    // PREVIEW
                    globalCamera.startPreview();

                    Log.d("ClassScanViewBarcodeActivity",
                            "camera opened & previewing");
                }
            }// end else ,check for front camera
        }// end try
        catch (Exception exc) {

            // in case of exception release resources & cleanup
            if (globalCamera != null) {
                globalCamera.stopPreview();
                globalCamera.setPreviewCallback(null);
                globalCamera.release();
                globalCamera = null;

            }
            Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:",
                    exc.getMessage());
        }// end catch
    }

    // onCreate, instantiates layouts & surfaceView used for video preview
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_barcode_vin_scanner);
        Log.d("ClassScanViewBarcodeActivity", "onCreate ");

        // create surfaceView for previewing of camera image
        frameLayoutBarcodeScanner = (FrameLayout) findViewById(R.id.FrameLayoutForPreview);
        surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner);

        initializeGlobalCamera();

        // create text area & scan button
        VINtext = (TextView) findViewById(R.id.mytext);
        scanButton = findViewById(R.id.webbutton);
        // on click listener, onClick take a picture
        scanButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {

                    // if true take a picture
                    if (isThereACamera) {
                        Log.d("ClassScanViewBarcodeActivity",
                                "setOnClickListener() isThereACamera: "+ isThereACamera);

                        //set picture format to JPEG, everytime makesure JPEg callback is called 
                         Parameters parameters = globalCamera.getParameters();              
                         parameters.setPictureFormat(ImageFormat.JPEG);
                         globalCamera.setParameters(parameters);                         
                         //take pic , should call Callback 
                        globalCamera.takePicture(null, null, jpegCallback);
                        // wait 1 sec , than start preview again
                        Thread.sleep(1000);
                        //STOP
                        globalCamera.stopPreview();
                        //start previewing again onthe SurfaceView in case use wants to take another pic/scan
                        globalCamera.startPreview();

                    }

                }// end try
                catch (Exception exc) {

                    // in case of exception release resources & cleanup
                    if (globalCamera != null) {
                        globalCamera.stopPreview();
                        globalCamera.setPreviewCallback(null);
                        globalCamera.release();
                        globalCamera = null;

                    }
                    Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:",
                            exc.getMessage());
                }// end catch

            }// end on Click
        });// end OnClickListener() implementation

    }// end onCreate

    @Override
    protected void onResume() {

        Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:",
                String.valueOf(globalCamera));

        if (globalCamera != null) {
            // START PREVIEW
            globalCamera.startPreview();
        } else {
            initializeGlobalCamera();
        }

        super.onResume();
    }

    @Override
    protected void onStop() {

        if (globalCamera != null) {
            globalCamera.stopPreview();
            globalCamera.setPreviewCallback(null);
            globalCamera.release();
            globalCamera = null;
        }
        super.onStop();
    }

    //callback used by takePicture()
    PictureCallback jpegCallback = new PictureCallback() {



        public void onPictureTaken(byte[] imgData, Camera camera) {
            BinaryBitmap bitmap = null;
            try {



                Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

                //save image to sd card 
                savePicture(imgData);

                // get the bitmap from camera imageData
                bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
                        imgData, 0, imgData.length);


                if (bmpOfTheImageFromCamera != null) {
                    //Galaxy S3 , incorrect rotation issue rotate to correct rotation
                    Matrix matrix = new Matrix();
                    matrix.postRotate(90);
                    Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);
                    // convert bitmap to binary bitmap
                    bitmap = cameraBytesToBinaryBitmap(rotatedBitmap);


                    if (bitmap != null) {
                        // decode the VIN
                        String VIN = decodeBitmapToString(bitmap);
                        Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
                                VIN);
                        VINtext.setText(VIN);
                    } else {
                        Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

                    }
                } else {
                    Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
                            String.valueOf(bmpOfTheImageFromCamera));

                }
            }// end try

            catch (Exception exc) {
                exc.getMessage();

                Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
                        exc.getMessage());
            }

        }// end onPictureTaken()
    };// jpegCallback implementation


    /*
     * created savePicture(byte [] data) for testing 
     */
    public void savePicture(byte [] data)
    {
        Log.d( "ScanVinFromBarcodeActivity " , "savePicture(byte [] data)");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_"+counter+"_"+ date + ".jpg";

        File sdDir = Environment
                  .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);


        String filename =sdDir + File.separator + photoFile;

        File pictureFile = new File(filename);

        try {
          FileOutputStream fos = new FileOutputStream(pictureFile);
          fos.write(data);
          fos.close();

          Toast.makeText(this, "New Image saved:" + photoFile,
              Toast.LENGTH_LONG).show();

        } catch (Exception error) {
            Log.d( "File not saved: " , error.getMessage());
          Toast.makeText(this, "Image could not be saved.",
              Toast.LENGTH_LONG).show();
        }
        counter++;
      }



    private int findFrontFacingCamera() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                Log.d("ClassScanViewBarcodeActivity , findFrontFacingCamera(): ",
                        "Camera found");
                cameraId = i;
                break;
            }
        }
        return cameraId;
    }// end findFrontFacingCamera()

    @Override
    protected void onPause() {
        if (globalCamera != null) {
            globalCamera.stopPreview();
            globalCamera.setPreviewCallback(null);
            globalCamera.release();
            globalCamera = null;
        }
        super.onPause();
    }// end onPause()

    public String decodeBitmapToString(BinaryBitmap bitmap) {
        Reader reader = null;
        Result result = null;
        String textResult = null;
        try {

            reader = new MultiFormatReader();
            if (bitmap != null) {
                result = reader.decode(bitmap);
                if (result != null) {
                    textResult = result.getText();
                } else {
                    Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): result = ",
                            String.valueOf(result));
                }
            } else {
                Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): bitmap = ",
                        String.valueOf(bitmap));
            }
            /*
             * byte[] rawBytes = result.getRawBytes(); BarcodeFormat format =
             * result.getBarcodeFormat(); ResultPoint[] points =
             * result.getResultPoints();
             */

        } catch (NotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ChecksumException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }

        return textResult;
    }// end decodeBitmapToString (BinaryBitmap bitmap)

    public BinaryBitmap cameraBytesToBinaryBitmap(Bitmap bitmap) {
        BinaryBitmap binaryBitmap = null;
        if (bitmap != null) {

            int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
            bitmap.getPixels(pixels, 0, 0, bitmap.getWidth() - 1,
                    bitmap.getHeight() - 1, bitmap.getWidth(),
                    bitmap.getHeight());

            RGBLuminanceSource source = new RGBLuminanceSource(
                    bitmap.getWidth(), bitmap.getHeight(), pixels);

            HybridBinarizer bh = new HybridBinarizer(source);
            binaryBitmap = new BinaryBitmap(bh);
        } else {
            Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap): bitmap = ",
                    String.valueOf(bitmap));
        }

        return binaryBitmap;
    }

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    /*
     * The method getScreenOrientation() return screen orientation either
     * landscape or portrait. IF width < height , than orientation = portrait,
     * ELSE landscape For backwards compatibility we use to methods to detect
     * the orientation. The first method is for API versions prior to 13 or
     * HONEYCOMB.
     */
    public int getScreenOrientation() {

        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        // if API version less than 13
        Display getOrient = getWindowManager().getDefaultDisplay();
        int orientation = Configuration.ORIENTATION_UNDEFINED;

        if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
            // Do something for API version less than HONEYCOMB

            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else {
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else {
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        } else {
            // Do something for API version greater or equal to HONEYCOMB

            Point size = new Point();
            this.getWindowManager().getDefaultDisplay().getSize(size);
            int width = size.x;
            int height = size.y;

            if (width < height) {
                orientation = Configuration.ORIENTATION_PORTRAIT;
            } else {
                orientation = Configuration.ORIENTATION_LANDSCAPE;
            }
        }

        return orientation;

    }// end getScreenOrientation()
}// end class ScanVinFromBarcodeActivity

用于在SurfaceView上显示实时摄像头的Preview类(CameraPreview.java):

package com.ty.tyownerspoc.barcode;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.hardware.Camera.CameraInfo;

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements
        SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Context context;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        this.context = context;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the
        // preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {

        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
                Camera.Parameters p = mCamera.getParameters();

        // get width & height of the SurfaceView
        int SurfaceViewWidth = this.getWidth();
        int SurfaceViewHeight = this.getHeight();

        List<Size> sizes = p.getSupportedPreviewSizes();
         Size optimalSize = getOptimalPreviewSize(sizes, SurfaceViewWidth, SurfaceViewHeight);


        // set parameters
        p.setPreviewSize(optimalSize.width, optimalSize.height);

        /*rotate the image by 90 degrees clockwise , in order to correctly displayed the image , images seem to be -90 degrees (counter clockwise) rotated 
         * I even tried setting it to  p.setRotation(0); , but still no effect.
         */
        mCamera.setDisplayOrientation(90);

        mCamera.setParameters(p);

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e) {
            Log.d("CameraPreview ,  surfaceCreated() , orientation: ",
                    String.valueOf(e.getMessage()));
        }
    }// end surfaceChanged()
     static Size getOptimalPreviewSize(List <Camera.Size>sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            final double MAX_DOWNSIZE = 1.5;

            double targetRatio = (double) w / h;
            if (sizes == null) return null;

            Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            // Try to find an size match aspect ratio and size
            for (Camera.Size size : sizes) {
              double ratio = (double) size.width / size.height;
              double downsize = (double) size.width / w;
              if (downsize > MAX_DOWNSIZE) {
                //if the preview is a lot larger than our display surface ignore it
                //reason - on some phones there is not enough heap available to show the larger preview sizes
                continue;
              }
              if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
              if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
              }
            }
            // Cannot find the one match the aspect ratio, ignore the requirement
            //keep the max_downsize requirement
            if (optimalSize == null) {
              minDiff = Double.MAX_VALUE;
              for (Size size : sizes) {
                double downsize = (double) size.width / w;
                if (downsize > MAX_DOWNSIZE) {
                  continue;
                }
                if (Math.abs(size.height - targetHeight) < minDiff) {
                  optimalSize = size;
                  minDiff = Math.abs(size.height - targetHeight);
                }
              }
            }
            //everything else failed, just take the closest match
            if (optimalSize == null) {
              minDiff = Double.MAX_VALUE;
              for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                  optimalSize = size;
                  minDiff = Math.abs(size.height - targetHeight);
                }
              }
            }
            return optimalSize;
          }

}//end Preview class

“ ScanVinFromBarcodeActivity”活动的布局(activity_barcode_vin_scanner.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:padding="20dip" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:text="@string/decode_label"
        android:textColor="@color/mbackground1" />

    <TextView
        android:id="@+id/mytext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/mbackground2"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:textColor="@color/mytextcolor" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:text="@string/continue_label"
        android:textColor="@color/mytextcolor" />

    <Button
        android:id="@+id/webbutton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/web_button"
        android:textColor="@color/mytextcolor" />

    <FrameLayout
    android:id="@+id/FrameLayoutForPreview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1">

        <SurfaceView
            android:id="@+id/surfaceViewBarcodeScanner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </FrameLayout>
</LinearLayout>

任何帮助将不胜感激。

谢谢

Updated & working onTakePicturen method, the that works , the PictureCallback returns (stopPreview & StartPreview were moved to inside this method in its finally block).


    public void onPictureTaken(byte[] imgData, Camera camera) {
        BinaryBitmap bitmap;
        try {



            Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

            //save image to sd card 
            savePicture(imgData);

            // get the bitmap from camera imageData

            BitmapFactory.Options options = new BitmapFactory.Options();
              options.inSampleSize = 8; 
              //down sample
            bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
                    imgData, 0, imgData.length,options);


            if (bmpOfTheImageFromCamera != null) {

                Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): bmpOfTheImageFromCamera getByteCount(): ",
                        String.valueOf(bmpOfTheImageFromCamera.getByteCount()));
                //Galaxy S3 , incorrect rotation issue rotate to correct rotation
                /*Matrix matrix = new Matrix();
                matrix.postRotate(90);
                Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);*/
                // convert bitmap to binary bitmap
                bitmap = cameraBytesToBinaryBitmap(bmpOfTheImageFromCamera);


                if (bitmap != null) {
                    // decode the VIN
                    String VIN = decodeBitmapToString(bitmap);
                    Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
                            VIN);
                    VINtext.setText(VIN);
                } else {
                    Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

                }
            } else {
                Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
                        String.valueOf(bmpOfTheImageFromCamera));

            }


        }// end try

        catch (Exception exc) {
            exc.getMessage();

            Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
                    exc.getMessage());
        }

        finally
        {
            globalCamera.stopPreview();
            //start previewing again onthe SurfaceView in case use wants to take another pic/scan
            globalCamera.startPreview();
        }

    }// end onPictureTaken()
};// jpegCallback implementation

问题答案:

我唯一可能发现的原因是您在jpegCallback返回之前再次启动了预览。根据javadoc,这是不允许的:

调用此方法后,在返回JPEG回调之前,您不得调用startPreview()或拍摄其他图片。

The callback is actually put on the UI thread queue - which will be suspended
in your Thread.sleep() and the same thread will have called stopPreview()
and startPreview() before actually coming to the callback. Generally
speaking, if you call Thread.sleep() on the UI thread - you’re doing it
wrong. So, hopefully if you remove the sleep() and put what comes after it
in the jpegCallback your problem should be solved.



 类似资料:
  • 相机控制了场景的观察视角。有很多相机操控方法,比如旋转、缩放、平移以及飞行定位。Cesium默认支持使用鼠标和触摸事件控制相机。Cesium也提供了一套可编程的相机控制API。这篇教程就是介绍相机相关知识,以及API。 快速开始 开始示例。打开Sandcastle的 Hello World 示例。默认场景按照下述方式处理鼠标和处理事件: 左键单击和拖拽 – 沿着地球表面平移(调整相机位置). 右键

  • 玩家看到的 3D 游戏世界,就是游戏制作中 相机(Camera) 对象查看到的场景,就如,观众看一部电影,看到的是电影拍摄时相机查看到的现实世界。游戏制作中的相机与电影拍摄时的相机作用是一样的。Camera 对象继承了 Node 对象,因此 Camera 支持大多数 Action。 相机有两种,一种是透视相机,一种是正交相机。透视相机看到的游戏世界具有远近效果,像这样: 就好像眼睛观察现实世界,近

  • CesiumJS中的Camera控制场景的视图。有很多方法可以操作Camera,如旋转(rotate)、缩放(zoom)、平移(pan)和飞到目的地(flyTo)。CesiumJS有鼠标和触摸事件用来处理与Camrea的交互,还有API来以编程方式操作摄像机。了解如何使用Camera API和自定义相机控制(Camera controls)。 默认Camera行为 打开Sandcastle中的He

  • 为了展现我们的无人机飞行,让我们用相机模式进行实验。我们将保持简单的两个基本的相机模式,用户可以切换之间。 Free Mode : 默认相机控制。 Drone Mode : 让相机跟随无人机通过飞行在一个固定的距离。 自由模式不需要代码,因为它使用默认控件。至于无人机跟随模式,我们可以使用摄像机的内置实体跟踪功能来定位摄像机,并用偏移量定位无人机。这就使得相机即使在移动时也能从指定的实体中得到固定

  • 本文向大家介绍Android 相机相册权限设置方法,包括了Android 相机相册权限设置方法的使用技巧和注意事项,需要的朋友参考一下 在AndroidManifest.xml中设置相机和相册的权限, 以上这篇Android 相机相册权限设置方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。