パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください -29ページ目

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

こんな↓波形です。
ソフトウエア開発(android・iphone・windows・java等)の事なら株式会社パークにお任せください_パク太郎のソフトウエア開発者ブログ

周期ごとの場合分けと、位相と周波数の考え方は前回の矩形波とほぼ一緒です。

では早速サンプリング間隔nInterval(ms)のデータにおけるデータ数:nDataNum
振幅:dbAmp(dBやVolt等) 周波数:dbFrequency(Hz) 位相:dbPhase(度) オフセット:dbOffset

ののこぎり波を作成してみます。


int nInterval // サンプリング間隔(ms)
double dbOffset // 縦軸オフセット(0点)
double dbAmp // 振幅(dBやVolt等)
double dbFrequency // 周波数(Hz)
double dbPhase // 位相(度)

for( nDataCnt = 0; nDataCnt < nDataNum; nDataCnt++ )
{
nRemain = (int)( nInterval * nDataCnt - 1000 * dbPhase / 360 ) % (int)( 1000 / dbFrequency );

if( 0 == nRemain || 500/dbFrequency == nRemain || -500/dbFrequency == nRemain )

adWaveData[ nDataCnt ] = dbOffset;

if( -1000 < nRemain && nRemain < -500/dbFrequency )

adWaveData[ nDataCnt ] = dbAmp * nRemain / ( 500 / dbFrequency ) + dbOffset + 2 * dbAmp;

else if( -500/dbFrequency < nRemain && nRemain < 0 )

adWaveData[ nDataCnt ] = dbAmp * nRemain / ( 500 / dbFrequency ) + dbOffset;

else if( 0 < nRemain && nRemain < 500/dbFrequency )

adWaveData[ nDataCnt ] = dbAmp * nRemain / ( 500 / dbFrequency ) + dbOffset;

else if( 500/dbFrequency < nRemain && nRemain < 1000/dbFrequency )

adWaveData[ nDataCnt ] = dbAmp * nRemain / ( 500 / dbFrequency ) + dbOffset - 2 * dbAmp;
}

nRemainが現在の横軸の点の位置になります。
nDataCntがインクリメントするごとにサンプリング間隔毎に点が移動するので、
nInterval * nDataCnt(ms)になります。

更に位相ずれ分を考慮した部分が - 1000 * dbPhase / 360 になります。

全体を最終的に % (int)( 1000 / dbFrequency ) してる部分が作成したい波形の
周期を考慮した部分です。
これにより、nInterval * nDataCnt(ms)部分が周期を超えたらnRemainが0に戻ります。
この部分が周期関数を実現している部分になります。

基本形は右上がりの一次式(y=ax+b)が連続しているだけなので
dbAmp / ( 500 / dbFrequency ) が傾き(a)の部分でそれに nRemain(x) をかけると 
dbAmp * nRemain / ( 500 / dbFrequency )
となり、場合分け毎全ての式における共通の部分です。

問題は場合ごとに違う(b:一次式のy切片)の部分です。

dbOffsetは波形の縦軸方向中間位置を表し、波形全体を縦軸方向に平行移動させます。
場合分け毎全ての式において共通の部分です。
以下場合分け毎のy切片の説明です。

・-1000 < nRemain && nRemain < -500/dbFrequencyの時は
 y軸(x=0)よりもマイナス方向にあるので、y切片は dbOffset + 2 * dbAmp となります。

・500/dbFrequency < nRemain && nRemain < 1000/dbFrequency の時は、
 y軸(x=0)よりもプラス方向にあるので、y切片は dbOffset - 2 * dbAmp となります。

・-500/dbFrequency < nRemain && nRemain < 0 及び
 0 < nRemain && nRemain < 500/dbFrequency の時はy軸を通るので、
 dbOffset となります。

・0 == nRemain || 500/dbFrequency == nRemain || -500/dbFrequency == nRemain の時
 前回矩形波同様丁度上下限になる瞬間の切れ目の部分
 dbOffset となります。
 これがないと、中途半端な周波数などの場合は上限値⇔下限値に
 移行する際の点が未定義になって波形が切れたりするのでしたね。
 (前回矩形波時と同様)

次回は更に別の波形の紹介をしたいと思います。
では、また。
Joseph Albahariさんの作ったLINQPadは、.NETコードのスクラッチパッドとして使える便利なアプリケーションです。
この記事を書いた時点ではhttp://www.linqpad.net/でダウンロードできます。

ちょっとした使い方をご紹介します。

起動するとこんな感じです↓
$ソフトウエア開発(android・iphone・windows・java等)の事なら株式会社パークにお任せください_パク太郎のソフトウエア開発者ブログ

