2018年6月13日水曜日

Real-Time Rendering, Fourth Edition

Real-Time Renderingの第4版が8月発売です。
Real-Time Rendering, Fourth Edition

2018年6月7日木曜日

64bitを考慮した, ファイル操作

LinuxとWindowsでチェックしています。
ftellをサイズ取得のために使うべきではないという説明はこちら
#include <cassert>
#include <cstdint>
#include <stdio.h>
#include <sys/stat.h>

//C++98 199711L
//C++11 201103L
#ifdef __cplusplus
#   if 201103L<=__cplusplus || 1900<=_MSC_VER
#       define CPP_CPP11 1
#   endif
#endif

#ifdef __cplusplus
#   ifdef CPP_CPP11
#       define CPP_NULL nullptr
#   else
#       define CPP_NULL 0
#   endif
#else
#   define CPP_NULL ((void*)0)
#endif

#ifdef _NDEBUG
#define CPP_ASSERT(exp)
#else
#define CPP_ASSERT(exp) assert(exp)
#endif

#ifndef CPP_TYPES
#define CPP_TYPES
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef float f32;
typedef double f64;

typedef char Char;

typedef ::size_t size_t;
#endif

#ifdef _MSC_VER
#ifndef CPP_FSEEK
#define CPP_FSEEK(f,p,o) _fseeki64((f),(p),(o))
#endif

#ifndef CPP_FTELL
#define CPP_FTELL(f) _ftelli64((f))
#endif

#ifndef CPP_SPRINTF
#define CPP_SPRINTF(b,f, ...) sprintf_s(b, f, __VA_ARGS__)
#endif

#ifndef CPP_FSEEK
#define CPP_FSEEK(f,p,o) fseeko64((f),(p),(o))
#endif

#ifndef CPP_FTELL
#define CPP_FTELL(f) ftello64((f))
#endif

#ifndef CPP_SPRINTF
#define CPP_SPRINTF(b,f, ...) sprintf((b), (f), __VA_ARGS__)
#endif

inline s64 CPP_FSIZE(FILE* file)
{
    CPP_ASSERT(CPP_NULL != file);
    struct _stat64 stat;
    return (0 == _fstat64(_fileno(file), &stat))? stat.st_size : 0;
}

inline FILE* CPP_FOPEN(const Char* filepath, const Char* mode)
{
    CPP_ASSERT(CPP_NULL != filepath);
    CPP_ASSERT(CPP_NULL != mode);
    FILE* file = CPP_NULL;
    return 0 == ::fopen_s(&file, filepath, mode) ? file : CPP_NULL;
}

inline void CPP_FCLOSE(FILE*& file)
{
    if(CPP_NULL != file){
        fclose(file);
        file = CPP_NULL;
    }
}

#else
#ifndef CPP_FSEEK
#define CPP_FSEEK(f,p,o) fseeko64((f),(p),(o))
#endif

#ifndef CPP_FTELL
#define CPP_FTELL(f) ftello64((f))
#endif

#ifndef CPP_SPRINTF
#define CPP_SPRINTF(b,f, ...) sprintf((b), (f), __VA_ARGS__)
#endif

inline s64 CPP_FSIZE(FILE* file)
{
    CPP_ASSERT(CPP_NULL != file);
    struct stat64 stat;
    return (0 == fstat64(fileno(file), &stat))? stat.st_size : 0;
}

inline FILE* CPP_FOPEN(const Char* filepath, const Char* mode)
{
    CPP_ASSERT(CPP_NULL != filepath);
    CPP_ASSERT(CPP_NULL != mode);
    return fopen(filepath, mode);
}

inline void CPP_FCLOSE(FILE*& file)
{
    if(CPP_NULL != file){
        fclose(file);
        file = CPP_NULL;
    }
}
#endif

int main(int argc, char** argv)
{
    FILE* file = CPP_FOPEN(argv[0], "rb");
    CPP_FSEEK(file, 0, SEEK_END);
    s64 size = CPP_FTELL(file);
    CPP_FSEEK(file, 0, SEEK_SET);
    s64 statSize = CPP_FSIZE(file);
    printf("size=%ld,%ld\n", size, statSize);
    CPP_FCLOSE(file);
    return 0;
}

Postprocess only assets which you selects in Unity

