Unity calls the C++ dll and then returns the array to C++

Basic data type int, float----just pass it directly

If it is int[], float[] can also be passed directly

C# string can be used for C++, etc., refer to

C++ dll file

// SPDX-License-Identifier: MIT
// Copyright (c) 2021 Manuel Stoiber, German Aerospace Center (DLR)

//#include <srt3d/azure_kinect_camera.h>
#define _CRT_SECURE_NO_WARNINGS //VS中必须定义,否则报错
#include <srt3d/my_camera.h>
#include <srt3d/camera.h>
#include <srt3d/body.h>
#include <srt3d/common.h>
#include <srt3d/normal_viewer.h>
#include <srt3d/occlusion_renderer.h>
#include <srt3d/region_modality.h>
#include <srt3d/renderer_geometry.h>
#include <srt3d/tracker.h>
#include <cmath>
#include <Eigen/Geometry>
#include <filesystem>
#include <memory>
#include <string>
#include <Windows.h>
#include <srt3d/ReConfig.h>
#include <ctime>


//Generate body1 template view 2562 of 2562

//global variables
//read config files
RF::RrConfig config;
std::string model_dir, geometry_path, model_bin;
std::ofstream os;     //创建一个文件输出流对象
time_t t = time(nullptr);
struct tm* now = localtime(&t);


extern "C" __declspec(dllexport)
bool readConfigFiles(char* path_ini)
{
	//std::string path_ini_string(path_ini);
	//os.open("D:\\sourcecode\\STR3D\\build\\examples\\log.txt");//将对象与文件关联
	//os << asctime(now) << path_ini_string << std::endl;
	//os << asctime(now) << path_ini << std::endl;
	//os << asctime(now) << path_ini[0] << std::endl;


	//bool configisOk = config.ReadConfig("D:\\BUFFER\\Unity\\DLLProject01\\Assets\\Plugins\\config.ini");  //the should be to transfer unity
	bool configisOk = config.ReadConfig(path_ini);  //the should be to transfer unity
	if (configisOk == false) {
		printf("ReadConfig is Error,Cfg=%s", "config.ini");
		return false;
	}
	model_dir = config.ReadString("configuration", "model_dir", "");
	//int Port = config.ReadInt("MYSQL", "Port", 0);
	geometry_path = config.ReadString("configuration", "geometry_path", "");
	model_bin = config.ReadString("configuration", "model_bin", "");

	//os << asctime(now) << model_dir << std::endl;
	//os << asctime(now) << geometry_path << std::endl;
	//os << asctime(now) << model_bin << std::endl;
	//os.close();

	return true;
}

//const std::filesystem::path model_directory{ model_dir };

constexpr bool kSaveViewerImage = false;
const std::filesystem::path viewer_save_directory{ "D:\\sourcecode\\STR3D\\SRT3D\\images\\" };

 Set up tracker and renderer geometry
auto tracker_ptr{ std::make_shared<srt3d::Tracker>("tracker") };
auto renderer_geometry_ptr{ std::make_shared<srt3d::RendererGeometry>("renderer geometry") };

 Set up camera

auto camera_ptr{ std::make_shared < srt3d::MyCamera>("RGB") };
 Set up viewers

auto viewer_ptr{ std::make_shared<srt3d::NormalViewer>("viewer", camera_ptr, renderer_geometry_ptr) };


 Set up body1 (change accordingly)
//const std::filesystem::path body1_geometry_path{ "D:\\sourcecode\\STR3D\\rbotdataset\\motorpart01.obj" };
const std::filesystem::path body1_geometry_path{ geometry_path };

srt3d::Transform3fA body1_geometry2body_pose{ Eigen::Translation3f(0.0f, 0.0f, 0.0f) };
auto body1_ptr{ std::make_shared<srt3d::Body>("body1", body1_geometry_path, 0.001f, true, false, 0.3f, body1_geometry2body_pose, 1) };


