2009年11月08日

WASAPI(22)

ぼちぼちと実装を見直しつつ行っている。
IAudioClientにはIsFormatSupported メソッドがある。
HRESULT IsFormatSupported(
[in] AUDCLNT_SHAREMODE ShareMode,
[in] const WAVEFORMATEX *pFormat,
[out] WAVEFORMATEX **ppClosestMatch
);


1つ目のパラメータは共有モードの指定、2つ目は確認したいフォーマット、3つ目は指定したWAVEFORMATはサポートしていないが、近いものを探してあった場合APIが返すフォーマットポインタのアドレスを指定する。
この3つ目のパラメータだが、共有モードでしか有効でない。排他モードだとかならずNULLが入り、HRESULTにAUDCLNT_E_UNSUPPORTED_FORMATが入る仕様となっている。排他モードだと相変わらず片っ端からサポートしているフォーマットをチェックしていかなくてはいけないのだろうか。ちょっとというか、かなり面倒臭い。



posted by S.F. at 10:34| 千葉 霧| Comment(0) | TrackBack(0) | WASAPI | このブログの読者になる | 更新情報をチェックする

2009年11月07日

コミック昭和史

僕は日本軍に関する本を読み漁っている。別にミリタリーマニアでもないのだけれど、やはり日本の近代史において一番重要な大東亜戦争における歴史的事実をできるだけ正確に把握しておきたいからである。
なぜならば、戦争経験者はもうその寿命を向かえつつあるし、だれかがその事実を継承していかなければ、そのとき得られた貴重な経験、教訓が忘却され、また同じことが繰り返されるからだ。

日本軍は戦略策定において欠陥があったのは事実で、そのために多くの犠牲を払って敗戦したというのがひとつの見方なのだけれど、もう1つはあれだけの国力で、戦術によって列強を少なからず苦しめたという側面もある。
軍政面においては、9割は植民地支配で植民地配下の現地民から搾取の限りを尽くしたという部分と、1割の現地民尊重の民主主義的支配形態(まさに八紘一宇のスローガンどおり)の両側面を持っていた。

水木しげるさんは、貴重な戦争体験者でもあり、日本の配色が濃くなりつつあった時期に召集され、ラバウルの近くのニューブリテン島で負傷し、ラバウルで終戦を迎えた。
そのため、水木さんはいくつかの兵隊目線での戦記漫画を書いている。
そこで書かれている水木さんはどちらかというと「変わり者」で上官からビンタされまくりな劣等兵である。漫画では兵隊の日常が克明に描かれている。本を読むと水木さん自体はまともな人間だと思うのだが、敗戦までの時代が狂っているので、「変わり者」扱いされていたことがわかる。

僕が一番最初に読んだのは「総員玉砕せよ!」である。

総員玉砕せよ! (講談社文庫)

