VisibleSimで遊んでみた--アプリの作成--

:::note warn
注意
　この文章の筆者は専門家ではないので鵜呑みにしないこと。
　正しい情報は参考リンクから調べてね。　
:::

# はじめに
　VisibleSimをいろいろいじって動きを調べていく。
まずは自分で新しくアプリケーションを作成するところをやっていく。
サンプルアプリに`hexanodes_demo`があるのでこれを複製していく。
# 遊んでみた
### ディレクトリ構成
　まずはディレクトリ構成を確認。
今回は新しくシュミレーションを行っていくので、`applicationSrc`と`applicationBin`がメインとなる。
```
.
+-- applicationsBin/
|   +-- [BlockCode Applications]
|	+-- meld/
+-- applicationsSrc/
|	+-- Makefile
|	+-- [BlockCode Sources]
+-- doc/
|	+-- Doxyfile
|	+-- html/
|	+-- Makefile
|	+-- [Various Documentations]
+-- simulatorCore/
|	+-- src/
|	|	+-- TinyXML/
|	|	+-- Debugger/
|	|	+-- [Core Source Files]
| 	+-- [Texture Directories]
|	+-- [UI Help Files]
+-- utilities/
|	+-- meld-compiler/
|	+-- LMParser/
|	+-- configGenerator/ (nazandre/VisibleSimConfigGenerator)
|	+-- blockCodeTest.sh
```

### ソースコードの作成
　早速コードを書いていく。アプリ名はhexTestとする。
手動で追加、更新するファイルは以下の6種類。
* applicationsSrc/hexTest/hexTest.cpp
* applicationsSrc/hexTest/hexTestBlockCode.cpp
* applicationsSrc/hexTest/hexTestBlockCode.hpp
* applicationsSrc/hexTest/Makefile
* applicationsSrc/Makefile
* applicationsBin/hexTest/config.xml

それでは上から追加していく。

```diff:applicationsSrc/hexTest/hexTest.cpp
/**
 * @file   nodeDemo.cpp
 * @author pthalamy <pthalamy@p3520-pthalamy-linux>
 * @date   Wed Jun 19 14:17:18 2019
 *
 * @brief
 *
 *
 */

#include <iostream>

#include "robots/hexanodes/hexanodesSimulator.h"
#include "robots/hexanodes/hexanodesBlockCode.h"
#include "hexTestBlockCode.hpp"

using namespace std;
using namespace Hexanodes;

int main(int argc, char **argv) {
    try {
        createSimulator(argc, argv, HexTestBlockCode::buildNewBlockCode);
        getSimulator()->printInfo();
        BaseSimulator::getWorld()->printInfo();
        deleteSimulator();
    }
    catch(std::logic_error const& err) {
        cerr << err.what();
    }
    catch (char const* msg) {
        cerr << msg << endl;
    }

    return 0;
}

```

```diff:applicationsSrc/hexTestBlockCode.cpp
/**
 * @file   nodeDemoBlockCode.cpp
 * @author pthalamy <pthalamy@p3520-pthalamy-linux>
 * @date   Wed Jun 19 14:15:26 2019
 *
 * @brief
 *
 *
 */

#include "hexTestBlockCode.hpp"

#include "robots/hexanodes/hexanodesWorld.h"

#include "events/scheduler.h"
#include "events/events.h"
#include "utils/trace.h"
#include "robots/hexanodes/hexanodesMotionEvents.h"
#include "robots/hexanodes/hexanodesMotionEngine.h"

using namespace Hexanodes;

HexTestBlockCode::HexTestBlockCode(HexanodesBlock *host):HexanodesBlockCode(host) {
    scheduler = getScheduler();
    node = (HexanodesBlock*)hostBlock;
}

HexTestBlockCode::~HexTestBlockCode() {
}

// Function called by the module upon initialization
void HexTestBlockCode::startup() {
    HexanodesWorld *wrl = Hexanodes::getWorld();
    // Dummy translation example
    if (node->blockId == 1) {
        // turn clockwise if possible !
        vector<HexanodesMotion*> tab = wrl->getAllMotionsForModule(node);
        console << "#motion=" << tab.size() << "\n";
        vector<HexanodesMotion*>::const_iterator ci=tab.begin();
        while (ci!=tab.end() && (*ci)->direction!=motionDirection::CW) {
                ci++;
        }
        if (ci!=tab.end()) {
            Cell3DPosition destination = (*ci)->getFinalPos(node->position);
						scheduler->schedule(new HexanodesMotionStartEvent(scheduler->now()+1000000, node,destination,(*ci)->getToConId()));
        }
    }
}

void HexTestBlockCode::onMotionEnd() {
    nMotions++;

    // turn clockwise from previousPivot attachment
    HexanodesWorld *wrl = Hexanodes::getWorld();
    vector<HexanodesMotion*> tab = wrl->getAllMotionsForModule(node);
    vector<HexanodesMotion*>::const_iterator ci=tab.begin();
    while (ci!=tab.end() && !((*ci)->direction==motionDirection::CW)) {
        ci++;
    }
    if (ci!=tab.end() && nMotions<=5000) {
        Cell3DPosition destination = (*ci)->getFinalPos(node->position);
        scheduler->schedule(new HexanodesMotionStartEvent(scheduler->now()+100000, node,destination,(*ci)->getToConId()));
    } else {
        cout << "no possible motions..." << endl;
    }
}

string HexTestBlockCode::onInterfaceDraw() {
    return "Number of motions: " + to_string(nMotions);
}

```

