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);
    }
}