Đồ án Mô phỏng hành động nhân vật trong xây dựng mô hình 3D

MỤC LỤC

MỤC LỤC . 1

LỜI GIỚI THIỆU . . 2

CHƯƠNG I . 3

TỔNG QUAN VỀ THỰC TẠI ẢO VÀ 3D ANIMATION TRONG THỰC

TẠI ẢO . 3

1.1. Tổng quan về thực tại ảo. 3

1.1.1. Sơ lược lịch sử phát triển . 3

1.1.2. Các lĩnh vực ứng dụng của Thực tại ảo. 4

1.2 Hành động của nhân vật (3D Animation) trong thựctại ảo. . 9

1.2.1. Animation trong thực tại ảo là gì? . 10

1.2.2. Hiệu ứng Animation trong thực tại ảo . . 10

1.2.3. Cơ sở mô phỏng 3D Animation . 11

1.2.4. Các vấn đề gặp phải trong quá trình nghiên cứu . . 13

1.2.5. Hướng giải quyết . 14

CHƯƠNG II. 15

KỸ THUẬT MÔ PHỎNG . . . 15

2.1. Đặt vấn đề . 15

2.2. Kỹ thuật mô phỏng . 15

2.2.1 Khởi tạo nhân vật và trang phục. . 15

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 . 23

2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển. . 39

CHƯƠNG III . . 49

CHƯƠNG TRÌNH MÔ PHỎNG . 49

3.1. Bài toán . 49

3.2. Mục đích và yêu cầu bài toán. . 49

3.3. Phương pháp giải quyết bài toán . 49

3.4 Một số kết quả bài toán. . 50

KẾT LUẬN . 55

HƯỚNG PHÁT TRIỂN ĐỀ TÀI. 56

PHỤ LỤC. . . 57

TÀI LIỆU THAM KHẢO . . . 77