```diff:applicationsSrc/hexTest/Makefile
 * @file   nodeDemoBlockCode.hpp
 * @author pthalamy <pthalamy@p3520-pthalamy-linux>
 * @date   Wed Jun 19 14:14:56 2019
 *
 * @brief
 *
 *
 */

#ifndef HexTestBlockCode_H_
#define HexTestBlockCode_H_

#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <climits>

#include "robots/hexanodes/hexanodesBlockCode.h"
#include "robots/hexanodes/hexanodesSimulator.h"
#include "robots/hexanodes/hexanodesBlock.h"
#include "grid/lattice.h"

using namespace Hexanodes;

class HexTestBlockCode : public Hexanodes::HexanodesBlockCode {
public:
    Scheduler *scheduler;
    Hexanodes::HexanodesBlock *node;
    inline static size_t nMotions = 0;

    HexTestBlockCode(Hexanodes::HexanodesBlock *host);
    ~HexTestBlockCode();

    void startup() override;
    //void processLocalEvent(EventPtr pev) override;
    void onMotionEnd() override;
    string onInterfaceDraw() override;

    void processReceivedMessage(MessagePtr msg, P2PNetworkInterface* sender);

    static BlockCode *buildNewBlockCode(BuildingBlock *host) {
        return (new HexTestBlockCode((HexanodesBlock*)host));
    }

};

#endif /* HexTestBlockCode_H_ */
```
```diff:applicationsSrc/Makefile
# Get current directory's name
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
APPDIR = ../../applicationsBin/$(current_dir)

#####################################################################
#
# --- Sample User Makefile ---
#
# GLOBAL_LIBS, GLOBAL_INCLUDES and GLOBAL_CFLAGS are set by parent Makefile
# HOWEVER: If calling make from the codeBlock directory (for more convenience to the user),
#	these variables will be empty. Hence we test their value and if undefined,
#	set them to predefined values.
#
# You will find instructions below on how to edit the Makefile to fit your needs.
#
# SRCS contains all the sources of your codeBlocks
SRCS =  hexTest.cpp hexTestBlockCode.cpp
#
# OUT is the output binary, where APPDIR is its enclosing directory
OUT = $(APPDIR)/hexTest
#
# MODULELIB is the library for your target module type: -lsim<module_name>
MODULELIB = -lsimHexanodes
# TESTS contains the commands that will be executed when `make test` is called
TESTS = ../../utilities/blockCodeTest.sh $(current_dir) $(OUT)
#
# End of Makefile section requiring input by user
#####################################################################

OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.depends)

OS = $(shell uname -s)
SIMULATORLIB = $(MODULELIB:-l%=../../simulatorCore/lib/lib%.a)

ifeq ($(GLOBAL_INCLUDES), )
INCLUDES = -I. -I../../simulatorCore/src -I/usr/local/include -I/opt/local/include -I/usr/X11/include
else
INCLUDES = -I. -I../../simulatorCore/src $(GLOBAL_INCLUDES)
endif

ifeq ($(GLOBAL_LIBS), )
	ifeq ($(OS),Darwin)
LIBS = -L./ -L../../simulatorCore/lib -L/usr/local/lib -lGLEW -lglut -framework GLUT -framework OpenGL -L/usr/X11/lib /usr/local/lib/libglut.dylib /usr/local/lib/libmuparser.dylib $(MODULELIB)
	else
LIBS = -L./ -L../../simulatorCore/lib -L/usr/local/lib -L/opt/local/lib -L/usr/X11/lib -lglut -lGL -lGLU -lGLEW -lpthread -lm -ldl -lmuparser $(MODULELIB)
	endif				#OS
else
LIBS = $(GLOBAL_LIBS) -L../../simulatorCore/lib
endif				#GLOBAL_LIBS

ifeq ($(GLOBAL_CCFLAGS),)
CCFLAGS = -g -Wall -std=c++17 -Wsuggest-override -fno-stack-protector
	ifeq ($(OS), Darwin)
	CCFLAGS += -DGL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED -Wno-deprecated-declarations -Wno-overloaded-virtual
	endif
else
CCFLAGS = $(GLOBAL_CCFLAGS)
endif

CC = g++

.PHONY: clean all test

.cpp.o:
	$(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@

%.depends: %.cpp
	$(CC) -M $(CCFLAGS) $(INCLUDES) $< > $@

all: $(OUT)
	@:

test:
	@$(TESTS)

autoinstall: $(OUT)
	cp $(OUT)  $(APPDIR)

$(APPDIR)/$(OUT): $(OUT)

$(OUT): $(SIMULATORLIB) $(OBJS)
	$(CC) -o $(OUT) $(OBJS) $(LIBS)

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

clean:
	rm -f *~ $(OBJS) $(OUT) $(DEPS)

```
```diff:applicationsSrc/Makefile
+ SUBDIRS = hexTest
- SUBDIRS = myApp
.PHONY: subdirs $(SUBDIRS) test
...
```
```diff:applicationsBin/hexTest/config.xml
<?xml version="1.0" standalone="no" ?>
<world gridSize="11,10,1" windowSize="1024,800">
    <camera target="356.5,175.274,18.2981" directionSpherical="0,70,640" angle="45.000000" near="1.000000" far="1500.000000" />
    <spotlight target="200,180,0" directionSpherical="-45,40,500" angle="56.309932" />
    <blockList blockSize="50,50,12.5">
        <block position="9,8,0" color="255,64,64" />
        <block position="1,8,0" color="255,255,64" />
        <block position="1,7,0" color="0,255,0" />
        <block position="2,7,0" color="0,255,0" />
        <block position="3,7,0" color="0,255,0" />
        <block position="4,7,0" color="0,255,0" />
        <block position="9,7,0" color="0,255,0" />
        <block position="1,6,0" color="0,255,0" />
        <block position="4,6,0" color="0,255,0" />
        <block position="6,6,0" color="0,255,0" />
        <block position="7,6,0" color="0,255,0" />
        <block position="8,6,0" color="0,255,0" />
        <block position="9,6,0" color="0,255,0" />
        <block position="1,5,0" color="0,255,0" />
        <block position="4,5,0" color="0,255,0" />
        <block position="7,5,0" color="0,255,0" />
        <block position="9,5,0" color="0,255,0" />
        <block position="1,4,0" color="0,255,0" />
        <block position="3,4,0" color="0,255,0" />
        <block position="4,4,0" color="0,255,0" />
        <block position="5,4,0" color="0,255,0" />
        <block position="6,4,0" color="0,255,0" />
        <block position="7,4,0" color="0,255,0" />
        <block position="9,4,0" color="0,255,0" />
        <block position="1,3,0" color="0,255,0" />
        <block position="9,3,0" color="0,255,0" />
        <block position="1,2,0" color="0,255,0" />
        <block position="2,2,0" color="0,255,0" />
        <block position="3,2,0" color="0,255,0" />
        <block position="4,2,0" color="0,255,0" />
        <block position="5,2,0" color="0,255,0" />
        <block position="6,2,0" color="0,255,0" />
        <block position="7,2,0" color="0,255,0" />
        <block position="8,2,0" color="0,255,0" />
        <block position="9,2,0" color="0,255,0" />
        <block position="9,1,0" color="0,255,0" />
    </blockList>
</world>

```