総員玉砕せよ! (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1995/06
  • メディア: 文庫




「コミック昭和史」は昭和という時代を水木さんの人生と照らし合わせながら描いている。もちろん戦記部分も充実している。


コミック昭和史〈第8巻〉―高度成長以降 (講談社文庫)

コミック昭和史〈第8巻〉―高度成長以降 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/11
  • メディア: 文庫




コミック 昭和史〈第7巻〉講和から復興 (講談社文庫)

コミック 昭和史〈第7巻〉講和から復興 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/11
  • メディア: 文庫




コミック昭和史〈第6巻〉―終戦から朝鮮戦争 (講談社文庫)

コミック昭和史〈第6巻〉―終戦から朝鮮戦争 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/10
  • メディア: 文庫




コミック昭和史〈第5巻〉太平洋戦争後半 (講談社文庫)

コミック昭和史〈第5巻〉太平洋戦争後半 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/10
  • メディア: 文庫




コミック昭和史〈第4巻〉太平洋戦争前半 (講談社文庫)

コミック昭和史〈第4巻〉太平洋戦争前半 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/09
  • メディア: 文庫




コミック昭和史〈第3巻〉日中全面戦争~太平洋戦争開始 (講談社文庫)

コミック昭和史〈第3巻〉日中全面戦争~太平洋戦争開始 (講談社文庫)

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/09
  • メディア: 文庫




コミック昭和史 (第2巻) 満州事変~日中全面戦争

コミック昭和史 (第2巻) 満州事変~日中全面戦争

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/08
  • メディア: 文庫




コミック昭和史 (第1巻) 関東大震災~満州事変

コミック昭和史 (第1巻) 関東大震災~満州事変

  • 作者: 水木 しげる
  • 出版社/メーカー: 講談社
  • 発売日: 1994/08
  • メディア: 文庫



タグ:水木しげる
posted by S.F. at 08:06| 千葉 霧| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2009年11月06日

Direct2Dスケルトンコード

Direct2DのスケルトンコードをSimpleDirect2DApplicationサンプルのコードをベースに作成してみた。
殆どパクリだけど、COMスマートポインタを使っているのが違うところ。例外処理はいれていない。
・ヘッダ(Direct2DBurn.h)
#pragma once

#include "resource.h"
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//

#pragma once

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER              // Allow use of features specific to Windows 7 or later.
#define WINVER 0x0700       // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT        // Allow use of features specific to Windows 7 or later.
#define _WIN32_WINNT 0x0700 // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include 

// C RunTime Header Files


/******************************************************************
*                                                                 *
*  Macros                                                         *
*                                                                 *
******************************************************************/


#ifndef Assert
#if defined( DEBUG ) || defined( _DEBUG )
#define Assert(b) do {if (!(b)) {OutputDebugStringA("Assert: " #b "\n");}} while(0)
#else
#define Assert(b)
#endif //DEBUG || _DEBUG
#endif


#ifndef HINST_THISCOMPONENT
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
#endif

_COM_SMARTPTR_TYPEDEF(ID2D1Factory,__uuidof(ID2D1Factory));

_COM_SMARTPTR_TYPEDEF(IWICImagingFactory, __uuidof(IWICImagingFactory));
_COM_SMARTPTR_TYPEDEF(IDWriteFactory , __uuidof(IDWriteFactory));
_COM_SMARTPTR_TYPEDEF(ID2D1HwndRenderTarget , __uuidof(ID2D1HwndRenderTarget));
_COM_SMARTPTR_TYPEDEF(IDWriteTextFormat, __uuidof(IDWriteTextFormat));
_COM_SMARTPTR_TYPEDEF(ID2D1PathGeometry , __uuidof(ID2D1PathGeometry));
_COM_SMARTPTR_TYPEDEF(ID2D1LinearGradientBrush , __uuidof(ID2D1LinearGradientBrush));
_COM_SMARTPTR_TYPEDEF(ID2D1SolidColorBrush , __uuidof(ID2D1SolidColorBrush));
_COM_SMARTPTR_TYPEDEF(ID2D1BitmapBrush , __uuidof(ID2D1BitmapBrush));
_COM_SMARTPTR_TYPEDEF(ID2D1Bitmap , __uuidof(ID2D1Bitmap));

/******************************************************************
*                                                                 *
*  Direct2dWindow                                                        *
*                                                                 *
******************************************************************/
namespace sf{

class Direct2dWindow
{
public:
    Direct2dWindow();
    ~Direct2dWindow();

    void Initialize();
    void RunMessageLoop();
private:

	HRESULT OnRender();
	void CreateDeviceResources();
	void DiscardDeviceResources();

	void OnResize(
        UINT width,
        UINT height
        );

    static LRESULT CALLBACK WndProc(
        HWND hWnd,
        UINT message,
        WPARAM wParam,
        LPARAM lParam
        );

private:
    HWND hwnd_;
    ID2D1FactoryPtr pD2DFactory_;
    ID2D1HwndRenderTargetPtr pRenderTarget_;
};
}
・本体
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <wchar.h>
#include <math.h>

#include <d2d1.h>
#include <d2d1helper.h>
#include <dwrite.h>
#include <wincodec.h>
#include <comdef.h>
#include "Direct2DBurn.h"
using namespace sf;
//
// Provides the entry point to the application.
//
int WINAPI WinMain(
    HINSTANCE /* hInstance */,
    HINSTANCE /* hPrevInstance */,
    LPSTR /* lpCmdLine */,
    int /* nCmdShow */
    )
{
    // Ignore the return value because we want to continue running even in the
    // unlikely event that HeapSetInformation fails.
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);

    if (SUCCEEDED(CoInitialize(NULL)))
    {
        {
            Direct2dWindow app;
			app.Initialize();
            app.RunMessageLoop();
        }
        CoUninitialize();
    }

    return 0;
}


//
// Initialize members.
//
Direct2dWindow::Direct2dWindow() :hwnd_(NULL)
{
}

//
// Release resources.
//
Direct2dWindow::~Direct2dWindow()
{
    pD2DFactory_.Release();
    pRenderTarget_.Release();
}

//
// Creates the application window and initializes
// device-independent resources.
//
void Direct2dWindow::Initialize()
{
    HRESULT hr;

    // Create a Direct2D factory.
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory_);


	
	if (SUCCEEDED(hr))
    {
        // Register the window class.
        WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
        wcex.style         = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc   = Direct2dWindow::WndProc;
        wcex.cbClsExtra    = 0;
        wcex.cbWndExtra    = sizeof(LONG_PTR);
        wcex.hInstance     = HINST_THISCOMPONENT;
        wcex.hbrBackground = NULL;
        wcex.lpszMenuName  = NULL;
        wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcex.lpszClassName = L"D2DDirect2dWindow";

        RegisterClassEx(&wcex);

        // Create the application window.
        //
        // Because the CreateWindow function takes its size in pixels, we
        // obtain the system DPI and use it to scale the window size.
        FLOAT dpiX, dpiY;
        pD2DFactory_->GetDesktopDpi(&dpiX, &dpiY);

        // Create the application window.
        hwnd_ = CreateWindow(
            L"D2DDirect2dWindow",
            L"Direct2D Demo Application",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            static_cast(ceil(640.f * dpiX / 96.f)),
            static_cast(ceil(480.f * dpiY / 96.f)),
            NULL,
            NULL,
            HINST_THISCOMPONENT,
            this
            );
        hr = hwnd_ ? S_OK : E_FAIL;
        if (SUCCEEDED(hr))
        {
            ShowWindow(hwnd_, SW_SHOWNORMAL);
            UpdateWindow(hwnd_);
        }
    }
}


//
//  This method creates resources which are bound to a particular
//  Direct3D device. It's all centralized here, in case the resources
//  need to be recreated in case of Direct3D device loss (eg. display
//  change, remoting, removal of video card, etc).
//
void Direct2dWindow::CreateDeviceResources()
{

	HRESULT hr = S_OK;

    if (!pRenderTarget_)
    {
        RECT rc;
        GetClientRect(hwnd_, &rc);

        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
            );

        // Create a Direct2D render target.
        hr = pD2DFactory_->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hwnd_, size),
            &pRenderTarget_
            );

    }
}


