質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.37%

  • C#

    4748questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    2286questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

OpenTKを用いたUnityによる物体描画

解決済

回答 1

投稿 2017/11/21 16:40

  • 評価
  • クリップ 0
  • VIEW 80

abc_oxox

score 8

unityで物体を描画するにあたって,計算の過程でOpenTKを使用したいのですが,仕様上不可能なのでしょうか.

C#のコードでOpenTKを用いて書かれたコードがあり,それをUnityへ移植しているのですが,コード内ではOpenTKの参照は追加済みでエラーはでていないのですが,Unityで実行すると,
「The type or namespace name 'OpenTK' could not be found.Are you missing an assembly reference?」
というようなエラーがでます.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fiveHundred

    2017/11/22 18:23

    「OpenTKの参照は追加済み」とのことですが、どのようにして追加したのでしょうか?。また、そのOpenTKを使って行いたい処理とは、具体的になんでしょうか?

    キャンセル

回答 1

checkベストアンサー

0

回答というより失敗報告で申し訳ないのですが...

OpenTK自体はマネージドアセンブリのようですので、NuGet Gallery | OpenTK 2.0.0 から入手したopentk.2.0.0.nupkgを展開、中に入っているOpenTK.dllを、Unityプロジェクト内にPluginsフォルダを作って中に入れるだけでスクリプトから参照することはできました。この状態で、OpenGLと関係ないOpenTKの機能(行列計算とか)は使えるかもしれませんが、OpenTK.Graphics.OpenGL.GLとかOpenTK.Graphics.ES30.GLの機能を使おうとするとUnityが異常終了したり応答不能になったりしてダメでした。

OpenGLの機能を使うには適切なGraphicsContextを用意してやる必要があるはず、それがないからダメなのか...?と思い、Unity - Manual: Low-level Native Plugin Interfaceに載っていたNativeRenderingPluginのサンプルをダウンロード、RenderingPlugin.cppを下記のように書き換えて(C++の知識も各プラットフォームの知識も不十分な状態で見よう見まねで書いたので、とんでもないコードになっている可能性がありますがご容赦下さい)、XcodeでビルドしてRenderingPlugin.bundleを、Visual StudioでビルドしてRenderingPlugin.dllを作り、これらもPluginsフォルダに入れました。

#include "PlatformBase.h"
#include "RenderAPI.h"

#include <assert.h>
#include <math.h>
#include <vector>

// --------------------------------------------------------------------------
// UnitySetInterfaces

static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType);

static IUnityInterfaces* s_UnityInterfaces = NULL;
static IUnityGraphics* s_Graphics = NULL;

extern "C" void    UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) {
    s_UnityInterfaces = unityInterfaces;
    s_Graphics = s_UnityInterfaces->Get<IUnityGraphics>();
    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);

    // Run OnGraphicsDeviceEvent(initialize) manually on plugin load
    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() {
    s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);
}

#if UNITY_WEBGL
typedef void (UNITY_INTERFACE_API * PluginLoadFunc)(IUnityInterfaces* unityInterfaces);
typedef void (UNITY_INTERFACE_API * PluginUnloadFunc)();

extern "C" void    UnityRegisterRenderingPlugin(PluginLoadFunc loadPlugin, PluginUnloadFunc unloadPlugin);

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RegisterPlugin() {
    UnityRegisterRenderingPlugin(UnityPluginLoad, UnityPluginUnload);
}
#endif

// --------------------------------------------------------------------------
// GraphicsDeviceEvent

static RenderAPI* s_CurrentAPI = NULL;
static UnityGfxRenderer s_DeviceType = kUnityGfxRendererNull;

static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) {
    // Create graphics API implementation upon initialization
    if (eventType == kUnityGfxDeviceEventInitialize) {
        assert(s_CurrentAPI == NULL);
        s_DeviceType = s_Graphics->GetRenderer();
        s_CurrentAPI = CreateRenderAPI(s_DeviceType);
    }

    // Let the implementation process the device related events
    if (s_CurrentAPI) {
        s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces);
    }

    // Cleanup graphics API implementation upon shutdown
    if (eventType == kUnityGfxDeviceEventShutdown) {
        delete s_CurrentAPI;
        s_CurrentAPI = NULL;
        s_DeviceType = kUnityGfxRendererNull;
    }
}