### ビルド
　公式ドキュメントによるとsimulatorCoreディレクトリをビルドした後変更がなければ直接ApplicationSrcから直接makeをしても問題なさそうだったので、やってみたがエラーになった。ApplicationSrc/hexTestも同様。
> Alternatively, the user can call make directly from the block code directory, if no change has been made to core, since the static libraries are used for linking.

```
test@test-Virtual-Machine:~/Documents/01_repository/VisibleSim/applicationsSrc$ make
Checking hexTest block code
make[1]: Entering directory '/home/test/Documents/01_repository/VisibleSim/applicationsSrc/hexTest'
g++ -o ../../applicationsBin/hexTest/hexTest hexTest.o hexTestBlockCode.o -L./ -L../../simulatorCore/lib -L/usr/local/lib -L/opt/local/lib -L/usr/X11/lib -lglut -lGL -lGLU -lGLEW -lpthread -lm -ldl -lmuparser -lsimHexanodes
/bin/ld: ../../simulatorCore/lib/libsimHexanodes.a(hexanodesWorld.o): in function `Hexanodes::HexanodesWorld::glDraw()':
/home/test/Documents/01_repository/VisibleSim/simulatorCore/src/robots/hexanodes/hexanodesWorld.cpp:246: undefined reference to `glDisable'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/robots/hexanodes/hexanodesWorld.cpp:253: undefined reference to `glPopMatrix'
<中略>
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:104: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:105: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:106: undefined reference to `glEnd'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:109: undefined reference to `glBegin'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:110: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:111: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:112: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:113: undefined reference to `glVertex3f'
/bin/ld: /home/test/Documents/01_repository/VisibleSim/simulatorCore/src/csg/csg.cpp:114: undefined reference to `glEnd'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:84: ../../applicationsBin/hexTest/hexTest] Error 1
make[1]: Leaving directory '/home/test/Documents/01_repository/VisibleSim/applicationsSrc/hexTest'
make: *** [Makefile:13: hexTest] Error 2
```

というわけで普通にリポジトリのルートからmakeを行う
```diff:VisibleSim/
make
```

### 実行
ビルドできたので動作確認してみる。
```diff:applicationsBin/hexTest
./hexTest
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2584877/98a84deb-8705-13db-4baf-339f9492a843.png)
rを押すとくるくる回り始める。かわいい

# おわりに
無事にサンプルのクローンを作成できたので、次は設定をいじってみる。


# 参考リンク
* https://www.programmable-matter.com/
* https://github.com/ProgrammableMatterProject/VisibleSim