We can select the "ToGray" menu item, then the "Do" method is called.
The OnPostprocessTexture method will do postprocessing to only assets which were preprocessed by "Do".
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class ToGrayTexture : AssetPostprocessor
{
    private static List<string> guids_ = new List<string>(8);

    [MenuItem("Assets/Texture/ToGray")]
    private static void Do()
    {
        guids_.Clear();
        Object[] objects = Selection.objects;
        if(objects.Length <= 0) {
            return;
        }
        foreach(Object obj in objects) {
            string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(obj));
            guids_.Add(guid);
        }
        EditorApplication.ExecuteMenuItem("Assets/Reimport");
    }


    void OnPostprocessTexture(Texture2D texture)
    {
        string guid = AssetDatabase.AssetPathToGUID(assetPath);
        if(!guids_.Exists(s => guid == s)) {
            return;
        }
        for(int i=0; i<texture.mipmapCount; ++i) {
            Color32[] colors = texture.GetPixels32(i);
            for(int j=0; j<colors.Length; ++j) {
                int c = (int)(0.299f * colors[j].r + 0.587f * colors[j].g + 0.114f * colors[j].b);
                colors[j].r = colors[j].g = colors[j].b = (byte)Mathf.Clamp(c, 0, 255);
            }
            texture.SetPixels32(colors, i);
        }
        texture.Apply();
        guids_.Remove(guid);
    }
}

2018年4月22日日曜日

Morton Code and Reverse Morton Code

なんとなく、MortonCodeの逆変換が欲しくなりました.
10bit対応しました. 3次元で10bitずつ各次元に割り当てる場合に使います.
typedef int s32;

s32 separateBy2(s32 x)
{
    x &= 0x09249249U;
    x = (x | (x << 8) | (x<<16)) & 0x0300F00FU;
    x = (x | (x << 4) | (x<< 8)) & 0x030C30C3U;
    x = (x | (x << 2) | (x<< 4)) & 0x09249249U;
    return x;
}

s32 combineBy2(s32 x)
{
    x = (x | (x>>2) | (x>> 4)) & 0x030C30C3U;
    x = (x | (x>>4) | (x>> 8)) & 0x0300F00FU;
    x = (x | (x>>8) | (x>>16)) & 0x3FFU;
    return x;
}

s32 mortonCode3(s32 x, s32 y, s32 z)
{
    return separateBy2(x) | (separateBy2(y) << 1) | (separateBy2(z) << 2);
}

void rmortonCode3(s32& x, s32& y, s32& z, s32 w)
{
    x = combineBy2(w);
    y = combineBy2(w>>1);
    z = combineBy2(w>>2);
}

2018年2月19日月曜日

VinoでVNC

XubuntuでVNCサーバを設定するノート

VNCサーバ

vinoをインストールする.
#vino-preferences
で設定起動.
以下のチェックを入れる.
[Sharing]
Allow other users to view your desktop
 Allow other users to control your desktop

以下のチェックを外す.
[Security]
You must confirm each access to this machine

暗号化を使わない場合,
#gsettings set org.gnome.Vino require-encryption false
とする.
サーバーの場所は以下,
#/usr/lib/vino/vino-server
スタートアップに設定しておくと楽.
VNCクライアントからは, IPアドレス:ディスプレイ番号で接続する. ディスプレイ番号が0なら省略可能.

Wake On LAN

まず, BIOS設定からそれっぽいものを有効にする.
ethtoolをインストールして, ツールにインターフェイス名を指定して情報を表示する.
以下のように, ステータスがdになっていれば無効になっている.
#apt install ethtool
#ethtool enp1s0
    ----
    Wake-on: d
    ----
以下のように有効化, 必要なら適当な箇所で有効になるように設定する.
ステータスがgになっていれば有効.
#ethtool -s enp1s0 wol g
    ----
    Wake-on: g
    ----

.Netから叩き起こす
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace WakeOnLAN
{
    class Program
    {
        static void Main(string[] args)
        {
            if(args.Length<2) {
                System.Console.WriteLine("Usage: <global ip address> <mac address>");
                return;
            }
            try {
                IPAddress globalAddress = null;
                if(!IPAddress.TryParse(args[0], out globalAddress)) {
                    return;
                }
                PhysicalAddress physicalAddress = PhysicalAddress.Parse(args[1]);
                using(MemoryStream memoryStream = new MemoryStream())
                using(BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
                using(UdpClient client = new UdpClient()) {
                    for(int i = 0; i<6; ++i) {
                        binaryWriter.Write((byte)0xFF);
                    }
                    byte[] bytes = physicalAddress.GetAddressBytes();
                    for(int i = 0; i<16; ++i) {
                        binaryWriter.Write(bytes);
                    }

                    binaryWriter.Flush();
                    byte[] sendData = memoryStream.ToArray();
                    client.EnableBroadcast = true;
                    client.Send(sendData, sendData.Length, new IPEndPoint(globalAddress, 0));
                    client.Close();
                }

            } catch {
                return;
            }
        }
    }
}

2018年2月7日水曜日

Morton Codeの計算とLBVH

Morton Code

概要

Z階数曲線(モートン符号)は, Z字型に空間を符号化します.
下図のように左上を原点とした場合にZ字型に空間を1次元に符号化します.

2018年1月20日土曜日

Simple zlib Decompression

概要

zlibフォーマットを自力で伸張するライブラリszlib(Github)を作成しました.
できるプログラマはこのようなものを簡単に作ると思いますが, 私は大変苦労したため,
ノートを残しておこうと思います.