// --------------------------------------------------------------------------
// OnRenderEvent
// This will be called for GL.IssuePluginEvent script calls; eventID will
// be the integer passed to IssuePluginEvent. In this example, we just ignore
// that value.

typedef void (*OpenTKRenderingCallback)(void* context, int eventID);

static OpenTKRenderingCallback s_RenderingCallback; // レンダリング時のコールバック...この中でOpenTKの機能を使う(ようにすればうまくいくかと思ったが失敗)

extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetCurrentGLContext();
extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetGLProcAddress(const char* name);

static void UNITY_INTERFACE_API OnRenderEvent(int eventID) {
    // Unknown / unsupported graphics device type? Do nothing
    if (s_CurrentAPI == NULL)
        return;

    if (s_RenderingCallback) {
        s_RenderingCallback(GetCurrentGLContext(), eventID);
    }
}

// --------------------------------------------------------------------------
// GetRenderEventFunc, an example function we export which is used to get a rendering event callback function.

extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() {
    return OnRenderEvent;
}

// --------------------------------------------------------------------------
// コールバックを登録
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetRenderingCallback(OpenTKRenderingCallback callback) {
    s_RenderingCallback = callback;
}

// --------------------------------------------------------------------------
// 現在のOpenGLコンテキストを取得/OpenGL関数を名前から取得

#if SUPPORT_OPENGL_LEGACY || SUPPORT_OPENGL_UNIFIED || SUPPORT_OPENGL_CORE || SUPPORT_OPENGL_ES
#if UNITY_WIN
#include <windows.h>

extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetCurrentGLContext() {
    return wglGetCurrentContext();
}

extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetGLProcAddress(const char* name) {
    return wglGetProcAddress(name);
}
#elif UNITY_LINUX // Linux版はテストしていないが、多分こんな感じだろうか?
#include "glxew.h"

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() {
    return glXGetCurrentContext();
}

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) {
    return glXGetProcAddress(name);
}
#elif UNITY_OSX // iOSはコンテキスト取得のAPIがObjective-C用しかない?やりようはありそうだが、過度な複雑化を避けるためiOSはさしあたり無視
#include <OpenGL/OpenGL.h>
#include <dlfcn.h>

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() {
    return CGLGetCurrentContext();
}

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char *name) {
    // https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_entrypts/opengl_entrypts.html#//apple_ref/doc/uid/TP40001987-CH402-SW6 掲載のサンプルコードは古いので
    // https://sourceforge.net/p/glew/patches/17/ の方法を採用

    static void* image = NULL;
    void* symbol;
    char* symbolName;

    if (!image) {
        image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
    }

    symbolName = (char*)malloc(strlen(name) + 2);
    strcpy(symbolName + 1, name);
    symbolName[0] = '_';
    symbol = image ? dlsym(image, symbolName) : NULL;
    free(symbolName);

    return symbol;
}
#else
extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() {
    return NULL;
}

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) {
    return NULL;
}
#endif
#else
extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() {
    return NULL;
}

extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) {
    return NULL;
}
#endif

そしてUnity側ではカメラに下記スクリプトをアタッチし、OnPostRenderのタイミングでコンテキストを取得(ここまではMac版、Windows版ともにできたように見えましたが)、いざOpenGLの機能を使えるか...と思ったらやっぱりダメでした。

using UnityEngine;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System;
using System.Runtime.InteropServices;

using TKGL = OpenTK.Graphics.OpenGL.GL; // UnityEngineのGLと名前かぶりするので別名を用意

[RequireComponent(typeof(Camera))]
public class OpenTKTest : MonoBehaviour
{
    private static GraphicsContext OpenGLContext;

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void RenderingCallback(IntPtr contextPointer, int eventID);

    [DllImport("RenderingPlugin")]
    private static extern void SetRenderingCallback([MarshalAs(UnmanagedType.FunctionPtr)] RenderingCallback callback);

    [DllImport("RenderingPlugin")]
    private static extern IntPtr GetRenderEventFunc();