pdf77 trang | Chia sẻ: netpro | Lượt xem: 1965 | Lượt tải: 5download
Bạn đang xem trước 20 trang tài liệu Đồ án 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
ng trục X, Y, Z (X_AXIS, Y_AXIS, Z_AXIS) hoặc có sự kết hợp của các trục khác (ví dụ: scale(1.1, X_AXIS+Y_AXIS)) void player::scale(double factor, int axis) { double scale[3]; 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(); } Ở đây factor là hệ số mà ta có thể tùy chọn theo điều kiện cần, do đó ta sẽ có được một nhân vật có kích thước phù hợp trong mọi trường hợp. + Hàm thiết lập tham số thay đổi theo tỉ lệ kích thước: 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; //set height 22 double box[2][3]; Morfit_object_get_bounding_box(m_player_object, box); m_height = box[1][2] - box[0][2]; } Khi tỉ lệ kích thước thay đổi thì các tham số thuộc tính của nhân vật như tốc độ, gia tốc, trang phục… cũng sẽ thay đổi theo. Ví dụ một nhân vật khi bị thu nhỏ lại thì nó sẽ di chuyển chậm hơn nhưng các bước chân sẽ nhanh hơn (ở đây ta nói tới tốc độ thực hiện một bước chân so với khi chưa thu nhỏ kích thước). Ở đây gia tốc được đặt giá trị là 4: #define ACCELERATION 4 b. Trang phục của nhân vật Trang phục là một phần không thể thiếu trong quá trình xây dựng nhân vật khi mô phỏng, nó quyết định và có tầm quan trọng để tạo lên tính cách, diện mạo, tính đồng bộ… của nhân vật đối với không gian thế giới. Vì vậy việc tạo và xây dựng trang phục cho nhân vật cũng là một phần đáng lưu ý của tác giả trong đề tài này. Trước tiên ta sẽ khai báo các biến liên quan đến trang phục: int m_skin_id; DWORD m_skin_bitmap, m_pain_bitmap; Biến m_skin_id có giá trị bằng 0 khi nhân vật có trang phục thường và có giá trị bằng 1 khi nhân vật trong tình trạng bị thương. m_skin_bitmap, m_pain_bitmap lần lượt là các biến khai báo các ảnh trang phục của nhân vật ở tình trạng bình thường và tình trạng bị thương. Việc thay đổi trang phục của nhân vật được hiểu chính là việc thay đổi các ảnh để có thể làm cho trang phục của nhân vật thay đổi như vậy khi đó nhân vật sẽ có một trang phục mới và ta có thể dễ dàng chuyển đổi từ trạng thái bình thường sang trạng thái bị thương và ngược lại mà ta có thể thấy rõ hơn qua đoạn mã sau: void player::replace_skin(void) { if(m_skin_id==0) 23 { 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; } 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 Điều khiển mô phỏng các trạng thái hành động của nhân vật là phần chính của đề tài này vì vậy mà tác giả sẽ đi sâu vào các hàm và đoạn mã mô phỏng. Việc xây dựng các trạng thái hành động của nhân vật phụ thuộc vào nhất nhiều các yếu tố như lực ma sát, trọng lực, hướng di chuyển, trình tự di chuyển...do đó dưới đây là các hàm xác định các yếu tố đó. a. Hàm xác định lực ma sát và trọng lực tác dụng lên nhân vật. Trước tiên ta phải hiểu rằng lực ma sát luôn luôn có tác dụng làm cản và làm giảm tốc độ chuyển động của một đối tượng trong môi trường của nó. Với mỗi môi trường và trọng lượng của đối tượng khác nhau mà lực ma sát tác dụng sẽ lớn hay nhỏ khác nhau. Ví dụ như một đối tượng chuyển động trên mặt nền đường nhựa nhẵn (có hệ số ma sát nhỏ) sẽ chuyển động nhanh hơn một đối tượng chuyển động trên mặt nền cát (có hệ số ma sát lớn). Như đã nói khối lượng (mà ở đây muốn nói tới chính là trọng lượng của nhân vật) là thành phần quan trọng trong công thức tính lực ma sát vì nó có liên quan tới trọng lực. Công thức tính lực trọng lực như sau : player_mass*earth_gravity*sin(alpha) Trong đó: + player_mass: Khối lượng của nhân vật (kí hiệu là m) + earth_gravity: Lực hút của trái đất (kí hiệu là g và thường có giá trị g=9,18) + alpha : Góc nghiêng của nhân vật đối với mặt ngang nền 24 Sau khi đã xác định được trọng lực thì việc tính toán lực ma sát được trở lên dễ dàng. Sau đây là công thức tính lực ma sát: gravity_factor * gravity_force Trong đó: + gravity_force : Trọng lực + gravity_factor: hệ số ma sát Sau đây là một hàm được xây dựng để xác định trọng lực và lực ma sát của nhân vật trong môi trường mô phỏng: double player::get_friction_and_gravity_factor() { double plane[4]; double point_below[3]; DWORD polygon = get_polygon_below(point_below); (3) if(polygon==NULL) return(m_friction); Morfit_polygon_get_plane(polygon, plane); (4) double gravity_direction[3]; double z_vector[3] = {0,0,1}; // quá trình xác định phương và hướng một véc tơ trọng lực (5) 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); //trả về ma sát của môi trường // tính trọng lực (6) double cos_alpha = plane[2]; double alpha = acos(cos_alpha); double gravity_force = sin(alpha); //m*g*sin(alpha) . // xác định hướng của nhân vật double direction[3]; 25 Morfit_object_get_direction(m_player_object,&direction[0], &direction[1], &direction[2]); // xác định hệ số ma sát (7) double gravity_factor = Morfit_math_product (gravity_direction, direction); if(m_speed < 0) gravity_factor = -gravity_factor; //Nhân vật sẽ ngã khi có một tốc độ quá lớn và chịu trọng lực quá lớn 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; } // tổng lực tác dụng nhân vật (8) double result = m_friction+gravity_factor * gravity_force; if(result < 0) result = 0; return(result); } Trong đó: + m_friction: biến toàn cục khai báo ma sát của môi trường tác động tới nhân vật (3) : Xác định một vùng nền bên dưới nơi mà chân của nhân vật sẽ di chuyển tới. (4): Xác định một vùng nền trên mặt nghiêng mà ta sẽ dựa vào đây để xác định. (5): Quá trình xác định một véc tơ chính của trọng lực (6): Quá trình tính trọng lực tác dụng lên nhân vật (7): Xác định hệ số ma sát (8): Tổng hợp các lực tác dụng lên nhân vật 26 Ghi chú: Khi nhân vật đang đứng trên bề mặt thì lực ma sát và hợp lực sẽ trả về giá trị m_friction (nhỏ hơn 1). Khi đang đi xuống đồi (một độ nghiêng) nó sẽ trả về giá trị lớn hơn (lớn hơn 1) vì vậy mà sẽ làm cho nhân vật chuyển động nhanh hơn. Khi đi lên đồi (một độ nghiêng) thì sẽ trả về một số nhỏ hơn m_friction vì vậy mà nhân vật sẽ di chuyển chậm lại. b. Hàm thiết lập trình tự tốc độ cho nhân vật Trình tự tốc độ nhân vật là trình tự vận tốc của nhân vật thực hiện trong một quãng đường trong một khoảng thời gian xác định. Ở đây ta sẽ đi thiết lập trình tự tốc độ trong một quãng đường (một đoạn đường) cụ thể và nó chính là việc nhân vật đã di chuyển trên một quãng đường thẳng. chính vì vậy mà phải xây dựng công thức liên kết giữa tốc độ của nhân vật và trình tự tốc độ. Ở đây chúng ta có thể hiểu là trình tự tốc độ sẽ tuyến tính với tốc độ của nhân vật theo một phương trình đường thẳng (sequence_speed=F(player_speed)) có dạng y = ax + b. Trong đề tài này tác giả sẽ xây dựng công thức tính khi tốc độ của nhân vật là 1 thì trình tự tốc độ sẽ là 0.7 và khi tốc độ của nhân vật là m_max_speed thì trình tự tốc độ sẽ là 0.25. Vì vậy mà khi thực hiên thay đổi các tùy chọn thì sẽ nhìn thấy sự thay đổi về hiệu ứng trạng thái hành động trong không gian của trình tự tốc độ như thế nào. Sự thay đổi của chính trình tự tốc độ sẽ làm cho một vài tham gia số của tỉ lệ kích thước nhân vật thay đổi. Như vậy việc thường xuyên cập nhật các tham số về tỉ lệ kích thước sẽ làm tăng thêm vẻ đẹp bề ngoài sự uyển chuyển của nhân vật. Morfit_3D_sequence_set_speed(m_current_sequence, sequence_speed); Là hàm được gọi để thiết lập cho trình tự nhân vật. Sau đây là đoạn chương trình thực hiện các mô tả thuật toán ở trên với việc thiết lập trình tự tốc độ cho nhân vật: void player::set_sequence_speed() { double sequence_speed=1; 27 if(m_sequence_id_num==FALL || m_sequence_id_num==ATTACK || m_sequence_id_num==PAIN) return; 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++; // tăng nhịp thở double seq_speed1=0.7; //trình tự khi nhân vật có tốc độ là 1. double seq_speed_max=0.35; // trình tự khi nhân vật có tốc độ là m_max_speed. //cập nhật tham số tỉ lệ kích thước nhân vật double scale[3]; Morfit_object_get_scale(m_player_object, scale); seq_speed1*=(1+scale[2]/200); seq_speed_max*=(1+scale[2]/200); //liên hệ giữa trình tự tốc độ và tốc độ theo pt đường thẳng if((m_max_speed-1) <=0) return; //trở lại khi 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; } 28 Morfit_3D_sequence_set_speed(m_current_sequence, sequence_speed); } c. Hàm tạo trình tự tốc độ khi nhân vật đang đứng Trình tự tốc độ khi nhân vật đang ở trạng thái đứng yên chính là việc mô phỏng nhịp thở của nhân vật. Ở đây thiết lập các giá trị sao cho nhịp độ âm thở (tempo) phù hợp với tần suất (effort). Việc tăng giảm tần suất của nhịp thở cũng kéo theo sự tăng giảm của âm độ nhịp thở. Trong trường hợp này sẽ đưa ra công thức như sau: tempo có giá trị là 0.1 (tempo==0.1) khi effort có giá trị 0 (effort=0) và tempo cũng đạt 0.1 khi effort==400. Sau đây là đoạn mã mô phỏng: double player::get_standing_sequence_speed() { double tempo=-(double)m_effort/400+0.8; if(tempo<0.1) tempo=0.1; m_effort=m_effort-1; if(m_effort<0) m_effort=0; if(m_effort>500) m_effort=500; return(tempo); } d. Hàm thiết lập trình tự trạng thái hành động Thiết lập trình tự trạng thái hành động cho nhân vật chính là việc lấy các tên trình tự đã được thiết lập để gán vào từng quá trình hành động của nhân vật. Có nghĩa là ta sẽ lấy mỗi hành động của nhân vật trong không gian thế giới và gán cho nó một cái tên tương ứng với đúng trình tự hành động của nó. Để hiểu rõ hơn có thể xem đoạn mã sau: 29 WORD 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); } 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_off

Các file đính kèm theo tài liệu này:

  • pdfMô phỏng hành động nhân vật trong xây dựng mô hình 3d.pdf