srt3d::Transform3fA body1_world2body_pose;
srt3d::Transform3fA realtime_myObj2world_pose;
float location[7] = { 0,0, 0, 0,0, 0, 0};



exe程序
extern "C" __declspec(dllexport)
void main()
{

	auto body_ptr{ std::make_shared<srt3d::Body>("body1", geometry_path, 0.001f, true, false, 0.3f, body1_geometry2body_pose, 1) };
	body1_ptr = body_ptr;


	//body1_world2body_pose.matrix() <<
	//	1.0f, 0.0f, 0.0f, 0.095f,
	//	0.0f, 1.0f, 0.0f, 0.1f,
	//	0.0f, 0.0f, 1.0f, -0.4f,
	//	0.0f, 0.0f, 0.0f, 1.0f;


	body1_world2body_pose.matrix() <<
		1.0f, 0.0f, 0.0f, 0.1f,
		0.0f, 1.0f, 0.0f, 0.05f,
		0.0f, 0.0f, 1.0f, -0.3f,
		0.0f, 0.0f, 0.0f, 1.0f;

	tracker_ptr->AddViewer(viewer_ptr);

	if (kSaveViewerImage) viewer_ptr->StartSavingImages(viewer_save_directory);


	//body1_ptr->set_body2world_pose(body1_world2body_pose);
	body1_ptr->set_world2body_pose(body1_world2body_pose);//原论文code
	renderer_geometry_ptr->AddBody(body1_ptr);


	// Set up model body 1
	//auto body1_model_ptr{ std::make_shared<srt3d::Model>("body1_model", body1_ptr, model_directory, "motorpart01_model.bin") };
	//auto body1_model_ptr{ std::make_shared<srt3d::Model>("body1_model", body1_ptr, model_directory, model_bin) };
	auto body1_model_ptr{ std::make_shared<srt3d::Model>("body1_model", body1_ptr, model_dir, model_bin) };

	//os << asctime(now) << "geometry_path:" << geometry_path << std::endl;   //将输入的内容放入txt文件中
	//os << asctime(now) << "model_directory:" << model_dir << std::endl;
	//os << asctime(now) << "model_bin:" << model_bin << std::endl;  
	//const std::filesystem::path test{ "D:\\sourcecode\\STR3D\\rbotdataset\\motorpart01.obj" };
	//os << asctime(now) << "test " << test << std::endl;
	//os.close();

	// Set up region modality body 1
	auto body1_region_modality_ptr{ std::make_shared<srt3d::RegionModality>(
		"body1_region_modality", body1_ptr, body1_model_ptr, camera_ptr) };
	tracker_ptr->AddRegionModality(body1_region_modality_ptr);

	// Set up occlusion renderer
	auto occlusion_renderer_ptr{ std::make_shared<srt3d::OcclusionRenderer>(
		"occlusion_renderer", renderer_geometry_ptr, camera_ptr) };
	body1_region_modality_ptr->UseOcclusionHandling(occlusion_renderer_ptr);

	 Start tracking
	tracker_ptr->SetUpTracker();
	//tracker_ptr->StartTracker(false);
	//float pos_value[3] = {1., 2.8, 2.33};
	//tracker_ptr->StartTracker(false, pos_value);
	//tracker_ptr->StartTracker(false, body1_ptr, &a);
	// 
	if (!tracker_ptr->set_up()) {
		std::cerr << "Set up tracker " << tracker_ptr->set_name() << " first" << std::endl;
		return;
	}
	tracker_ptr->set_start_tracking(false);

}