//
// The main window message loop.
//
void Direct2dWindow::RunMessageLoop()
{
    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}


//
//  Called whenever the application needs to display the client
//  window. This method draws a bitmap a couple times, draws some
//  geometries, and writes "Hello, World"
//
//  Note that this function will not render anything if the window
//  is occluded (e.g. when the screen is locked).
//  Also, this function will automatically discard device-specific
//  resources if the Direct3D device disappears during function
//  invocation, and will recreate the resources the next time it's
//  invoked.
//

HRESULT Direct2dWindow::OnRender()
{
    HRESULT hr;

    CreateDeviceResources();

    if (!(pRenderTarget_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))
    {
        static const WCHAR sc_helloWorld[] = L"Hello, World!";
        // Retrieve the size of the render target.
        D2D1_SIZE_F renderTargetSize = pRenderTarget_->GetSize();

        pRenderTarget_->BeginDraw();
        pRenderTarget_->SetTransform(D2D1::Matrix3x2F::Identity());
        pRenderTarget_->Clear(D2D1::ColorF(D2D1::ColorF::White));

	    hr = pRenderTarget_->EndDraw();

        if (hr == D2DERR_RECREATE_TARGET)
        {
            //hr = S_OK;
            DiscardDeviceResources();
        }
    }

    return hr;
}

void Direct2dWindow::DiscardDeviceResources()
{
}

//
//  If the application receives a WM_SIZE message, this method
//  resize the render target appropriately.
//
void Direct2dWindow::OnResize(UINT width, UINT height)
{
    if (pRenderTarget_)
    {
        D2D1_SIZE_U size;
        size.width = width;
        size.height = height;

        // Note: This method can fail, but it's okay to ignore the
        // error here -- it will be repeated on the next call to
        // EndDraw.
        pRenderTarget_->Resize(size);
    }
}


//
// The window message handler.
//
LRESULT CALLBACK Direct2dWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT result = 0;

    if (message == WM_CREATE)
    {
        LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
        Direct2dWindow *pDirect2dWindow = (Direct2dWindow *)pcs->lpCreateParams;

        ::SetWindowLongPtrW(
            hwnd,
            GWLP_USERDATA,
            PtrToUlong(pDirect2dWindow)
            );

        result = 1;
    }
    else
    {
        Direct2dWindow *pDirect2dWindow = reinterpret_cast(static_cast(
            ::GetWindowLongPtrW(
                hwnd,
                GWLP_USERDATA
                )));

        bool wasHandled = false;

        if (pDirect2dWindow)
        {
            switch (message)
            {
            case WM_SIZE:
                {
                    UINT width = LOWORD(lParam);
                    UINT height = HIWORD(lParam);
                    pDirect2dWindow->OnResize(width, height);
                }
                result = 0;
                wasHandled = true;
                break;

            case WM_PAINT:
            case WM_DISPLAYCHANGE:
                {
                    PAINTSTRUCT ps;
                    BeginPaint(hwnd, &ps);
                    pDirect2dWindow->OnRender();
                    EndPaint(hwnd, &ps);
                }
                result = 0;
                wasHandled = true;
                break;

            case WM_DESTROY:
                {
                    PostQuitMessage(0);
                }
                result = 1;
                wasHandled = true;
                break;
            }
        }

        if (!wasHandled)
        {
            result = DefWindowProc(hwnd, message, wParam, lParam);
        }
    }

    return result;
}
タグ:Direct2D
posted by S.F. at 21:12| 千葉 | Comment(0) | TrackBack(0) | Library | このブログの読者になる | 更新情報をチェックする

Native Client

Native Clientのサンプルを少し見てみた。
http://nativeclient.googlecode.com/svn/data/docs_tarball/nacl/googleclient/native_client/tests/npapi_hw/npapi_hw.c
見た感じは、COMのdispatch interfaceっぽい。
variantとか、invokeとかPropertyとか。。。
http://msdn.microsoft.com/en-us/library/ms221608.aspx
なので、ソースコードレベルで見るとあまり新しく感じないのが意外であった。スクリプトとネイティブとのインターフェース部分という限定された世界の中のことなので、みな似たようなものになってくるということなのだろうか。

ただ、Naclの場合コンパイラが特殊なバイナリを吐き、セキュリティが保たれるという部分が違うので、アセンブラレベルで見たほうが目新しく感じるのかもしれない。そこまでする気はないが。


posted by S.F. at 21:01| 千葉 | Comment(0) | TrackBack(0) | Library | このブログの読者になる | 更新情報をチェックする

2009年11月04日

Blender

Blenderも息が長いね。。
http://blender.jp/
posted by S.F. at 21:31| 千葉 晴れ| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

鉄人28号

神戸に鉄人28号が設置されるのか。。
なんか作者とゆかりがあるのだろうか。
posted by S.F. at 06:42| 千葉 | Comment(0) | TrackBack(0) | etc | このブログの読者になる | 更新情報をチェックする

2009年11月03日

R.S. vol.1 [ HD ] 3DCG 自主制作アニメ 第1話 : 牛山雅博

こういうのが自主制作できる世の中なのか。。。
しかも製作年が2004年とは。。。

