CHƯƠNG I .
TỔNG QUAN VỀ THỰC TẠI ẢO VÀ 3D ANIMATION TRONG THỰC
TẠI ẢO .
1.1. Tổng quan về thực tại ảo
1.1.1. Sơ lược lịch sử phát triển .
1.1.2. Các lĩnh vực ứng dụng của Thực tại ảo.
1.2 Hành động của nhân vật (3D Animation) trong thực tại ảo.
1.2.1. Animation trong thực tại ảo là gì? .
1.2.2. Hiệu ứng Animation trong thực tại ảo
1.2.3. Cơ sở mô phỏng 3D Animation.
1.2.4. Các vấn đề gặp phải trong quá trình nghiên cứu
1.2.5. Hướng giải quyết
CHƯƠNG II
KỸ THUẬT MÔ PHỎNG
2.1. Đặt vấn đề .
2.2. Kỹ thuật mô phỏng
2.2.1 Khởi tạo nhân vật và trang phục
2.2.2 Điều khiển mô phỏng các trạng thái hành động của nhân vật
2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển.
CHƯƠNG III .
CHƯƠNG TRÌNH MÔ PHỎNG.
3.1. Bài toán
3.2. Mục đích và yêu cầu bài toán
3.3. Phương pháp giải quyết bài toán .
3.4 Một số kết quả bài toán
77 trang |
Chia sẻ: lvcdongnoi | Lượt xem: 2751 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Mô phỏng hành động nhân vật trong xây dựng mô hình 3d, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
r::set_animation_sequence(char *sequence_name, int
transition_duration)
{
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
DWORD sequence = Morfit_3D_sequence_get_using_name(anim3d,
sequence_name);
if(sequence == NULL)
return(NULL);
Morfit_object_set_3D_sequence(m_player_object, sequence,
transition_duration);
return(sequence);
}
e. Hàm lựa chọn trình tự cho nhân vật
Việc lựa chọn trình tự cho nhân vật được thực hiện khi ta thiết lập các
trình tự đã có như trình tự đi bộ, trình tự tấn công bị thương, trình tự đứng,…Với
mỗi trình tự sẽ được gắn một số id (m_sequence_id_num) vì vậy mà sẽ rất dễ
dàng cho việc lựa chọn, quản lý các trình tự.
Ở đây chúng ta sẽ cố gắng giữ m_sequence_id_num được cập nhập nhưng
trong một số trường hợp thì không thể. Ví dụ nếu trình tự hiện tại
(m_current_sequence) là trình tự tấn công (m_attack_sequence) và sẽ được phép
làm như sau:
Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_object,
m_stand_sequence,300);
Trong trường hợp không biết chính xác thì trình đứng sẽ trở thành trình tự
hiện tại. Vì vậy mà ở đây sẽ truy vấn tới trình tự hiện tại và sẽ cập nhập
m_sequence_id_num và m_current_sequence phù hợp. Để hiểu rõ ý này xem
đoạn mã sau:
30
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(sequence == m_stand_sequence)
{
m_sequence_id_num = STAND;
m_current_sequence = m_stand_sequence;
}
else
{
if(sequence == m_walk_sequence)
m_sequence_id_num = WALK;
m_current_sequence = m_walk_sequence;
}
Chú ý điều quan trọng là khi chúng ta thiết lập một trình tự riêng biệt
(specific sequence) thì đầu tiên sẽ thiết lập một trạng thái trình tự hành động
và chỉ sau khi trình tự trạng thái hành động kết thúc thì nó sẽ tự động thiết lập
trình tự muốn có. Có nghĩa là nếu muốn tạo trình tự đi bộ (walk_sequence) ta
sẽ gọi hàm
Morfit_object_set_3D_sequence(m_player_object,walk_sequence);
Và ngay sau đó gọi hàm :
sequence=Morfit_object_get_3D_sequence(m_player_object);
thì kết quả trình tự trả về sẽ nhận được không phải là trình tự đi bộ
(sequence!=walk_sequence !!!). Chỉ sau khi trình tự trạng thái hành động kết
thúc thì trình tự walk_sequence mới được sử dụng.
Sau đây là đoạn mã của quá trình lựa chọn một trình tự:
void player::select_sequence()
{
DWORD sequence =
Morfit_object_get_3D_sequence(m_player_object);
if(sequence == m_stand_sequence)
{
31
m_sequence_id_num = STAND;
m_current_sequence = m_stand_sequence;
}
else
{
if(sequence == m_walk_sequence)
m_sequence_id_num = WALK;
m_current_sequence = m_walk_sequence;
}
if( (sequence == m_walk_sequence) && (m_speed < m_min_speed
&& m_speed > -m_min_speed))
{
m_current_sequence =
set_animation_sequence("stand",100);
m_sequence_id_num = STAND;
}
else if((sequence == m_stand_sequence) && (m_speed >=
m_min_speed || m_speed <= -m_min_speed))
{
m_current_sequence =
set_animation_sequence("walk",100);
m_sequence_id_num = WALK;
}
else if((sequence == m_fall_sequence) && (m_speed <
m_min_speed && m_speed > -m_min_speed))
{
//kiểm tra trình tự ngã (fall_sequence) đã kết thúc hay chưa
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
32
DWORD fall_sequence = Morfit_3D_sequence_get_using_name(anim3d,
"death");
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(fall_sequence);
double current_position =
Morfit_3D_sequence_get_current_frame(fall_sequence);
if(current_position >= num_of_frames - 2)
{
m_current_sequence =
set_animation_sequence("stand",1000);
m_sequence_id_num = STAND;
}
}
if(m_sequence_id_num!=FALL)
{
//thiết lập một trình tự đúng
if(m_speed<0 )
{
Morfit_3D_sequence_backwards_play(m_current_sequence,YES);
}
else
{
Morfit_3D_sequence_backwards_play(m_current_sequence,NO);
}
}
set_sequence_speed();
}
33
f. Hàm di chuyển trạng thái hành động của nhân vật
Di chuyển trạng thái hành động của nhân vật là việc thực hiện các thao tác
điều khiển cho nhân vật thực hiện một hành động để chuyển từ vị trí này sang vị
trí khác như tiến lên trước, lùi về phía sau, sang phải, sang trái…
Để thực hiện việc di chuyển cho nhân vật trước tiên phải xác định vị trí
mà nhân vật cần đi tới. Việc này được thực hiện một cách dễ dàng qua hàm :
Morfit_object_get_location(m_player_object,&save_location[0],
&save_location[1], &save_location[2]);
Sau đó sẽ tạo một trình tự cho nhân vật qua hàm:
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
Có nghĩa là giả sử m_sequence_id_num==WALK là một trình tự đi bộ
hoặc là một vài trình tự vận chuyển ban đầu của trình tự đi bộ, nếu ta có thể thay
thế sequence==m_walk_sequence thì nó sẽ không thể bắt kịp sự chuyển vận từ
trạng thái đứng sang trạng thái đi bộ được. Nên nhớ rằng trình tự vận chuyển đã
được phát sinh một cách tự động bởi các engine vì vậy mà việc chuyển đổi từ
một trình tự này sang một trình tự khác được thực hiện một cách mềm mại và
nhịp nhàng. Nếu không muốn trình tự vận chuyển phát sinh một cách tự động thì
đơn giản có thể gọi hàm sau :
Morfit_object_set_3D_sequence( ,0);
Trong đó với 0 là khoảng thời gian tồn tại cho sự vận chuyển.
Cũng như vậy trong quá trình di chuyển phải xác định lực đã sử dụng hay
chính xác hơn chính là lực tác dụng vào nhân vật, vì vậy mà biến int
muscle_force_used = NO; được khai báo có ý nghĩa ban đầu là chưa có lực nào
tác dụng. Như đã nói ở trên thì tốc độ của nhân vật phụ thuộc vào các thành phần
lực vì vậy mà dựa vào đó mà có thể thấy rõ sự nhanh hay chậm của nhân vật
trong từng trình tự trạng thái chuyển động.
Sau đây là một đoạn chương trình mô phỏng việc dịch chuyển tiến phía
trước, lùi phía sau, sang trái, sang phải của nhân vật:
void player::move(void)
{
34
int muscle_force_used = NO; // ko có lực tác dụng
double save_location[3];
//Xác định vị trí nhân vật cần di chuyển tới
Morfit_object_get_location(m_player_object, &save_location[0],
&save_location[1], &save_location[2]);
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(m_sequence_id_num == WALK || sequence == m_stand_sequence)
{
//tiến phía trước
if(GetAsyncKeyState(VK_UP) < 0)
{
m_speed += m_acceleration;
muscle_force_used = YES;
}
//lùi phía sau
if(GetAsyncKeyState(VK_DOWN) < 0)
{
muscle_force_used = YES;
m_speed -= m_acceleration;
}
}
if(m_sequence_id_num == WALK || sequence ==
m_stand_sequence || sequence == m_attack_sequence || sequence ==
m_pain_sequence)
{
//sang trái
if(GetAsyncKeyState(VK_LEFT) < 0)
{
Morfit_object_rotate_z(m_player_object, 6, WORLD_SPACE);
}
35
//sang phải
if(GetAsyncKeyState(VK_RIGHT) < 0)
{
Morfit_object_rotate_z(m_player_object, -6, WORLD_SPACE);
}
}
// xác định vận tốc và lực đã sử dụng
double gravity_and_friction_factor = get_friction_and_gravity_factor();
if(muscle_force_used == NO || fabs(m_speed) > m_min_speed)
{
m_speed *= gravity_and_friction_factor;
if(muscle_force_used == YES)
if(fabs(m_speed) < fabs(m_min_speed))
m_speed = m_min_speed * m_speed / fabs(m_speed);
}
if(m_speed > m_max_speed)
m_speed = m_max_speed;
if(m_speed < -m_max_speed)
m_speed = -m_max_speed;
Morfit_object_move(m_player_object,OBJECT_SPACE, -m_speed,0,0);
// Lựa chọn trình tự đúng
select_sequence();
// Xác địn vùng nền dưới
double point_below[3];
get_polygon_below(point_below);
// Xác định một trạng thái mới
if(new_altitude > save_location[2] + m_height / 3)
{
36
Morfit_object_set_location(m_player_object,save_location[0],
save_location[1], save_location[2]);
m_speed = -m_speed * 0.5;
}
else
{
double location[3];
Morfit_object_get_location(m_player_object, &location[0],
&location[1], &location[2]);
Morfit_object_set_location(m_player_object, location[0],
location[1], new_altitude);
}
}
g. Một số trạng thái chuyển động của nhân vật
* Trạng thái tấn công (Attack)
Ở đây sẽ mô phỏng nhân vật trong tư thế dùng vũ khí tấn công một đối
tượng khác. Một trình tự tấn công thực tế được xây dựng từ rất nhiều các trình tự
tấn công khác. Như tấn công với súng, phóng đạn, bắn trúng mục tiêu với cùng
một điều khiển…Trong game thì nó rất dễ dàng có được các trạng thái riêng biệt
đối với các trình tự khác nhau. Có thể tham khảo đoạn mã sau để hiểu rõ hơn về
một trình tự trạng thái tấn công:
void player::attack(void)
{
if(m_attack_sequence==NULL)
return;
Morfit_object_set_3D_sequence(m_player_object,
m_attack_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_obj
ect, m_stand_sequence,300);
m_current_sequence=m_attack_sequence;
37
m_sequence_id_num=ATTACK;
}
* Trạng thái bị thương
Cũng giống như trạng thái tấn công thì trạng thái bị thương sẽ mô phỏng
khi nhân vật bị trúng đạn và nó cũng được tạo lên bằng hàng loạt các trình tự bị
thương khác như sẽ giảm tốc độ, có thể khụy xuống và hiện chỗ thương trúng
đạn tại vị trí đó. Và sau đây là đoạn mã mô phỏng trạng thái bị thương:
void player::pain(void)
{
if(m_pain_sequence==NULL)
return;
Morfit_object_set_3D_sequence(m_player_object,
m_pain_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_obj
ect, m_stand_sequence,400);
m_current_sequence=m_pain_sequence;
m_sequence_id_num=PAIN;
}
* Cập nhập theo một trạng thái hành động mới
Như đã nói khi một trạng thái được thay đổi thì các tham số hành động
một hành động của nhân vật sẽ thay đổi theo sao cho phù hợp với từng trình tự
mô phỏng hành động đó. Ở đây có thể “load” chúng khi mà cần tới những ảnh
mô phỏng đó trong khi các “engine” sẽ không đủ nhanh để “load” những ảnh đã
có sẵn trong bộ nhớ. Có thể theo dõi đoạn mã sau để thấy được sự thay đổi giữa
các trạng thái:
int player::update_according_to_new_animation(void)
{
char buff[MAX_PATH];
strcpy(buff,m_bitmap_path);
38
strcat(buff,"\\skin.bmp");
m_skin_bitmap = Morfit_bitmap_load(buff,-1);
strcpy(buff,m_bitmap_path);
strcat(buff,"\\pain.bmp");
m_pain_bitmap = Morfit_bitmap_load(buff,-1);
//Thiết lập trang phục
Morfit_object_set_bitmap(m_player_object, m_skin_bitmap);
// Thiết lập tham số theo tỉ lệ kích thước
set_parameters_according_to_scale();
m_current_sequence = set_animation_sequence("stand", 0);
m_sequence_id_num = STAND;
m_stand_sequence = m_current_sequence;
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
m_fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death");
if(m_fall_sequence != NULL)
{
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(m_fall_sequence);
//Dừng quá trình đang ngã trong một trạng thái riêng.
Morfit_3D_sequence_set_frame_duration(m_fall_sequence,
num_of_frames-2, 1000000);
Morfit_3D_sequence_set_speed(m_fall_sequence,0.5);
}
m_walk_sequence = Morfit_3D_sequence_get_using_name(anim3d, "walk");
if(m_walk_sequence == NULL)
return(VR_ERROR);
m_attack_sequence =
Morfit_3D_sequence_get_using_name(anim3d, "attak");
m_pain_sequence = Morfit_3D_sequence_get_using_name(anim3d, "pain");
return(OK);
}
39
2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển.
a. Các vấn đề liên quan tới camera.
Camera là thành phần vô cùng quan trọng trong kĩ thuật mô phỏng vì nó
quyết định tới góc nhìn, khoảng cách nhìn, không gian nhìn đối với các đối tượng
trong không gian thới giới ảo. Việc liên kết giữa camera và đối tượng sẽ làm cho
quá trình mô phỏng sẽ được linh động hơn, mềm mại và chân thật hơn đối với
người quan sát. Với mỗi chế độ camera khác nhau ta cũng có các hiệu ứng khác
nhau vì vậy mà sau đây là một số chế độ camera và hiệu ứng cơ bản về camera
đã sử dụng để mô phỏng nhân vật trong đề tài này:
* Thiết lập camera ở chế độ chase_flexible
Ở chế độ này camera sẽ di chuyển mềm mại, uyển chuyển theo đối tượng
mà nó bám theo. Chúng ta có thể thiết lập kiểu theo cho đối tượng bằng hàm:
STATE_object_set_chase_type(Handle,chase_type)
Với kiểu theo là flexible, ta có thể thiết lập độ mềm dẻo của đường rẽ
bằng hàm STATE_object_set_chase_softness(object_handle,softness) và tương
tự có hàm lấy sự mềm dẻo hiện tại của đối tượng theo là:
STATE_object_get_chase_softness(object_handle). Giá trị softness nằm trong
khoảng [0-1].
Khoảng cách theo (chase offset): Chase offset xác định khoảng cách từ
đối tượng theo đến đối tượng bị theo. Ví dụ: char offset là [0,0,10] có nghĩa là
đối tượng theo sẽ theo đối tượng nhưng nó sẽ ở bên trên đối tượng cách đối
tượng 10 đơn vị.
Ta có thể thiết lập char offset bằng hàm sau:
STATE_object_set_chase_offset(object_handle,offset[3]).
Ta cũng có thể lấy char offset hiện tại của đối tượng bằng hàm sau:
STATE_object_get_chase_offset(object_handle,offset[3]).
Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ chase_flexible:
void camera::set_ chase_flexible_mode(void)
{
40
Morfit_camera_set_chase_type(m_camera_handle,
CHASE_FLEXIBLE);
double chase_offset[3] = {0,0,0};
Morfit_camera_set_chase_offset(m_camera_handle, chase_offset);
update_chase_params();
}
* Thiết lập camera ở chế độ chase_location
Cũng giống như ở chế độ chase_flexible nó cũng có nhiệm vụ bám theo
đối tượng và tính khoảng cách tới đối tượng xong có sự khác biệt ở đây là camera
sẽ không quay khi đối tượng bị theo quay. Sau đây là đoạn mã mô phỏng thiết
lập camera ở chế độ chase_location:
void camera::set_chase_location_mode(void)
{
Morfit_camera_set_chase_type(m_camera_handle,
CHASE_LOCATION);
double box[2][3];
Morfit_object_get_bounding_box(m_object_to_chase, box);
double height = box[1][2] - box[0][2];
double distance = height * 1.5 + 40;
// double scale[3];
// Morfit_object_get_scale(m_camera_handle, scale);
// double distance=scale[2]*100+100;
double direction[3];
Morfit_object_get_direction(m_object_to_chase,&direction[0],
&direction[1], &direction[2]);
Double chase_offset[3] = {-direction[0]*distance, -direction[1]*distance, 20};
41
Morfit_camera_set_chase_offset(m_camera_handle, chase_offset);
double location[3];Morfit_object_get_location(m_object_to_chase,
&location[0], &location[1], &location[2]);
Morfit_camera_point_at(m_camera_handle,location[0],location[1],
location[2]);
}
* Tạm dừng một chế độ camera (stop_chasing):
Việc tạm dừng một chế độ camera theo đối tượng được thực hiện một
cách đơn giản khi dùng hàm sau :
Morfit_camera_set_chase_type(m_camera_handle, NO_CHASE);
* Thiết lập camera ở chế độ zoom_in và zoom_out:
Thiết lập camera ở chế độ zoom_out là quá trình di chuyển camera ra xa
từ đối tượng bị theo. Chú ý rằng ở đây không phải là một zoom_out thực sư, để
tạo một zoom_out thực sự thì có thể sự dụng hàm sau:
Morfit_camera_set_field_of_view()
Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ zoom_out:
void camera::zoom_out(void)
{
int chase_type = Morfit_camera_get_chase_type(m_camera_handle);
if(chase_type == CHASE_LOCATION)
{
// chase_distance không thích hợp ở chế độ CHASE_LOCATION
double chase_offset[3];
Morfit_camera_get_chase_offset(m_camera_handle, chase_offset);
chase_offset[0] *= 1.1;
chase_offset[1] *= 1.1;
chase_offset[2] *= 1.1;
Morfit_camera_set_chase_offset(m_camera_handle, chase_offset);
return;
42
}
if(chase_type == CHASE_FLEXIBLE)
{
double distance = Morfit_camera_get_chase_distance(m_camera_handle);
Morfit_camera_set_chase_distance(m_camera_handle,distance*1.1);
return;
}
}
Thiết lập camera ở chế độ zoom_in là quá trình đưa camera lại gần đối
tượng bị theo. Chú ý rằng ở đây cũng như chế độ zoom_out thì đây cũng không
phải là một chế độ zoom_in thực sự, để tạo một zoom_out thực sự thì có thể sự
dụng hàm sau: Morfit_camera_set_field_of_view()
Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ zoom_in:
void camera::zoom_in(void)
{
int chase_type = Morfit_camera_get_chase_type(m_camera_handle);
if(chase_type == CHASE_LOCATION)
{
// chase_distance không thích hợp ở chế độ CHASE_LOCATION
double chase_offset[3];
Morfit_camera_get_chase_offset(m_camera_handle, chase_offset);
chase_offset[0] *= 0.9;
chase_offset[1] *= 0.9;
chase_offset[2] *= 0.9;
Morfit_camera_set_chase_offset(m_camera_handle, chase_offset);
return;
}
if(chase_type == CHASE_FLEXIBLE)
{
43
double distance = Morfit_camera_get_chase_distance(m_camera_handle);
Morfit_camera_set_chase_distance(m_camera_handle,distance*0.9);
return;
}
}
b. Các vần đề liên quan tới các phím điều khiển.
Trong quá trình mô phỏng trạng thái hành động của nhân vật thì việc dùng
các phím điều khiển để thay đổi các tùy chọn, thiết lập hoặc điều khiển di chuyển
của nhân vật là rất cần thiết. Chính vì vậy để cho quá trình sử dụng chương trình
một cách dễ dàng mà trong chương trình đã thiết lập cài đặt sử dụng các phím
điều khiển tương ứng với các nhiệm vụ và tác dụng của nó như sau:
+ Phím “A” : Zoom out với camera.
+ Phím “Z” : Zoom in với camera
+ Phím “S” : Phóng to kích thước tương ứng với kích thước của nhân vật
+ Phím “X” : Thu nhỏ thước tương ứng với kích thước của nhân vật
+ Phím “W” : Thiết lập tỉ lệ kích thước mặc định
+ Phím “D” : Tỉ lệ kích thước theo trục X (tạo cho nhân vật “mập” lên)
+ Phím “C” : Tỉ lệ kích thước theo trục X (tạo cho nhân vật “gầy” xuống)
+ Phím “G” : Tỉ lệ kích thước theo trục Y (tạo cho nhân vật “rộng” lên)
+ Phím “B” : Tỉ lệ kích thước theo trục Y (tạo cho nhân vật “hẹp” xuống)
+ Phím “H” : Tỉ lệ kích thước theo trục Z (tạo cho nhân vật “cao” lên)
+ Phím “N” : Tỉ lệ kích thước theo trục Z (tạo cho nhân vật “Thấp” xuống)
+ Phím “F” : Không sử dụng chế độ full_screen (màn hình 800x600)
+ Phím “V” : Sử dụng chế độ full_screen (màn hình 800x600)
+ Phím “R” : Không sử dụng card đồ họa thiết lập cửa sổ mặc định
(240,180,400,400)
+ Phím “1” : Thiết lập camera ở chế độ chase_location
+ Phím “2” : Thiết lập camera ở chế độ chase_flexible
+ Phím “3” : Thiết lập camera ở chế độ stop_chasing
+ Phím “4” : Thiết lập nhân vật ở trạng thái tấn công (attack)
44
+ Phím “5” : Thiết lập nhân vật ở trạng thái tấn bị thương (pain)
+ Phím “6” : Thiết lập lại trang phục cho nhân vật (replace_skin)
+ Phím “7” : Thiết lập lại bề ngoài cho nhân vật (replace_shape)
+ Phím “F1” : Gọi một bảng HELP
Sau đây là toàn bộ mã chương trình đặt chế độ điều khiển tương ứng với
các phím như mô tả trên:
void settings(camera *camera1, player *player1, DWORD anim1,
DWORD anim2)
{
//Zoom out với camera
if(GetAsyncKeyState('A')<0)
{
camera1->zoom_out();
}
else if(GetAsyncKeyState('Z')<0) //Zoom in với camera
{
camera1->zoom_in();
}
int scale_flag = 0;
//Tỉ lệ kích thước tương ứng với kích thước của nhân vật
if( GetAsyncKeyState('S')<0 )
{
player1->scale(1.1, X_AXIS|Y_AXIS|Z_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('X')<0 )
{
player1->scale(0.9, X_AXIS|Y_AXIS|Z_AXIS);
scale_flag++;
}
45
else if(GetAsyncKeyState('W')<0) //Thiết lập tỉ lệ kích thước mặc định
{
player1->scale_default();
scale_flag++;
}
//Tỉ lệ kích thước theo trục X (tạo cho nhân vật mập lên)
if( GetAsyncKeyState('D')<0)
{
player1->scale(1.1, X_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('C')<0)
{
player1->scale(0.9, X_AXIS);
scale_flag++;
}
//Tỉ lệ kích thước nhân vật theo trục Y (tạo cho nhân vật “rộng lên”)
if( GetAsyncKeyState('G')<0)
{
player1->scale(1.1, Y_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('B')<0)
{
player1->scale(0.9, Y_AXIS);
scale_flag++;
}
// Tỉ lệ kích thước nhân vật theo trục Z (tạo cho nhân vật “cao lên”)
if( GetAsyncKeyState('H')<0)
{
46
player1->scale(1.1, Z_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('N')<0)
{
player1->scale(0.9, Z_AXIS);
scale_flag++;
}
if(scale_flag)
camera1->update_chase_params();
if( (GetAsyncKeyState('F')&1) && (GetAsyncKeyState('F')<0))
{
if(Morfit_3D_card_is_used() ==NO ||
Morfit_3D_card_is_full_screen_mode() == NO)
{
if(Morfit_3D_card_set_full_screen_mode(800,600) ==
VR_ERROR)
{
if(Morfit_3D_card_check_hardware_support() == YES)
{
MessageBox(NULL, "Failed to initialize your 3D card.\n This
sample only works with hardware rendering\nPlease check that you have a 3D
card and DirectX 6.1 and above\n","No 3D card", MB_OK);
}
}
}
}
else if((GetAsyncKeyState('V')&1) && (GetAsyncKeyState('V')<0))
{
47
if(Morfit_3D_card_is_used() == NO ||
Morfit_3D_card_is_full_screen_mode() == YES)
{
Morfit_engine_maximize_default_rendering_window();
if(Morfit_3D_card_set_window_mode() == VR_ERROR)
{
if(Morfit_3D_card_check_hardware_support() == YES)
{
MessageBox(NULL, "Failed to initialize your 3D card.\n This sample
only works with hardware rendering\nPlease check that you have a 3D card and
DirectX 6.1 and above\n","No 3D card", MB_OK);
}
}
}
}
else if((GetAsyncKeyState('R')&1)&& (GetAsyncKeyState('R')<0))
{
Morfit_3D_card_use(NO);
Morfit_engine_set_default_rendering_window_size(240,180,400,400);
}
if(GetAsyncKeyState('1')<0)
{
camera1->set_chase_location_mode();
}
else if(GetAsyncKeyState('2')<0)
{
camera1->set_chase_flexible_mode();
}
else if(GetAsyncKeyState('3')<0)
{
48
camera1->stop_chasing();
}
if(GetAsyncKeyState('4')<0)
{
player1->attack();
}
else if(GetAsyncKeyState('5')<0)
{
player1->pain();
}
if(GetAsyncKeyState('6')&1)
{
player1->replace_skin();
}
static int anim_toggle = 0;
if(GetAsyncKeyState('7')&1)
{ if(anim_toggle == 0)
{
player1->replace_shape(anim2,
"..\\..\\..\\..\\..\\Worlds\\player2");
anim_toggle = 1;
}
else
{
player1->replace_shape(anim1,
"..\\..\\..\\..\\..\\Worlds\\player1");
anim_toggle = 0;
}
}
if(GetAsyncKeyState(VK_F1)&1)
{
help_popup();
}
}
49
CHƯƠNG III
CHƯƠNG TRÌNH MÔ PHỎNG
3.1. Bài toán
Sau một thời gian tìm hiểu về Thực tại ảo và 3D animation trong Thực tại
ảo, tác giả xin đưa ra một ứng dụng nhỏ; xây dựng một số hiệu ứng cho nhân vật
trong môi trường thực tại ảo.
Bài toán tác giả đưa ra trong đồ án này là bài toán mô phỏng một số hiệu
ứng 3D animation trong môi trường thựct ại ảo.
3.2. Mục đích và yêu cầu bài toán.
Mục đích của bài toán: Từ bài toán trên ta nhận thấy mục đích của bài
toán bao gồm:
+Nhằm giới thiệu một phương pháp tiếp cận mới đối với 3D animation,
đó là phương pháp tiếp cận và xử lý dựa trên ảnh.
+ Nhằm giới thiệu một số thuật toán trong quá trình xây dựng các hiệu
ứng 3D animation.
+ Nhằm giới thiệu một hướng nghiên cứu và xây dựng mới về hiệu ứng
3D trong môi trường thực tại ảo, đó chính là hiệu ứng 3D animation.
Yêu cầu của bài toán: Từ mục đích của bài toán chúng ta nhận thấy
những yêu cầu của bài toán như sau:
+ Vì bài toán mang mục đích tìm hiểu và giới thiệu phương pháp xây dựng
mô phỏng hành động nhân vật trong môi trường thực tại ảo, vì vậy bài toán phải
mang tính điển hình rễ hiểu và đáp ứng được những mục đích mà bài toán đề ra.
+ Bài toán phải cho thấy được vai trò cũng như tầm quan trọng của việc mô
phỏng trong các hiệu ứng 3D animation nói riêng và trong môi trường thực tại ảo
nói chung.
+ Bài toán phải thể hiện được một số hiệu ứng cơ bản của các hành động
của nhân vật trong môi trường thực tại ảo.
3.3. Phương pháp giải quyết bài toán
Từ những yêu cầu và mục đích trên tác giả đề ra phương hướng giải quyêt
50
bài toán như sau:
Vì bài toán nhằm mục đích tìm hiểu về các hành động của nhân vật được
mô phỏng trong môi trường thực tại ảo. Vì vậy tác giả đi mô phỏng các hiệu ứng
mang tính đơn giả, dễ mô phỏng.
Kết hợp các ảnh của nhân vật để mô phỏng các hiệu ứng .
Ta sử dụng hai ngôn ngữ là Morfit 3D và Virsual C++ để mô phỏng và
điều khiển các hành động nhân vật.
3.4 Một số kết quả bài toán.
Các ảnh đầu vào:
Ảnh mặt trước và sau của skin và pain:
Các ảnh này được ghép vào các đa giác của khối hình nhân vật tạo từ 3dsmax.
Cửa sổ Help hiện ra để hướng dẫn khi bắt đầu chạy chương trình hoặc khi ấn F1
51
Hình nhân vật khi khởi động chương trình ở trạng thái đứng yên:
Một số hình ảnh về trạng thái tấn công, thương, lên dốc, xuống dốc của
nhân vật.
52
53
54
55
KẾT LUẬN
Sau một thời gian nghiên cứu, tìm hiểu thì đồ án đã hoàn thành và đạt
được một số kết quả như sau:
* Giới thiệu và tổng quan về thực tại ảo và 3D animation trong thực tại ảo.
* Giới thiệu cách thức để khởi tạo một đối tượng trong thực tại ảo.
* Giới thiệu một số thuật toán cơ bản trong quá trình điều khiển đố tượng.
* Giới thiệu một số trạng thái của đối tượng.
* Giới thiệu một số chế độ điều khiển camera và sự chuyển đổi giữa các
chế độ đó.
* Xây dựng một chương trình nhỏ mô phỏng hành động của nhân vật
với một số hiệu ứng 3D animation trong môi trường thực tại ảo với các trạng
thái cụ thể.
56
HƯỚNG PHÁT TRIỂN ĐỀ TÀI
Trong tương lai tác giả sẽ cố gắng phát triển theo hướng sâu hơn, với
quy mô lớn hơn và có tính thực tế cao hơn. Sẽ cố gắng hoàn thành và phát triển
một game với ứng dụng của việc mô phỏng các hành động nhân vật với nhiều
nhân vật và tương tác hơn với môi trường thế giới ảo.
57
PHỤ LỤC
// player.h
#ifndef PLAYER_H
#define PLAYER_H
#define ACCELERATION 4
#define MAX_SPEED 50
#define MIN_SPEED 2
#define STAND 0
#define WALK 1
#define FALL 2
#define ATTACK 3
#define PAIN 4
#define X_AXIS 1
#define Y_AXIS 2
#define Z_AXIS 4
//#include "Engine\\mrft_api.h"
#include
class player
{
public:
player();
virtual ~player();
int init(char *file_name, char *bitmap_path);
//di chuyen nhan vat
void move(void);
//ti le kich thuoc nhan vat theo cac truc x,y,x hoac co the ket hop giua cac truc
void scale(double factor, int axis);
//Thiet lap ti le kich thuoc mac dinh
void scale_default(void);
//trang thai tan cong
void attack(void);
//trang thai bi thuong
void pain(void);
//Lay lai trang phuc cho nhan vat,chinh la chuyen doi giua cac anh
void replace_skin(void);
//Lay lai hinh dang ban dau cho nhan vat
void replace_shape(DWORD new_3d_animation, char *bitmap_path);
DWORD m_player_object;
private:
58
double m_speed;
DWORD m_current_sequence;
int m_sequence_id_num;
DWORD m_walk_sequence, m_stand_sequence, m_fall_sequence,
m_attack_sequence, m_pain_sequence;
DWORD m_skin_bitmap, m_pain_bitmap;
double m_acceleration;
int m_effort; //su dung thiet lap nhip tho khi nhan vat dang dung
double m_friction;
double m_max_speed;
double m_min_speed;
int m_skin_id; // 0 khi su dung skin bitmap. 1 khi su dung pain bitmap
double m_height;
char m_bitmap_path[MAX_PATH];
//Tao cong thuc tinh luc ma sat va trong luc len nhan vat
double get_friction_and_gravity_factor(void);
DWORD set_animation_sequence(char *sequence_name, int
transition_duration);
//Thiet lap cac them so theo ti le kich thuoc
//Khi trang thai nhan vat thay doi thi cac thuoc tinh cung thay doi
void set_parameters_according_to_scale(void);
//Lua chon mot trinh tu dung de mo phong tai mot vi tri
//Nhu chuyen doi tu mot trang thai dang chay thanh trang thai dung
void select_sequence();
//Tao trinh tu tho khi nhan vat dang dung
double get_standing_sequence_speed(void);
//Thiet lap trinh tu toc do
void set_sequence_speed(void);
//lap lai hanh dong nhan vat theo moi thoi gian co the
int update_according_to_new_animation(void);
//Xac dinh mot diem duoi nen
DWORD get_polygon_below(double point_below[3]);
};
#endif // PLAYER_H
// camera.h
#ifndef CAMERA_H
#define CAMERA_H
//#include "mrft_api.h"
#include
59
class camera
{
public:
camera();
virtual ~camera();
int init(DWORD object_to_chase);
void move(void);
void zoom_out(void);
void zoom_in(void);
void set_chase_flexible_mode(void);
void set_chase_location_mode(void);
void stop_chasing(void);
void update_chase_params(void);
DWORD m_camera_handle;
private:
DWORD m_object_to_chase;
};
#endif // CAMERA_H
/ anim3d.cpp
//////////////////////////////////////////////////////////////////////
#include
#include
#include
//#include
#include "..\\..\\..\\..\\..\\Engine\\Include\\mrft_api.h"
#include "player.h"
#include "camera.h"
int init_stuff(player *player1, player *player2, camera *camera1, DWORD
*animation1, DWORD *animation2);
void settings(camera *camera1, player *player1, DWORD anim1, DWORD anim2);
void help_popup(void);
void set_vector(double vector[3], double x, double y, double z);
void main()
{
player player1, player2; //thu voi player 1
camera camera1;
DWORD animation1, animation2;
60
help_popup();
if(init_stuff(&player1,&player2, &camera1, &animation1,
&animation2)==VR_ERROR)
{
printf("Co loi trong khi thiet lap the gioi\nAn mot nut bat ki de thoat");
getch();
return;
}
while( (GetAsyncKeyState(VK_ESCAPE)&1) ==0 ) //GetAsyncKeyState() la
mot ham API cua WIN32 (not Morfit)
{
//Ham nay kiem tra xem nut Escape da duoc an chua
player1.move();
camera1.move();
Morfit_engine_render(NULL,camera1.m_camera_handle); //Dua 1 anh
toi camera va dat no vao cua so mo phong mac dinh
settings(&camera1, &player1, animation1, animation2); //scan keyboard
and thay doi global theo thiet lap
}
Morfit_engine_close();
}
void help_popup(void)
{
if(Morfit_3D_card_is_used() == YES &&
Morfit_3D_card_is_full_screen_mode() == YES)
return;
int file_size;
char *buff = (char *)Morfit_utilities_file_to_memory("help.txt", &file_size);
MessageBox(NULL,buff,"Help", MB_ICONINFORMATION);
Morfit_utilities_free_file_memory(buff);
}
//Thay doi thiet lap chuong trinh theo dau vao cua ban phim
void settings(camera *camera1, player *player1, DWORD anim1, DWORD anim2)
{
//Zoom out voi camera
if(GetAsyncKeyState('A')<0)
{
camera1->zoom_out();
}
61
else if(GetAsyncKeyState('Z')<0) //Zoom in voi camera
{
camera1->zoom_in();
}
int scale_flag = 0;
//Ti le kich thuoc tuong ung voi kich thuoc nhan vat
if( GetAsyncKeyState('S')<0 )
{
player1->scale(1.1, X_AXIS|Y_AXIS|Z_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('X')<0 )
{
player1->scale(0.9, X_AXIS|Y_AXIS|Z_AXIS);
scale_flag++;
}
else if(GetAsyncKeyState('W')<0) //Thiet lap ti le kich thuoc mac dinh
{
player1->scale_default();
scale_flag++;
}
//Ti le kich thuoc theo truc X(tao cho nhan vat map len hay gay xuong)
if( GetAsyncKeyState('D')<0)
{
player1->scale(1.1, X_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('C')<0)
{
player1->scale(0.9, X_AXIS);
scale_flag++;
}
//Ti le kich thuoc theo truc Y(tao cho nhan vat rong len hay hep di)
if( GetAsyncKeyState('G')<0)
{
player1->scale(1.1, Y_AXIS);
scale_flag++;
}
62
else if( GetAsyncKeyState('B')<0)
{
player1->scale(0.9, Y_AXIS);
scale_flag++;
}
//Ti le kich thuoc theo truc Z(tao cho nhan vat cao len hay thap xuong)
if( GetAsyncKeyState('H')<0)
{
player1->scale(1.1, Z_AXIS);
scale_flag++;
}
else if( GetAsyncKeyState('N')<0)
{
player1->scale(0.9, Z_AXIS);
scale_flag++;
}
if(scale_flag)
camera1->update_chase_params();
if( (GetAsyncKeyState('F')&1) && (GetAsyncKeyState('F')<0))
{
if(Morfit_3D_card_is_used() == NO ||
Morfit_3D_card_is_full_screen_mode() == NO)
{
if(Morfit_3D_card_set_full_screen_mode(800,600) == VR_ERROR)
{
if(Morfit_3D_card_check_hardware_support() == YES)
{
MessageBox(NULL, "Loi cai dat 3D card.\n \nVui long kiem tra 3D card
and DirectX 6.1 \n","No 3D card", MB_OK);
}
}
}
}
else if((GetAsyncKeyState('V')&1) && (GetAsyncKeyState('V')<0))
{
if(Morfit_3D_card_is_used() == NO ||
Morfit_3D_card_is_full_screen_mode() == YES)
{
63
Morfit_engine_maximize_default_rendering_window();
if(Morfit_3D_card_set_window_mode() == VR_ERROR)
{
if(Morfit_3D_card_check_hardware_support() == YES)
{
MessageBox(NULL, "Loi cai dat 3D card.\n \nVui
long kiem tra 3D card and DirectX 6.1 \n","No 3D card", MB_OK);
}
}
}
}
else if((GetAsyncKeyState('R')&1)&& (GetAsyncKeyState('R')<0))
{
Morfit_3D_card_use(NO);
Morfit_engine_set_default_rendering_window_size(240,180,400,400);
}
if(GetAsyncKeyState('1')<0)
{
camera1->set_chase_location_mode();
}
else if(GetAsyncKeyState('2')<0)
{
camera1->set_chase_flexible_mode();
}
else if(GetAsyncKeyState('3')<0)
{
camera1->stop_chasing();
}
if(GetAsyncKeyState('4')<0)
{
player1->attack();
}
else if(GetAsyncKeyState('5')<0)
{
player1->pain();
}
if(GetAsyncKeyState('6')&1)
64
{
player1->replace_skin();
}
static int anim_toggle = 0;
if(GetAsyncKeyState('7')&1)
{
if(anim_toggle == 0)
{
player1->replace_shape(anim2, "..\\..\\..\\..\\..\\Worlds\\player2");
anim_toggle = 1;
}
else
{
player1->replace_shape(anim1, "..\\..\\..\\..\\..\\Worlds\\player1");
anim_toggle = 0;
}
}
if(GetAsyncKeyState(VK_F1)&1)
{
help_popup();
}
}
int init_stuff(player *player1, player *player2, camera *camera1,DWORD
*animation1, DWORD *animation2)
{
//Morfit_3D_card_use(YES);
int rc = Morfit_engine_load_world("..\\..\\..\\..\\..\\worlds\\country.wld", NULL,
"..\\..\\..\\..\\..\\worlds\\bitmaps", USER_DEFINED_BEHAVIOR);
if(rc != OK)
return(VR_ERROR);
// Morfit_3D_sequence_duplicate()
if(player1->init("..\\..\\..\\..\\..\\Worlds\\player1\\player.md2",
"..\\..\\..\\..\\..\\Worlds\\player1") == VR_ERROR)
return(VR_ERROR);
if(player2->init("..\\..\\..\\..\\..\\Worlds\\player2\\player.md2",
"..\\..\\..\\..\\..\\Worlds\\player2") == VR_ERROR)
return(VR_ERROR);
*animation1 = Morfit_object_get_3D_animation(player1->m_player_object);
65
*animation2 = Morfit_object_get_3D_animation(player2->m_player_object);
//disable player2
Morfit_object_disable(player2->m_player_object);
//Xac dinh vi tri nhan vat
//Trong truong hop Z==10000 la vi itri cua nhan vat o duoi nen
//Sau do nhan vat se duoc dieu chinh toi mot vi tri tot hon.
Morfit_object_move(player1->m_player_object,OBJECT_SPACE, -
1000,0,10000);
if(camera1->init(player1->m_player_object) != OK)
return(VR_ERROR);
//Vai thiet lap voi cua so
//
//Cac hieu ung nay chi tren pm mo phong
Morfit_engine_set_picture_quality(640*480);
Morfit_engine_maximize_default_rendering_window();
Morfit_engine_set_default_rendering_window_title("Do an tot nghiep. Cac
phim dieu khien: F1, A,Z,X,S,W,1,2,3,4,5,6,7, V,F,R,D,C,H,N, ESC");
Morfit_engine_set_atmospheric_effect_intensity(0);
ShowCursor(FALSE);
if(Morfit_3D_card_set_window_mode() == VR_ERROR)
{
if(Morfit_3D_card_check_hardware_support() == YES)
{
MessageBox(NULL, "Failed to initialize your 3D card.\n This sample only
works with hardware rendering\nPlease check that you have a 3D card and DirectX 6.1
and above\n","No 3D card", MB_OK);
}
//Tao ra mot cua so nho cho pm mo phong
Morfit_engine_set_default_rendering_window_size(240,180,400,400);
}
Morfit_engine_hide_log_window();
return(OK);
}
//Ham tao vecto toa do
void set_vector(double vector[3], double x, double y, double z)
{
vector[0] = x;
vector[1] = y;
vector[2] = z;
66
}
// player.cpp
//
//////////////////////////////////////////////////////////////////////
#include
#include
#include "player.h"
#include "..\\..\\..\\..\\..\\Engine\\Include\\mrft_api.h"
//Ham tao vecto toa do
void set_vector(double vector[3], double x, double y, double z);
player::player()
{
}
player::~player()
{
}
int player::init(char *file_name, char *bitmap_path)
{
m_speed = 0;
m_friction = 0.8;
m_max_speed = 50;
m_min_speed = 2;
m_skin_id = 0;
m_player_object = Morfit_object_create_from_file(file_name);
if(m_player_object == NULL)
return(VR_ERROR);
double scale[3] = {3,3,3};
Morfit_object_set_scale(m_player_object, scale);
strcpy(m_bitmap_path, bitmap_path);
return(update_according_to_new_animation());
}
int player::update_according_to_new_animation(void)
{
//load chung khi can toi anh. engine se ko du de load cac anh da co san trong bo nho
char buff[MAX_PATH];
strcpy(buff,m_bitmap_path);
strcat(buff,"\\skin.bmp");
m_skin_bitmap = Morfit_bitmap_load(buff,-1);
strcpy(buff,m_bitmap_path);
67
strcat(buff,"\\pain.bmp");
m_pain_bitmap = Morfit_bitmap_load(buff,-1);
//thiet lap trang phuc
Morfit_object_set_bitmap(m_player_object, m_skin_bitmap);
set_parameters_according_to_scale();
m_current_sequence = set_animation_sequence("stand", 0);
m_sequence_id_num = STAND;
m_stand_sequence = m_current_sequence;
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
m_fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death");
if(m_fall_sequence != NULL)
{
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(m_fall_sequence);
//dung trinh tu nga trong mot trang thai rieng
Morfit_3D_sequence_set_frame_duration(m_fall_sequence,
num_of_frames-2, 1000000);
Morfit_3D_sequence_set_speed(m_fall_sequence,0.5); //times nhanh
hon 2 lan
}
m_walk_sequence = Morfit_3D_sequence_get_using_name(anim3d, "walk");
if(m_walk_sequence == NULL)
return(VR_ERROR);
m_attack_sequence = Morfit_3D_sequence_get_using_name(anim3d, "attak");
m_pain_sequence = Morfit_3D_sequence_get_using_name(anim3d, "pain");
return(OK);
}
//Thiet lap cac them so theo ti le kich thuoc
//Khi trang thai nhan vat thay doi thi cac thuoc tinh cung thay doi
void player::set_parameters_according_to_scale()
{
double scale[3];
Morfit_object_get_scale(m_player_object, scale);
m_acceleration = ACCELERATION * scale[2] / 5;
if(m_acceleration < ACCELERATION)
m_acceleration = ACCELERATION;
m_max_speed = MAX_SPEED * scale[2] / 3;
m_min_speed = MIN_SPEED * scale[2] / 3;
//thiet lap chieu cao
68
double box[2][3];
Morfit_object_get_bounding_box(m_player_object, box);
m_height = box[1][2] - box[0][2];
}
DWORD player::set_animation_sequence(char *sequence_name, int
transition_duration)
{
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
DWORD sequence = Morfit_3D_sequence_get_using_name(anim3d,
sequence_name);
if(sequence == NULL)
return(NULL);
Morfit_object_set_3D_sequence(m_player_object, sequence,
transition_duration);
return(sequence);
}
void player::move(void)
{
int muscle_force_used = NO;
double save_location[3];
//ghi lai vi tri trong truong hop nhan vat muon toi.
Morfit_object_get_location(m_player_object, &save_location[0],
&save_location[1], &save_location[2]);
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(m_sequence_id_num == WALK || sequence == m_stand_sequence)
{
//tien phia truoc
if(GetAsyncKeyState(VK_UP) < 0)
{
m_speed += m_acceleration;
muscle_force_used = YES;
}
//lui phia sau
if(GetAsyncKeyState(VK_DOWN) < 0)
{
muscle_force_used = YES;
m_speed -= m_acceleration;
}
}
69
if(m_sequence_id_num == WALK || sequence == m_stand_sequence || sequence
== m_attack_sequence || sequence == m_pain_sequence)
{
//sang trai
if(GetAsyncKeyState(VK_LEFT) < 0)
{
Morfit_object_rotate_z(m_player_object, 6, WORLD_SPACE);
}
//sang phai
if(GetAsyncKeyState(VK_RIGHT) < 0)
{
Morfit_object_rotate_z(m_player_object, -6, WORLD_SPACE);
}
}
double gravity_and_friction_factor = get_friction_and_gravity_factor();
if(muscle_force_used == NO || fabs(m_speed) > m_min_speed)
{
m_speed *= gravity_and_friction_factor;
if(muscle_force_used == YES)
if(fabs(m_speed) < fabs(m_min_speed))
m_speed = m_min_speed * m_speed / fabs(m_speed);
}
if(m_speed > m_max_speed)
m_speed = m_max_speed;
if(m_speed < -m_max_speed)
m_speed = -m_max_speed;
Morfit_object_move(m_player_object,OBJECT_SPACE, -m_speed,0,0);
select_sequence();
// xac dinh mot diem duoi cung nen
double point_below[3];
get_polygon_below(point_below);
//chieu cao giua cua nhan vat co the la chieu cao len + chieu cao than tinh
// tu giua xuong duoi (m_height/2)
double new_altitude = point_below[2] + m_height / 2;
if(new_altitude > save_location[2] + m_height / 3)
{
Morfit_object_set_location(m_player_object, save_location[0],
save_location[1], save_location[2]);
70
m_speed = -m_speed * 0.5;
}
else
{
double location[3];
Morfit_object_get_location(m_player_object, &location[0],
&location[1], &location[2]);
Morfit_object_set_location(m_player_object, location[0], location[1],
new_altitude);
}
}
double player::get_friction_and_gravity_factor()
{
//cong thuc tinh trong luc
// player_mass*earth_gravity*sin(alpha)
double plane[4];
double point_below[3];
DWORD polygon = get_polygon_below(point_below);
if(polygon==NULL)
return(m_friction);
Morfit_polygon_get_plane(polygon, plane);
double gravity_direction[3];
double z_vector[3] = {0,0,1};
Morfit_math_cross(plane, z_vector, gravity_direction);
Morfit_math_cross( plane, gravity_direction, gravity_direction);
Morfit_math_normalize_vector(gravity_direction);
if(plane[2] 1)
return(m_friction); //khong co gi xay ra
double cos_alpha = plane[2];
double alpha = acos(cos_alpha);
double gravity_force = sin(alpha); //m*g*sin(alpha) . m*g==80. m==mass.
g==earth gravity
double direction[3];
Morfit_object_get_direction(m_player_object, &direction[0], &direction[1],
&direction[2]);
double gravity_factor = Morfit_math_product(gravity_direction, direction);
if(m_speed < 0)
gravity_factor = -gravity_factor;
71
//nhan vat nga xuong khi toc do qua cao hoac luc tac dung qua lon
if((m_sequence_id_num != FALL) && (gravity_factor * gravity_force > 0.3)
&& (fabs(m_speed) > 0.8 * m_max_speed))
{
m_current_sequence = set_animation_sequence("death",300);
m_sequence_id_num = FALL;
}
double result = m_friction+gravity_factor * gravity_force;
if(result < 0)
result = 0;
return(result);
}
void player::select_sequence()
{
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(sequence == m_stand_sequence)
{
m_sequence_id_num = STAND;
m_current_sequence = m_stand_sequence;
}
else
{
if(sequence == m_walk_sequence)
m_sequence_id_num = WALK;
m_current_sequence = m_walk_sequence;
}
// chi mot trinh tu ket thuc thi trinh tu khac moi duoc bat dau
// trinh tu van chuyen duoc tao ra tu dong
if( (sequence == m_walk_sequence) && (m_speed < m_min_speed &&
m_speed > -m_min_speed))
{
m_current_sequence = set_animation_sequence("stand",100);
m_sequence_id_num = STAND;
}
else if((sequence == m_stand_sequence) && (m_speed >= m_min_speed ||
m_speed <= -m_min_speed))
{
m_current_sequence = set_animation_sequence("walk",100);
m_sequence_id_num = WALK;
72
}
else if((sequence == m_fall_sequence) && (m_speed < m_min_speed &&
m_speed > -m_min_speed))
{
//kiem tra trinh tu nga da ket thuc hay chua
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
DWORD fall_sequence =
Morfit_3D_sequence_get_using_name(anim3d, "death");
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(fall_sequence);
double current_position =
Morfit_3D_sequence_get_current_frame(fall_sequence);
if(current_position >= num_of_frames - 2)
{
m_current_sequence = set_animation_sequence("stand",1000);
m_sequence_id_num = STAND;
}
}
if(m_sequence_id_num!=FALL)
{
//thiet lap mot trinh tu dung
if(m_speed<0 )
{
Morfit_3D_sequence_backwards_play(m_current_sequence,YES);
}
else
{
Morfit_3D_sequence_backwards_play(m_current_sequence,NO);
}
}
set_sequence_speed();
}
void player::set_sequence_speed()
{
double sequence_speed=1;
if(m_sequence_id_num==FALL || m_sequence_id_num==ATTACK ||
m_sequence_id_num==PAIN)
return;
73
if(m_sequence_id_num==STAND)
sequence_speed=get_standing_sequence_speed();
else
{
double abs_speed=m_speed;
if(abs_speed<0)
abs_speed=-abs_speed;
m_effort++;
//xay dung moi lien ket giua toc do va trinh tu toc do
// sequence_speed=F(player_speed);
//toc do nhan vat la 1 thi trinh tu toc do se la 0.7
//toc do nhan vat la to m_max_speed tthi trinh tu toc do se la 0.25
//thay doi cac thiet lap de nhin thay su thay doi cac hieu ung
double seq_speed1=0.7; //trinh tu toc do khi toc do nguoi choi la 1.
double seq_speed_max=0.35;
//trinh tu toc do khi toc do nguoi choi la m_max_speed.
//cap nhap toc do theo ti le kich thuoc nhan vat
double scale[3];
Morfit_object_get_scale(m_player_object, scale);
seq_speed1*=(1+scale[2]/200);
seq_speed_max*=(1+scale[2]/200);
//pt duong thang y=a*x+b
if((m_max_speed-1) <=0)
return; //bao dam de ko chia cho 0
double a=(seq_speed_max-seq_speed1)/(m_max_speed -1);
double b=seq_speed1-a;
sequence_speed=a*abs_speed+b;
if(sequence_speed<seq_speed_max)
sequence_speed=seq_speed_max;
}
Morfit_3D_sequence_set_speed(m_current_sequence, sequence_speed);
}
//Tao trinh tu tho khi nhan vat dang dung
double player::get_standing_sequence_speed()
{
//This formula gives tempo==0.1 when effort=0
//and tempo 0.1 when effort==400
double tempo=-(double)m_effort/400+0.8;
if(tempo<0.1)
74
tempo=0.1;
m_effort=m_effort-1;
if(m_effort<0)
m_effort=0;
if(m_effort>500)
m_effort=500;
return(tempo);
}
//Xac dinh vung duoi nen
DWORD player::get_polygon_below(double point_below[3])
{
double location[3];
Morfit_object_get_location(m_player_object, &location[0], &location[1],
&location[2]);
double up_location[3], down_location[3];
set_vector(up_location, location[0], location[1], 1000000);
set_vector(down_location, location[0], location[1], -1000000);
DWORD terrain_poly, blocking_object;
int flag=Morfit_object_is_movement_possible(m_player_object, up_location,
down_location, &terrain_poly, point_below, &blocking_object);
if(flag==YES)
{
printf("An error occurred, there is now ground below !!!\n");
return(NULL);
}
return(terrain_poly);
}
//Thiet lap ti le kich thuoc mac dinh
void player::scale_default(void)
{
double scale[3]={3,3,3};
Morfit_object_set_scale(m_player_object,scale);
set_parameters_according_to_scale();
}
//ti le kich thuoc nhan vat theo cac truc x,y,x hoac co the ket hop giua cac truc
void player::scale(double factor, int axis)
{
double scale[3];
75
Morfit_object_get_scale(m_player_object,scale);
if(axis & X_AXIS)
scale[0]*=factor;
if(axis & Y_AXIS)
scale[1]*=factor;
if(axis & Z_AXIS)
scale[2]*=factor;
Morfit_object_set_scale(m_player_object,scale);
set_parameters_according_to_scale();
}
//trang thai tan cong
void player::attack(void)
{
if(m_attack_sequence==NULL)
return;
//trinh tu tan cong duoc xay dung boi rat nhieu trang thai tan cong nhu cam
sung,ban....
Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_object,
m_stand_sequence,300);
m_current_sequence=m_attack_sequence;
m_sequence_id_num=ATTACK;
}
//trang thai bi thuong
void player::pain(void)
{
if(m_pain_sequence==NULL)
return;
Morfit_object_set_3D_sequence(m_player_object, m_pain_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_object,
m_stand_sequence,400);
m_current_sequence=m_pain_sequence;
m_sequence_id_num=PAIN;
}
//Lay lai trang phuc cho nhan vat,chinh la chuyen doi giua cac anh
void player::replace_skin(void)
{
if(m_skin_id==0)
{
76
Morfit_object_set_bitmap(m_player_object, m_pain_bitmap);
m_skin_id=1;
return;
}
Morfit_object_set_bitmap(m_player_object, m_skin_bitmap);
m_skin_id=0;
}
//Lay lai hinh dang ban dau cho nhan vat
void player::replace_shape(DWORD anim3d, char *bitmap_path)
{
Morfit_object_set_3D_animation(m_player_object, anim3d);
strcpy(m_bitmap_path, bitmap_path);
update_according_to_new_animation();
}
77
TÀI LIỆU THAM KHẢO
[1]. Nguyễn Văn Huân- Vũ Đức Thái, Kỹ thuật lập trình mô phỏng thế giới thực
dựa trên Morfit
[2]. Một số trang web như:
http:// www.3dnews.com
- The site for the Morfit VC++ developers, run by Bucky
(Brad Buchanan).
- Morfit Developer Mailing List
- The Morfit official mailing list.
http:// www.3dng.com - Morfit 3D for Euphoria Web Page. Run by Mark Brown.
- Morfit for Borland Builder C++ users.
- Beros 3D World - One of the most promising arcade
games under development. Visit to see screenshots and a demo.
- Morfit Projects - This page includes links
and information on different Morfit projects.
Các file đính kèm theo tài liệu này:
- Mô phỏng hành động nhân vật trong xây dựng mô hình 3d.pdf