//将旋转矩阵转化为四元数
Eigen::Quaterniond Matrix2Quaternion(Eigen::Matrix<float, 4, 4> matrixofBody)
{

	Eigen::Matrix<float, 4, 4> matrix_body2world_pose;
	//Eigen::Matrix<float, 3, 3> matrix_rotation;
	Eigen::Matrix3d matrix_rotation;

	//Eigen::Quaterniond matrix_quarternion;

	matrix_body2world_pose = matrixofBody;
	//matrix_body2world_pose = body1_ptr->body2world_pose().matrix();

	//body1_ptr->geometry2world_pose().matrix();
	//for (size_t i = 0; i < 4; i++)
	//{
	//	for (size_t j = 0; j < 4; j++)
	//	{
	//		std::cout << matrix_body2world_pose(i, j) << "\t";
	//	}

	//}

	//取出旋转矩阵
	for (size_t i = 0; i < 3; i++)
	{
		for (size_t j = 0; j < 3; j++)
		{
			matrix_rotation(i, j) = matrix_body2world_pose(i, j);
		}
	}

	//std::cout << "---------------matrix_quarternion-----------------" << std::endl;
	std::cout << matrix_quarternion << std::endl;
	//std::cout << matrix_quarternion.x() << "\t" <<matrix_quarternion.y() << "\t"  
	//	<< matrix_quarternion.z() << "\t" << matrix_quarternion.z() << "\t" << std::endl;

	return Eigen::Quaterniond(matrix_rotation);
}

Eigen::Quaterniond matrix_quarternion;
Eigen::Matrix<float, 4, 4> matrix_body2world_pose;
cv::Mat frameRGB, horizonalFlip;

extern "C" __declspec(dllexport)
int start_track(int iteration, float* pos_array, bool* update, uchar * texturePtr, float pos_rt[7])
//int start_track(int iteration, float* pos_array, bool* update, uchar* texturePtr, float x, float y, float z, float w, float pos_x, float pos_y, float pos_z)
//int start_track(int iteration, float* pos_array, bool* update, float pos_z)