posted by S.F. at 19:29| 千葉 晴れ| Comment(0) | TrackBack(0) | etc | このブログの読者になる | 更新情報をチェックする

組織は合理的に失敗する

「組織は合理的に失敗する」をななめ読了。

組織は合理的に失敗する(日経ビジネス人文庫)

組織は合理的に失敗する(日経ビジネス人文庫)

  • 作者: 菊澤 研宗
  • 出版社/メーカー: 日本経済新聞出版社
  • 発売日: 2009/09/02
  • メディア: 文庫



posted by S.F. at 17:48| 千葉 晴れ| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

_com_ptr_t

Windows7のDirect2Dハンズオン・ラボ(http://msdn.microsoft.com/ja-jp/windows/ee427969.aspx)を見ていて気づいたのだけれど、COMインターフェースのスマートポインタの定義に下記マクロを使っていた。

_COM_SMARTPTR_TYPEDEF(IMyInterface , __uuidof(IMyInterface))

VC 2008 Expressで検索すると、上記マクロ定義するとIMyInterfacePtrというcom_ptr_tのtypedefが生成されると書いてあった。
http://msdn.microsoft.com/ja-jp/library/417w8b3b(VS.100).aspx
なのでVC限定だが、COMスマートポインタを自作したり、boost::instrusive_ptrを使わなくてもよかったのだった。

posted by S.F. at 15:28| 千葉 晴れ| Comment(0) | TrackBack(0) | Library | このブログの読者になる | 更新情報をチェックする

HTML5 canvas - Burn DEMO

またしても古いでもコードより引っ張ってきてcanvasに移植。
<html>
<head>
<title>Sample0005(Burn Demo)</title>
<script type="text/javascript" >

/*--------------------------------------------------------------------
  Fire Effect デモ by SFPGMR.
  元ネタ:Frank Jan Sorensenさんのパスカルコード
	元ソースコードのヘッダコメント 
	Hi guys, try this, use it in your code, but please credit
	Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk) for the
	fireroutine.
  --------------------------------------------------------------------*/



var ctx;
var bufimg;
var w,h;
var dt;
var WIDTH = 320;
var HEIGHT = 200;
var buffer = new Array(WIDTH * HEIGHT);
var maxColor     = 256;  // Constant for the MakePal procedure 
var palette = new Array(maxColor);
var rootRand     =  20;//  Max/Min decrease of the root of the flames 
var decay        =  5;//  How far should the flames go up on the screen?
var minY         = 10;//  Startingline of the flame routine.
                       //  (should be adjusted along with MinY above) 
var smooth       =   2;//  How descrete can the flames be?
var minFire      =  50;//  limit between the "starting to burn" and
                       //  the "is burning" routines 
var xStart       =  50;//  Startingpos on the screen}
var xEnd         = 270;//  Guess! 
var flameWidth        = xEnd - xStart;// Well- 
var fireIncrease  =   100;// 	3 = Wood, 90 = Gazolin 
var flameArray = new Array(flameWidth);// frame Array
var keyBuffer = new Array(0);
var moreFire = 1;

function rgb(hue, saturation, intensity)
{
  var T = 256.9999 * intensity / 2.0;
  this.r = Math.floor((1.0 + saturation * Math.sin(hue - 2.0 * Math.PI / 3.0)) * T);
  this.g = Math.floor((1.0 + saturation * Math.sin(hue)) * T);
  this.b = Math.floor((1.0 + saturation * Math.sin(hue + 2.0 * Math.PI / 3.0)) * T);
  
}

/*
function rgb(r,g,b)
{
	this.r = r;
	this.g = g;
	this.b = b;
}
*/
function pset(x,y,r,g,b,a)
{
	var st = (x + w * y) * 4;
	dt[st++] = r;
	dt[st++] = g;
	dt[st++] = b;
	dt[st++] = a;
}

function init()
{
	var log = "";
	for(var i = 0; i < 256; ++i)
	{
		palette[i] = new rgb(4.6 - 1.5 * i / 64,i / 64.0,i / 64.0);
	}

	for(var i = 0; i < WIDTH*HEIGHT;++i)
	{
		buffer[i] = 0;
	}

	for(var i = 0; i < flameWidth;++i)
	{
		flameArray[i] = 0;
	}

}

function draw()
{	
	// get keycode
	var keyCode = ""
	if(keyBuffer.length > 0)
	{	keyCode = keyBuffer.shift();
	}
	
	// Put the values from FlameArray on the bottom line of the screen
	for(var i = 0;i < flameWidth;++i)
	{
		buffer[i + xStart + 199 * WIDTH] = flameArray[i];
	}
	
	//This loop makes the actual flames
	for(var i = xStart ; i < xEnd; ++i)
	{
		for(var j = minY; j < 200;++j)
		{
			var v = buffer[i + j * WIDTH];
			if(v == 0 || v < decay || i <= xStart || i >= xEnd) 
			{
				buffer[i + (j - 1) * WIDTH] = 0;
			} else {
				buffer[i - (Math.floor((Math.random() * 3)) - 1) + (j - 1) * WIDTH] = v - Math.floor(Math.random() * decay);
			}
		}
	}
	
	if(Math.floor(Math.random() * 150) == 0 || keyCode == "F")
	{
		var r = Math.floor(Math.random() * (flameWidth - 5));
		for(var i = r;i < (r + 5); ++i)
		{
			flameArray[i] = 255;
		}
	}
	
	if((keyCode == "A") && (moreFire >-2))
	{
		--moreFire;
	}
	
	if((keyCode == "S") && (moreFire < 4))
	{
		moreFire++;
	}
	
	if(keyCode >= "1" && keyCode <= "9")
	{
		fireIncrease = 3 + parseInt(keyCode) * 20;
	}
	
	for(var i = 0; i < flameWidth;++i)
	{
		var x = flameArray[i];
		if(x < minFire) {
			if(x > 10) { x += Math.floor(Math.random() * fireIncrease); }
		} else {
			x += Math.floor(Math.random(rootRand * 2 + 1) - rootRand + moreFire);
		}
		if(x > 255) x = 255;
		flameArray[i] = x;
	}
	
	for(var i = 1; i < (flameWidth / 8);++i)
	{
		var X = Math.floor(Math.sqrt(Math.random()) * flameWidth / 8);
		flameArray[X] = 0;
		flameArray[flameWidth - 1 - X] = 0;
	}
	
	for( var i = smooth ; i <  (flameWidth - smooth) ; ++i)
	{
		var X = 0;
		for(var j = -smooth ; j < smooth;++j)
		{
			X += flameArray[i+j];
		}
		flameArray[i] = Math.round(X / (2 * smooth  + 1));
	}
	var b = bufimg.data;
	for(var i = 0; i < WIDTH * HEIGHT; ++i)
	{
		b[i * 4 ] = palette[buffer[i]].r;
		b[i * 4 + 1] = palette[buffer[i]].g;
		b[i * 4 + 2] = palette[buffer[i]].b;
		b[i * 4 + 3] = 255;
	}
	ctx.putImageData(bufimg,0,0);
}

document.onkeydown = function()
{
	keyBuffer.push(String.fromCharCode(event.keyCode).toUpperCase());
}

window.onload = function()
{
	ctx = document.getElementById("ctx").getContext("2d");
	w = document.getElementById("ctx").flameWidth;
	h = document.getElementById("ctx").height;
	bufimg = ctx.createImageData(WIDTH,HEIGHT);
	init();
}


</script>
</head>
<body>
<div>Burn Demo</div>
<div>キー操作:フルキー1〜9 火勢調節 </div>
<input type="button" onclick="timerID = window.setInterval(draw,10);" value="Start"/ >
<input type="button" onclick="window.clearInterval(timerID);" value="Stop"/ >
<div>
<canvas id="ctx" width="320" height="200" style="border:1px solid gray;"></canvas>
</div>
</body>
</html>

タグ:Canvas HTML5
posted by S.F. at 11:38| 千葉 霧| Comment(0) | TrackBack(0) | HTML | このブログの読者になる | 更新情報をチェックする

2009年11月02日

オオカミとブタ。Stop motion with wolf and pig.

すごいな。デジカメだからこそできるんだろうけど、、、。
作品も凄いが、それにしてもこれに費やした労力にもっと凄さを感じる。
posted by S.F. at 22:10| 千葉 曇り| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

Direct2D入門

Direct2D入門。よくまとまっている。こういうページを見ると尊敬する。
http://www.tkzdev.net/

Direct2DとGDIの描画速度の違い。
http://zoome.jp/pcuser/diary/14
posted by S.F. at 21:59| 千葉 曇り| Comment(0) | TrackBack(0) | Library | このブログの読者になる | 更新情報をチェックする

2009年11月01日

Fireエフェクト

どこかでゲットしたすごい古いコードをVistaで動かしてみた。
もともとはWin3.1用であったが、WinGの部分をDIBに置き換えたらあっさり動いた。
(たぶん作者はhttp://www.terra.es/personal3/jare70/
20091031Fire.png
// ------------------------ WINFIRE.CPP ------------------------------
// Win32 port By S.F. 2009.11.1.
// もとネタは下記コメントを参照。WinGで組まれていたのをDIBに置き換えた。
// ---------------
// Coded bye Jare of Iguana near Xmas of 1994
// Comments to a880104@zipi.fi.upm.es
// My original ASM routine was 200 lines of plain ASM, this Windows
// version goes up to near 500 lines!!
// You can use this for anything you like, but you must credit me.

#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <string.h>

    // Fire array size.
#define FIREW 128
#define FIREH  96
    // Nice size for the window. Frame will take some bits apart, however.
#define WINDOWW FIREW*4
#define WINDOWH FIREH*4

    // Handy msg structure.
typedef struct {
    HWND    hwnd;
    UINT    msg;
    WPARAM  wParam;
    LPARAM  lParam;
} tMSG, *pMSG;

    // Low Level data types.
typedef unsigned char  byte;
typedef unsigned short word;
typedef unsigned long  dword;

typedef byte  * Pbyte;
typedef word  * Pword;
typedef dword * Pdword;

typedef byte  FAR * LPbyte;
typedef word  FAR * LPword;
typedef dword FAR * LPdword;

// ===============================================================
// WinG DC handling functions.

struct dc {
	dc(HWND h): h_(h) {dc_ = GetDC(h);}
	~dc(){ReleaseDC(h_,dc_);}
	operator HDC() {return dc_;}

private:
	HDC dc_;
	HWND h_;
};

    // The stock default bitmap of a WinGDC.
static HBITMAP hBitmapMonochrome = 0;

    // Creates a top-down WinGDC with the specified rgb palette.
    // Returns the HDC and stores the bitmap pointer in ppSurfaceBits,
    // if not passed a NULL parameter.

HDC MakeWinGDC(HWND hwnd,RGBQUAD rgb[256], LPbyte *ppSurfaceBits) {
    HBITMAP hBitmapNew;
    int     i;
	static BITMAPINFO info;
	

        // Force top-down 8-bit bitmap of size FIREW*FIREH.
    info.bmiHeader.biSize         = sizeof(info.bmiHeader);
    info.bmiHeader.biPlanes       = 1;
    info.bmiHeader.biBitCount     = 8;
    info.bmiHeader.biCompression  = BI_RGB;
    info.bmiHeader.biSizeImage    = 0;
    info.bmiHeader.biClrUsed      = 0;
    info.bmiHeader.biClrImportant = 0;
    info.bmiHeader.biWidth        = FIREW;
    info.bmiHeader.biHeight       = -FIREH;    // Minus for top-down.

    for (i = 0; i < 256; i++)
        info.bmiColors[i] = rgb[i];

    // Create a WinGDC and Bitmap, then select away DC's default
    // monochrome bitmap.
	dc hdc(hwnd);
	hBitmapNew = ::CreateDIBSection(hdc,&info,DIB_RGB_COLORS,(void**)ppSurfaceBits,NULL,NULL);
	HDC dcBitmap = ::CreateCompatibleDC(hdc);
	hBitmapMonochrome = (HBITMAP)SelectObject(dcBitmap,hBitmapNew);
	return dcBitmap;
}

    // Finishes the WinGDC. Pretty straightforward.

static void EndWinGDC(HDC hWinGDC) {
    HBITMAP hBitmapOld;
    if (hWinGDC && hBitmapMonochrome) {
            // Select the stock 1x1 monochrome bitmap back in
        hBitmapOld = (HBITMAP)SelectObject(hWinGDC,
                                           hBitmapMonochrome);
        hBitmapMonochrome = 0;
        DeleteObject(hBitmapOld);
        DeleteDC(hWinGDC);
    }
}

    // Creates a palette from the specified colors, but requires
    // using the system colors. Updates 'rgb' to enable the use of an
    // identity palette i.e. on exit, rgb contains the effective
    // palette, that can in turn be used for creating the WinGDC.

static HPALETTE CreateIdentityPalette(RGBQUAD aRGB[256], int nColors) 
{
    int i;
    static struct {
        WORD         Version;
        WORD         NumberOfEntries;
        PALETTEENTRY aEntries[256];
    } pal = {
        0x300,
        256
    };
        // For SYSPAL_STATIC, get the twenty static colors into
        // the array, then fill in the empty spaces with the
        // given color table
 
	{
		dc sysdc(NULL);
        // Get the static colors
		GetSystemPaletteEntries(sysdc, 0,   10, pal.aEntries);
		GetSystemPaletteEntries(sysdc, 246, 10, pal.aEntries + 246);

			// Set the peFlags of the lower static colors to zero.
			// And copy the static colors to the user palette so
			// the caller knows exactly which palette we created.
		for (i = 0; i < 10; i++) {
			aRGB[i].rgbRed   = pal.aEntries[i].peRed;
			aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
			aRGB[i].rgbBlue  = pal.aEntries[i].peBlue;
			pal.aEntries[i].peFlags = 0;
		}

			// Fill in the entries from the given color table
		for (; i < nColors+10; i++) {
			pal.aEntries[i].peRed   = aRGB[i].rgbRed;
			pal.aEntries[i].peGreen = aRGB[i].rgbGreen;
			pal.aEntries[i].peBlue  = aRGB[i].rgbBlue;
			pal.aEntries[i].peFlags = PC_RESERVED;
		}

			// Mark any empty entries as PC_RESERVED
		for (; i < 246; i++) {
			aRGB[i].rgbRed   = pal.aEntries[i].peRed;
			aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
			aRGB[i].rgbBlue  = pal.aEntries[i].peBlue;
			pal.aEntries[i].peFlags = PC_RESERVED;
		}

			// Set the peFlags of the upper static colors to zero, and
			// copy static colors.
		for (; i < 256; i++) {
			aRGB[i].rgbRed   = pal.aEntries[i].peRed;
			aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
			aRGB[i].rgbBlue  = pal.aEntries[i].peBlue;
			pal.aEntries[i].peFlags = 0;
		}

	}

        // Create the palette
    return CreatePalette((LOGPALETTE *)&pal);
}

// ===============================================================
// Fire algorithm. Pure C, ASM will do it much faster.

static void DoFire(Pbyte to, Pbyte from) {
    int i, j;

    from += FIREW;
    to   += 0;

        // All lines but the first and last. The first will disappear,
        // and the last must be taken with care for the limits of the
        // array.
    for (i = 1; i < FIREH-1; i++) {
            // Leftmost pixel.
        *to++ = (byte)((  (word)from[-1]          + (word)from[1]
                        + (word)from[-(int)FIREW] + (word)from[FIREW]) >> 2);
        from++;
            // Middle pixels.
        for (j = 1; j < FIREW-1; j++) {
            *to++ = (byte)((  (word)from[-1]            + (word)from[1]
                            + (word)from[-(int)FIREW-1] + (word)from[-(int)FIREW+1]
                            + (word)from[+(int)FIREW-1] + (word)from[+(int)FIREW+1]
                            + (word)from[-(int)FIREW]   + (word)from[FIREW]
                           ) >> 3);
            from++;
        }
            // Rightmost pixel.
        *to++ = (byte)((  (word)from[-1]          + (word)from[1]
                        + (word)from[-(int)FIREW] + (word)from[FIREW]) >> 2);
        from++;
    }
        // Bottom line.
    for (j = 0; j < FIREW-1; j++) {
        *to++ = (byte)((  (word)from[-1]          + (word)from[1]
                        + (word)from[-(int)FIREW] + (word)from[0]) >> 2);
        from++;
    }
        // Rightmost pixel of bottom line.
    *to = (byte)(((word)from[-1] + (word)from[-(int)FIREW]) >> 1);
}

// ===============================================================
// Fire Window message handlers.

    // Global vars.
static HINSTANCE AppInstance;       // ditto.

static HDC      ScreenHDC;          // WinGDC created.
static LPbyte   Screen;             // Pointer to the surface bitmap.
static UINT     Timer;              // Timer identifier.
static RGBQUAD  rgb[256];           // Palette used.
static HPALETTE Palette;            // Handle to it.
static int      WindowState;        // Minimized, maximized or normal?
static HICON    FireIcon;           // Handle to icon for QueryDragIcon.

    // Fire buffers. FAR so the are in their own data segment.
static byte FireBuf1[FIREW*FIREH], FireBuf2[FIREW*FIREH];
static Pbyte Buf1 = FireBuf1, Buf2 = FireBuf2;

// ---------- Message handlers.

static LRESULT wmCreate(pMSG msg) {
    int     i;

    FireIcon = LoadIcon(AppInstance, "FIREICON");

        // Create a smooth palette.
    memset(rgb, 0, sizeof(rgb));
    for (i = 10; i < 10+16; i++)
        rgb[i].rgbRed   = (BYTE)((i-10)*16);
    for (; i < 10+48; i++) {
        rgb[i].rgbRed   = 255;
        rgb[i].rgbGreen = (BYTE)((i-10-16)*8);
    }
    for (; i < 10+80; i++) {
        rgb[i].rgbRed   = 255;
        rgb[i].rgbGreen = 255;
        rgb[i].rgbBlue  = (BYTE)((i-10-48)*8);
    }
    for (; i < 10+236; i++) {
        rgb[i].rgbRed   = 255;
        rgb[i].rgbGreen = 255;
        rgb[i].rgbBlue  = 255;
    }

        // Clean up buffers.
    memset(FireBuf1, 0, sizeof(FireBuf1));
    memset(FireBuf2, 0, sizeof(FireBuf2));

        // Create stuff.
    Palette   = CreateIdentityPalette(rgb, 236);
	ScreenHDC = MakeWinGDC(msg->hwnd,rgb, &Screen);
    WindowState = SC_RESTORE;
    Timer     = SetTimer(msg->hwnd, 1, 1, NULL);
    return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
}

static LRESULT wmDestroy(pMSG msg) {
    KillTimer(msg->hwnd, Timer);
    EndWinGDC(ScreenHDC);
    if (Palette != 0)
        DeleteObject(Palette);
    DestroyIcon(FireIcon);
    return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
}

static LRESULT wmTimer(pMSG msg) {
    HDC     hdc;
    int     i;
    LPdword p;
    Pdword  q;
    Pbyte   s;
    RECT    r;

        // Clean bottom line.
    memset(Buf2 + FIREW*(FIREH-1), 0, FIREW);
        // Set random hot spots and animate.
    for (i = 0; i < 20; i++) {
        int k = rand() % (FIREW-2);
        Buf2[FIREW*FIREH - k] = 235;
    }
    DoFire(Buf1, Buf2);

        // Copy buffer to the WinGDC bitmap, adding 10 for the colors.
    p = (LPdword)Screen;
    q = (Pdword)Buf1;
    for (i = 0; i < FIREH*FIREW/4; i++)
        *p++ = *q++ + 0x0a0a0a0a;

        // Swap buffers.
    s = Buf1;
    Buf1 = Buf2;
    Buf2 = s;

        // Dump bitmap.
    GetClientRect(msg->hwnd, &r);
    hdc = GetDC(msg->hwnd);
    SelectPalette(hdc, Palette, FALSE);
    RealizePalette(hdc);

        // If window is not minimized or maximized, do optimal stretch
        // by multiplying by 2^2, else stretch to whatever the size.
        // Vertical stretch can be anything, as it doesn't slow down
        // if it's not stretched by a power of two.
    if (WindowState == SC_MINIMIZE || WindowState == SC_MAXIMIZE)
	{
		
        StretchBlt(hdc, 0, 0, r.right-r.left, r.bottom-r.top,
                       ScreenHDC, 0, 0, FIREW, FIREH,SRCCOPY);
	} else {
        StretchBlt(hdc, 0, 0, WINDOWW, r.bottom-r.top,
                       ScreenHDC, 0, 0, FIREW, FIREH,SRCCOPY);
	}

    ReleaseDC(msg->hwnd, hdc);

    return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
}

static LRESULT wmQueryNewPalette(pMSG msg) {
    HDC hdc;
    LRESULT f;

    hdc = GetDC(msg->hwnd);
    if (Palette)
        SelectPalette(hdc, Palette, FALSE);
    f = RealizePalette(hdc);
    ReleaseDC(msg->hwnd, hdc);
    return f;
}

static LRESULT wmSysCommand(pMSG msg) {
    if (msg->wParam == SC_MINIMIZE ||
        msg->wParam == SC_MAXIMIZE ||
        msg->wParam == SC_RESTORE)
        WindowState = msg->wParam;
    return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
}

static LRESULT wmWindowPosChanging(pMSG msg) {
    LPWINDOWPOS lpwp;
    RECT rw, rc;
    int  x, w;

        // If window is not maximized or minimized, align its client
        // area to a four-pixel boundary for optimal performance.
    if (WindowState == SC_RESTORE) {
        lpwp = (LPWINDOWPOS)msg->lParam;
        GetWindowRect(msg->hwnd, &rw);
        GetClientRect(msg->hwnd, &rc);
        w = rw.right - rw.left - (rc.right - rc.left); // Width of frame.
        x = lpwp->x + w;
        lpwp->x = (x & ~3) - w;   // Align it.
        if (lpwp->cx - w > WINDOWW)
            lpwp->cx = w + WINDOWW;
    }
    return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
}


    // Window procedure.
LRESULT CALLBACK FireWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    tMSG m;

    m.hwnd   = hwnd;
    m.msg    = msg;
    m.wParam = wParam;
    m.lParam = lParam;

    switch (msg) {
        case WM_CREATE:        return wmCreate(&m);
        case WM_DESTROY:       return wmDestroy(&m);
        case WM_QUERYDRAGICON:
            if (FireIcon != (HICON)NULL)
                return (LRESULT)FireIcon;
            break;

        case WM_TIMER: return wmTimer(&m);

        case WM_PALETTECHANGED:
            if ((HWND)wParam != hwnd)   // If we changed the palette.
                return wmQueryNewPalette(&m);
            break;
        case WM_QUERYNEWPALETTE: return wmQueryNewPalette(&m);

        case WM_WINDOWPOSCHANGING: return wmWindowPosChanging(&m);
        case WM_SYSCOMMAND:        return wmSysCommand(&m);

        case WM_CLOSE:
            PostQuitMessage(0);
            break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

// ===============================================================
// Main entry point.

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {
    static char ClassName[] = "WinFire";
    static char AppName[]   = "WinFire";
            int w, h;
            MSG msg;
           HWND hwnd;

    if (hPrev == 0) {
        WNDCLASS c;

        c.hCursor       = LoadCursor(NULL, IDC_WAIT);
        c.hIcon         = NULL;
        c.lpszMenuName  = NULL;
        c.lpszClassName = "WinFire";
        c.hbrBackground = NULL;
        c.hInstance     = hInst;
        c.style         = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
        c.lpfnWndProc   = (WNDPROC)FireWndProc;
        c.cbWndExtra    = 0;
        c.cbClsExtra    = 0;
        if (!RegisterClass(&c))
            return 1;
    }

    AppInstance = hInst;
    w = GetSystemMetrics(SM_CXSCREEN);
    h = GetSystemMetrics(SM_CYSCREEN);

    hwnd = CreateWindow (ClassName,                // Class name
                         AppName,                  // Caption
                         WS_OVERLAPPEDWINDOW,      // Style bits
                         (w-WINDOWW)/2, (h-WINDOWH)/2, // Position
                         WINDOWW, WINDOWH,             // Size
                         (HWND)NULL,               // Parent window (no parent)
                         (HMENU)NULL,              // no menu
                         hInst,                    // handle to window instance
                         (LPSTR)NULL               // no params to pass on
                        );
    if (hwnd == (HWND)NULL)
        return 1;
    ShowWindow(hwnd, sw);

    while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

// ------------------------ WINFIRE.CPP ------------------------------


タグ:Win32API
posted by S.F. at 14:40| 千葉 晴れ| Comment(0) | TrackBack(0) | etc | このブログの読者になる | 更新情報をチェックする

WASAPI(21)

JUCEにはAudioIODeviceという基本クラスがあり、DirectSoundやASIOはこれを継承し、具象クラスとして実装されている。

以前にも書いたが、JUCEの作者はすでにWASPIの共有モードでのAudioIODevice具象クラスWASAPIIODeviceを作成している。掲示板で見る限り良好に動いているようだ。
http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=4404

しかし、やはりWASAPIは排他モードで行ったほうが、よりレイテンシの低いサウンド再生ができるので、私は排他モードで動かすIODeviceに拘り実装を続けている。

もう少しで音を鳴らせるのだけれど、とにかく音だけを出したいっていう方針で進めてきたので、多少強引なコードになってしまっている。
デバッグしていて気づいたのだけれど、今の自分の実装だと「エンドポイントはステレオで、In・Outはサンプリングレートが同じで周波数も同じが前提!」というコードになってしまっているので融通が利かない。この部分をいろいろなデバイスに可能な限り柔軟にサポートできるようにしようかなと思っている。

もうすぐまとまった休みが取れる(9日間)ので、そのときに一気に実装してしまいたいなと考えている。
posted by S.F. at 11:18| 千葉 霧| Comment(0) | TrackBack(0) | WASAPI | このブログの読者になる | 更新情報をチェックする

PUMA

Protected User Mode Audio (PUMA)の解説記事。
http://msdn.microsoft.com/ja-jp/windows/dd637384.aspx
http://www.microsoft.com/japan/whdc/device/media/output_protect.mspx
タグ:PUMA
posted by S.F. at 07:45| 千葉 霧| Comment(0) | TrackBack(0) | WASAPI | このブログの読者になる | 更新情報をチェックする