例えば、組み立てたXElementが正しいかちょっと確認したいなーってときは、↓です。
$ソフトウエア開発(android・iphone・windows・java等)の事なら株式会社パークにお任せください_パク太郎のソフトウエア開発者ブログ

アセンブリの参照もできます。F4でQuery Propertiesを開いてdllを追加すれば、↓
$ソフトウエア開発(android・iphone・windows・java等)の事なら株式会社パークにお任せください_パク太郎のソフトウエア開発者ブログ

MessageBox.Show()もできちゃいます↓
$ソフトウエア開発(android・iphone・windows・java等)の事なら株式会社パークにお任せください_パク太郎のソフトウエア開発者ブログ

とても便利なので是非使ってみてください。
Tです。

お隣の国では政府検閲でFacebookやTwitterなどへのアクセスが規制されていますね。
ポータルやニュースサイトへアクセスしようとしても、その先にFacebookへのリンクが
あると影響を受けて開けない…なんてことも。

近い国ですからビジネスや旅行で行かれる方も多いかと思います。
これはホント困りますね。

そこでご紹介したいのが筑波大学と民間会社の共同研究プロジェクトです。

utvpn

学術的なお話はさておき、こちらでVPN中継サーバを公開していますので先ずは使ってみましょう。

ただし、ここも当然検閲対象になっているため直接URLを入力してもアクセス出来ません。
旅先でも簡単に使えるwebメールを宛先にメール配信サービスに登録しておくといいですよ。

接続方法も詳しく記述されていますのでお試しになってはいかがでしょうか?
開発をしているとテストを行うが、テストを自動化していると
同じようなテストコードを書くようなことがある。

テストを行うメソッドのパラメータに違う値を指定したり・・・・。

そこで、面倒くさいコード作成を簡単にできないかと思い。
NUnitを調べて[TestCase]属性を見つけた。

実際のシステム開発のテストコードに記載したことはないが
使えそうだなぁ~と思っている。
(テストコードを削減できると思う)

まぁ、くどくど説明するよりコードを見た方が分かりやすいとおもう。


-----------------------------------------------------
○サンプル

using System;
using NUnit.Framework;

namespace SampleTest
{
[TestFixture]
class TestClass
{
    ///
/// TestCaseに指定したパラメータがTest1のパラメータに指定されて
/// NUnitがテストしてくれる
/// 下記のようなにパラメータに指定してテストが行われる
    /// Test1("A1","A",1)
    /// Test1("B2","B",2)
    /// Test1("C3","C",3)
    ///

[TestCase("A1","A",1)]
[TestCase("B2","B",2)]
[TestCase("C3","C",3)]
public void Test1(string result, string str, int num)
{
// string.Formatの戻り値がresultと同じかをテスト
Assert.AreEqual(result, string.Format("{0}{1}",str,num));
}

    ///
/// TestCaseに指定したパラメータがTest1のパラメータに指定されて
/// NUnitがテストしてくれる
/// 下記のようなテストが行われる。Test2の結果がResult= と同じかをチェックする
    /// Test1("A",1)
    /// Test1("B",2)
    /// Test1("C",3)
    ///

[TestCase("A",1, Result = "A1")]
[TestCase("B",2, Result = "B2")]
[TestCase("C",3, Result = "C3")]
public string Test2(string str, int num)
{
// string.Formatの戻り値がresultと同じかをテスト
return string.Format("{0}{1}",str,num);
}
}
}

テストコードは、実装のコード量より、
コード量が多いので作成するが大変・・・・
今度、実際のテストコードで試してみて
どれだけテストコードを簡単に作成できるか試してみたいと思う。

では、さらば。
@some
さて、今回は前回の記事の続きでAndroidでのOpenGLの使い方の続きを解説します。
前回はOpenGLを動作させるためのソースを記述しました。
今回は書いたソースについて解説していきます。

まずはMainActivityから見て行きましょう。


package com.example.opengl_test;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity {
private MyGLView myGLView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGLView = new MyGLView(this);
setContentView(myGLView);
}

@Override
protected void onResume() {
super.onResume();
myGLView.onResume();
}

@Override
protected void onPause() {
super.onPause();
myGLView.onPause();
}
}



AndroidアプリはこのMainActivityから始まるため、このソースは詳細な意味を覚えるよりこういうお作法とおぼえておいたほうがいいです。
そして上で強調した行はActivityからOpenGL表示用のビューを呼び出しています。

次にMyGLViewを見てみましょう。


package com.example.opengl_test;

import android.content.Context;
import android.opengl.GLSurfaceView;

public class MyGLView extends GLSurfaceView {
private MyRenderer myRenderer;

public MyGLView(Context context) {
super(context);

myRenderer = new MyRenderer();
setRenderer(myRenderer);
}
}


ここではビューにOpenGL描画用のレンダーを登録しています。

次にMyRendererを見てみましょう。