{
	/// <summary>
/// For unity dll test
/// </summary>
/// <param name="pos_array"></param>
/// <returns></returns>
 	

		if (tracker_ptr->get_start_tracking())
		{
			if (!tracker_ptr->StartRegionModalities())
			{
				return -1;
			}
			tracker_ptr->set_tracking_started(true);
			tracker_ptr->set_start_tracking(false);

			//std::cout << "StartRegionModalities" << std::endl;
		}
		if (tracker_ptr->get_tracking_started())
		{
			//std::cout << "--------------------------------" << std::endl;
			//std::cout << body1_ptr->body2world_pose().matrix() << std::endl;

			//当物体追踪后实时更新将我们的旋转和平移传给unity
			matrix_body2world_pose = body1_ptr->body2world_pose().matrix();
			matrix_quarternion = Matrix2Quaternion(matrix_body2world_pose);


			//右手坐标转化为左手坐标 x,z取反
			保存表示旋转的四元数和平移的值
			float location[7] = { -matrix_quarternion.x(), matrix_quarternion.y(), -matrix_quarternion.z(), matrix_quarternion.w(),
									matrix_body2world_pose(0, 3), -matrix_body2world_pose(1, 3),matrix_body2world_pose(2, 3) };
			memcpy(pos_array, location, sizeof(float) * 7);

			std::cout << "---------------------translation-----------------------------" << std::endl;
			std::cout << matrix_body2world_pose(0, 3) << "\t" << matrix_body2world_pose(1, 3) << "\t" << matrix_body2world_pose(2, 3) << std::endl;
			

			//控制unity3d 进程的退出
			int update_is[2] = { tracker_ptr->get_update(), 0 };
			memcpy(update, update_is, sizeof(int)*2);


			//将相机图片传给unity
			cv::flip(camera_ptr->image(), horizonalFlip, 1);
			cv::cvtColor(horizonalFlip, frameRGB, cv::COLOR_BGR2RGB);
			memcpy(texturePtr, frameRGB.data, frameRGB.cols * frameRGB.rows * frameRGB.channels() * sizeof(uchar));

			if (!tracker_ptr->ExecuteTrackingCycle(iteration))
			{
				std::cout << "ExecuteTrackingCycle--break" << std::endl;
				int update_is[2] = { tracker_ptr->get_update(), 2 };
				memcpy(update, update_is, sizeof(int) * 2);
				return -1;
			}
		}
		else
		{
			//传unity物体最初的位置
			//程序开始后将初始化的旋转和平移传给unity
			if (!tracker_ptr->get_update())
			{

				matrix_body2world_pose = body1_ptr->body2world_pose().matrix();
				matrix_quarternion = Matrix2Quaternion(matrix_body2world_pose);
				float location[7] = { -matrix_quarternion.x(), matrix_quarternion.y(), -matrix_quarternion.z(), matrix_quarternion.w(),
						  matrix_body2world_pose(0, 3), -matrix_body2world_pose(1, 3),matrix_body2world_pose(2, 3) };
				memcpy(pos_array, location, sizeof(float) * 7);

			}
			else //程序开始后将按下r后旋转和平移传给unity
			{

				
				int update_is[2] = { tracker_ptr->get_update(), 1 };
				memcpy(update, update_is, sizeof(int) * 2);  //控制unity3d 进程的退出

				接收unity中的物体位姿
				float pos_x = pos_rt[0];
				float pos_y = pos_rt[1];
				float pos_z = pos_rt[2];
				float x = pos_rt[3];
				float y = pos_rt[4];
				float z = pos_rt[5];
				float w = pos_rt[6];

				Eigen::Quaterniond quat_u3d(w, x, y, z);

				Eigen::Matrix3d rotation_matrix = quat_u3d.matrix();

				for (size_t i = 0; i < 3; i++)
				{
					for (size_t j = 0; j < 3; j++)
					{
						body1_world2body_pose.matrix()(i, j) = rotation_matrix.matrix()(i, j);
					}
				}

				body1_world2body_pose.matrix()(0, 3) = pos_x;
				body1_world2body_pose.matrix()(1, 3) = pos_y;
				body1_world2body_pose.matrix()(2, 3) = pos_z;

				body1_world2body_pose.matrix()(3, 0) = 0;
				body1_world2body_pose.matrix()(3, 1) = 0;
				body1_world2body_pose.matrix()(3, 2) = 0;
				body1_world2body_pose.matrix()(3, 3) = 1;

				body1_ptr->set_body2world_pose(body1_world2body_pose);
			}


			//将相机图片传给unity
			cv::flip(camera_ptr->image(), horizonalFlip, 1);
			cv::cvtColor(horizonalFlip, frameRGB, cv::COLOR_BGR2RGB);
			memcpy(texturePtr, frameRGB.data, frameRGB.cols * frameRGB.rows * frameRGB.channels() * sizeof(uchar));

			if (!tracker_ptr->ExecuteViewingCycle(iteration))
			{
				//控制unity3d 进程的退出
				int update_is[2] = { tracker_ptr->get_update(), 2 };
				memcpy(update, update_is, sizeof(int)*2);
				return -1;
			}
		}
	

	return 0;
}


unity

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System;

public class useDll : MonoBehaviour
{

    [DllImport("run_on_camera_sequence")]
    static extern bool readConfigFiles(string path_ini);

    [DllImport("run_on_camera_sequence")]
    static extern void main();

    [DllImport("run_on_camera_sequence")]
    static extern int start_track(int iteration, float[] pos_array, int[] is_update, byte[] imageData, float[] pos_rt);
    //static extern int start_track(int iteration, float[] pos_array, int[] is_update, byte[] imageData, float x, float y, float z, float w, float pos_x, float pos_y, float pos_z);



    // 为接收dll中计算值开辟空间
    private float[] pos_array = new float[7];
    private float[] pos_rt = new float[7];
    private int[] is_update = new int[2];