    [DllImport("RenderingPlugin")]
    private static extern IntPtr GetCurrentGLContext();

    [DllImport("RenderingPlugin")]
    private static extern IntPtr GetGLProcAddress([MarshalAs(UnmanagedType.LPStr)] string name);

    private static ContextHandle GetCurrentContextAsContextHandle()
    {
        return new ContextHandle(GetCurrentGLContext());
    }

    private void Start()
    {
        SetRenderingCallback(this.RenderWithOpenTK);
    }

    // Unityの描画終了後にOpenTKにより追加描画
    private void OnPostRender()
    {
        UnityEngine.GL.IssuePluginEvent(GetRenderEventFunc(), 1234); // イベントIDに適当な値を渡し、値が伝達されるかテスト
    }

    private void RenderWithOpenTK(IntPtr contextPointer, int eventID)
    {
        if (OpenGLContext == null)
        {
            Debug.LogFormat("Context:{0} Event ID:{1}", contextPointer, eventID); // Mac、Windowsともに一応コンテキストのポインタらしきものは取れて、ダミーコンテキストもエラーなく生成できるのだが...
            OpenGLContext = new GraphicsContext(new ContextHandle(contextPointer), GetGLProcAddress, GetCurrentContextAsContextHandle);
            OpenGLContext.MakeCurrent(null);
            // Debug.Log(TKGL.GetString(StringName.Version)); // GLの機能を使おうとするとUnityがクラッシュ、または応答しなくなる
        }

        Debug.Log(GraphicsContext.CurrentContext);
        // TKGL.Clear(ClearBufferMask.ColorBufferBit);
    }
}

OpenTK用のコードをそのまま動かそうとするのはハードルが高そうです。追記修正欄にてfiveHundredさんもご指摘なさっていますが、その「OpenTKを用いて書かれたコード」はどういったものでしょうか?さほど規模が大きくなければ、それをOpenTK不使用の完全Unityオンリーなコードに書き換える方が、より現実的かもしれません。

投稿 2017/11/23 11:15

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/23 17:48

    大変丁寧な回答ありがとうございます.
    「OpenTKを用いて書かれたコード」ですが,OpenTK.Graphics.OpenGL.GLを用いて描画するコードがありますが,Unityで代用できそうです.
    他はOpenTK.dllを、Unityプロジェクト内のPluginsフォルダに入れることでエラーは消えてくれました.
    ありがとうございました.

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.37%

関連した質問

  • 受付中

    Unity、頂点の選択について

    1頂点を取得(選択)した後、その頂点の周りに接する頂点をまとめて選択するような方法を探しています。 また、いくつかの頂点を選択した後、一番端っこに属する頂点を選択から除くような処

  • 解決済

    【Unity】外部のオブジェクトを参照したい

    始めにこちらのサイトを参考にさせていただきました http://qiita.com/JunShimura/items/864054bb9710b63c1a3b#%E5%80%A4

  • 解決済

    its value is never usedのエラー

    Assets/Script/PlayerController.cs(21,27): warning CS0414: The private field `PlayerControl

  • 解決済

    MissingReferenceExceptionのエラー

    MissingReferenceException: The object of type 'Transform' has been destroyed but you are s

  • 解決済

    緊急 誰か助けてください!

    このスクリプトを試してみてください(T ^ T) using UnityEngine; using System.Collections; public class 

  • 受付中

    unity nintendo 3ds ビルドができない。

    前提・実現したいこと 今現在unityとnintendo 3ds のインストールをしてそこまでは成功したのですがそれを3dsでビルドしようとしたら変なエラーコードが出てきました。

  • 解決済

    メソッドにアクセスできない。

    前提・実現したいこと インスタンスのメソッドにアクセスしようとすると、エラーが出てしまいます。(おそらくアクセス権限のエラー。) publicで定義しているので、原因、対処法が

  • 解決済

    持ち物画面を作成したいです

    わからないこと 持ち物画面を作成を作成しようとこちらを参考にしながら作っいますが、エラーが出てしまいます。 using System.Collections; using S

同じタグがついた質問を見る

  • C#

    4748questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    2286questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。