package com.example.opengl_test;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;

public class MyRenderer implements Renderer {
MyCube cube = new MyCube();

@Override
public void onDrawFrame(GL10 arg0) {
// 背景色を設定
arg0.glClearColor(0, 0, 1, 1.0f);
arg0.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

arg0.glMatrixMode(GL10.GL_MODELVIEW);
arg0.glLoadIdentity();
arg0.glTranslatef(0, 0, -3f);

arg0.glRotatef(30f, 0, 1, 0);
arg0.glRotatef(30f, 1, 0, 0);

cube.draw(arg0);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45f, (float) width / height, 1f, 50f);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glDepthFunc(GL10.GL_LEQUAL);
}

}


ここでは3つのメソッドが登場します。
上から順番に見て行きましょう。

まず一番上で登場するonDrawFrameメソッドはアプリの描画の際に繰り返し呼ばれます。
ですので描画処理は基本的にはこちらで行うことになります。

次にonSurfaceChangedメソッドについてですが、こちらは主に画面の向きが縦から横へ、
またはその逆に切り替わった時に呼ばれます。
そのため基本的な画面設定はこちらに書きます。

最後にonSurfaceCreatedメソッドについてなのですが、こちらはレンダークラスの初期化時に呼ばれます。

ではメソッドの中身を一つづつ見て行きましょう。
まずは初期化時に呼ばれるonSurfaceCreated之中身についてですが、ここでは主に描画の設定を行っています。
まず上から3つのglEnableメソッドについては3Dの描画を行う上での機能を有効化しています。
GL_DEPTH_TESTは名前の通りデプステストを、GL_LIGHTINGは光源のライティングを、GL_LIGHT0は使う光源の番号を設定しその高原を有効化しています。
最後のglDepthFuncについては深度値と深度バッファの震度を比較する関数の指定を行っています。
今回指定しているGL_LEQUALは入って来る深度値が格納された深度値以下である時に通過を設定しています。

次にonSurfaceChangedを見ていきます。
ここでは画面の設定を行っています。
まず画面の範囲を指定します。
その後画面のパースペクティブを登録し、どの端末でも同じように描画できるよう設定します。

最後にonDrawFrameを見ていきます。
まず最初の2行について見てみます。
こちらは背景色を設定しています。

次の3行についてですが、ここでは実際に指定した座標にものを描画するという設定と描画するものの移動を行っています。

次の2行は3Dオブジェクトの回転を行っています。
3Dでは行列を使って描画する物体の移動や回転を行います。
行列については詳しくは高校数学を参照してみてください。
またゲームプログラムのための3Dの書籍に乗っているのでそちらを参考にしてみください。

最後の1行については、ここで画面に四角描画しています。
でわ最後のソースの四角の描画について見てみましょう。


package com.example.opengl_test;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class MyCube {
private final FloatBuffer mVertexBuffer;

public MyCube() {

float vertices[] = {
// 前
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,

// 後
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,

// 左
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,

// 右
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,

// 上
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,

// 底
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f };

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);

}

public void draw(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);

// Front
gl.glNormal3f(0, 0, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

// Back
gl.glNormal3f(0, 0, -1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

// Left
gl.glNormal3f(-1.0f, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);

// Right
gl.glNormal3f(1.0f, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

// Top
gl.glNormal3f(0, 1.0f, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);

// Right
gl.glNormal3f(0, -1.0f, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
}
}


まずコンストラクタから見て行きましょう。
ここでは3Dの描画の座標を設定しています。
3Dは基本的にはすべて三角形で描画されます。
このことを考慮した上でソースを見て行きましょう。

3Dでは座標は(x,y,z)の3つの位置情報を指定します。
今回のソースでは四点ごとに分けてあります。
それぞれ四角形の四頂点を指定しています。
またOpenGLでは頂点情報をバッファクラスに詰めて使用します。

次はdrawメソッドを見て行きましょう
ここでは実際に頂点情報を使用して四角形を順番に描画しています。
最初の一行目では頂点配列を描画するという設定を行い、
次の一行で設定した頂点情報を渡します。
その後各四角形を描画します。

四角形を描画する二行一組については以下の様な設定を行います。
glNormal3fメソッドは光を反射する方向を指定しています。
次のglDrawArraysメソッドは頂点情報を使用して三角形を二枚描画します。
描画まず頂点情報のはじめの3つの頂点を使用し三角形を一枚描画します。
その後2番目、3番目、4番目を使用してい一枚描画します。
こうして4つの頂点情報で四角形を一枚描画ができます。
このようにして3Dの正方形が描画できます。

今回はAndroidでのOpenGLの描画の内容について説明してきました。
今後はこれらを利用してゲームの作り方的なものをかけていけたらと思いますの。

今回は、ここまで!