    // 申请变量向dll中传值,改变c++程序的运行逻辑
    // 物体的position
    private float pos_x = 0.095f;
    private float pos_y = 0.1f;
    private float pos_z = -0.4f;

    // 物体的旋转
    private float x = 0.0f;
    private float y = 0.0f;
    private float z = 0.0f;
    private float w = 0.0f;


    //接收dll中传过来相机图像数据
    private Texture2D tex;
    private int Width = 640;
    private int Length = 480;
    private byte[] imageData;


    Quaternion rotation_ = new Quaternion(0, 0, 0, 1);
    Vector3 trans_ = new Vector3(0, 0, 0);

    public GameObject Target;
    public GameObject CameraRender;

    int stop_run = 0;
    bool change_pos = true;

    
    int iteration = 0;

    private string stingpath_ini = "D:\\BUFFER\\Unity\\DLLProject01\\Assets\\Plugins\\config.ini";
    float[] pos_test = new float[3];
    char[] path_ini = new char[100];

    // Start is called before the first frame update
    void Start()
    {


        //path_ini = stingpath_ini.ToCharArray();
        if (readConfigFiles(stingpath_ini))
        {
            main();

            imageData = new byte[Width * Length * 3];
            tex = new Texture2D(Width, Length, TextureFormat.RGB24, false);
        }

        pos_rt[0] = pos_x;
        pos_rt[1] = pos_y;
        pos_rt[2] = pos_z;
        pos_rt[3] = x;
        pos_rt[4] = y;
        pos_rt[5] = z;
        pos_rt[6] = w;

    }

    // Update is called once per frame
    void Update()
    {

        if (stop_run != -1)
        {
            //stop_run = start_track(iteration, pos_array, is_update, imageData, x, y, z, w, pos_x, pos_y, pos_z);
            stop_run = start_track(iteration, pos_array, is_update, imageData, pos_rt);
            print(pos_array[4] + "**********" + pos_array[5] + "**********" + pos_array[6] + "**********");
            iteration += 1;

            tex.LoadRawTextureData(imageData);
            tex.Apply();
            CameraRender.GetComponent<Renderer>().material.mainTexture = tex;


            if (is_update[0] != is_update[1] && (is_update[0] * is_update[1]) == 0)
            {
                rotation_.x = pos_array[0];
                rotation_.y = pos_array[1];
                rotation_.z = pos_array[2];
                rotation_.w = pos_array[3];
                Target.transform.localRotation = rotation_;

                trans_.x = pos_array[4];
                trans_.y = pos_array[5];
                trans_.z = pos_array[6];
                Target.transform.localPosition = trans_;

                print("****localRotation*****" + Target.transform.localRotation + "****localPosition*****" + Target.transform.localPosition);
                print("---change---");
            }

            print("-------[0]------" + is_update[0] + "-------[1]------" + is_update[1]);


            if (is_update[0] == is_update[1])
            {
                x = -Target.transform.localRotation.x;
                y = Target.transform.localRotation.y;
                z = -Target.transform.localRotation.z;
                w = Target.transform.localRotation.w;

                pos_x = Target.transform.localPosition.x;
                pos_y = -Target.transform.localPosition.y;
                pos_z = Target.transform.localPosition.z;

                print("***********pos_z************" + pos_z + "******is_update[0]*****" + is_update[0] + "******is_update[1]*****" + is_update[1]);


                pos_rt[0] = pos_x;
                pos_rt[1] = pos_y;
                pos_rt[2] = pos_z;
                pos_rt[3] = x;
                pos_rt[4] = y;
                pos_rt[5] = z;
                pos_rt[6] = w;
                //pos_z = Target.transform.localPosition.z;
            }

        }
        //if ( is_update[1] == 2)
        //{
        //    //is_update[0] = -1;
        //    //is_update[1] = 0;

        //    print("free room");

        //}

    }


}

Guess you like

Origin blog.csdn.net/moonlightpeng/article/details/131924323